From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Fri, 1 Nov 2019 10:33:04 -0500 Subject: [PATCH] libmultipath: fix sgio_get_vpd looping If do_inq returns a page with a length that is less than maxlen, but larger than DEFAULT_SGIO_LEN, this function will loop forever. Also if do_inq returns with a length equal to or greater than maxlen, sgio_get_vpd will exit immediately, even if it hasn't read the entire page. Fix these issues, modify the tests to verify the new behavior. Signed-off-by: Benjamin Marzinski --- libmultipath/discovery.c | 12 +++--- tests/vpd.c | 84 ++++++++++++++++++++++++---------------- 2 files changed, 57 insertions(+), 39 deletions(-) diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c index 72f455e8..3c72a80a 100644 --- a/libmultipath/discovery.c +++ b/libmultipath/discovery.c @@ -870,6 +870,7 @@ static int sgio_get_vpd (unsigned char * buff, int maxlen, int fd, int pg) { int len = DEFAULT_SGIO_LEN; + int rlen; if (fd < 0) { errno = EBADF; @@ -877,12 +878,11 @@ sgio_get_vpd (unsigned char * buff, int maxlen, int fd, int pg) } retry: if (0 == do_inq(fd, 0, 1, pg, buff, len)) { - len = get_unaligned_be16(&buff[2]) + 4; - if (len >= maxlen) - return len; - if (len > DEFAULT_SGIO_LEN) - goto retry; - return len; + rlen = get_unaligned_be16(&buff[2]) + 4; + if (rlen <= len || len >= maxlen) + return rlen; + len = (rlen < maxlen)? rlen : maxlen; + goto retry; } return -1; } diff --git a/tests/vpd.c b/tests/vpd.c index d9f80eaa..4dbce010 100644 --- a/tests/vpd.c +++ b/tests/vpd.c @@ -306,7 +306,7 @@ static int create_vpd83(unsigned char *buf, size_t bufsiz, const char *id, default: break; } - put_unaligned_be16(n, buf + 2); + put_unaligned_be16(bufsiz, buf + 2); return n + 4; } @@ -429,6 +429,8 @@ static void test_vpd_vnd_ ## len ## _ ## wlen(void **state) \ free(exp_wwid); \ will_return(__wrap_ioctl, n); \ will_return(__wrap_ioctl, vt->vpdbuf); \ + will_return(__wrap_ioctl, n); \ + will_return(__wrap_ioctl, vt->vpdbuf); \ ret = get_vpd_sgio(10, 0x83, vt->wwid, wlen); \ assert_correct_wwid("test_vpd_vnd_" #len "_" #wlen, \ exp_len, ret, '1', 0, false, \ @@ -459,6 +461,8 @@ static void test_vpd_str_ ## typ ## _ ## len ## _ ## wlen(void **state) \ exp_len = wlen - 1; \ will_return(__wrap_ioctl, n); \ will_return(__wrap_ioctl, vt->vpdbuf); \ + will_return(__wrap_ioctl, n); \ + will_return(__wrap_ioctl, vt->vpdbuf); \ ret = get_vpd_sgio(10, 0x83, vt->wwid, wlen); \ assert_correct_wwid("test_vpd_str_" #typ "_" #len "_" #wlen, \ exp_len, ret, byte0[type], 0, \ @@ -496,6 +500,8 @@ static void test_vpd_naa_ ## naa ## _ ## wlen(void **state) \ 3, naa, 0); \ will_return(__wrap_ioctl, n); \ will_return(__wrap_ioctl, vt->vpdbuf); \ + will_return(__wrap_ioctl, n); \ + will_return(__wrap_ioctl, vt->vpdbuf); \ ret = get_vpd_sgio(10, 0x83, vt->wwid, wlen); \ assert_correct_wwid("test_vpd_naa_" #naa "_" #wlen, \ exp_len, ret, '3', '0' + naa, true, \ @@ -506,22 +512,26 @@ static void test_vpd_naa_ ## naa ## _ ## wlen(void **state) \ * test_vpd_eui_LEN_WLEN() - test code for VPD 83, EUI64 * @LEN: EUI64 length (8, 12, or 16) * @WLEN: WWID buffer size + * @SML: Use small VPD page size */ -#define make_test_vpd_eui(len, wlen) \ -static void test_vpd_eui_ ## len ## _ ## wlen(void **state) \ +#define make_test_vpd_eui(len, wlen, sml) \ +static void test_vpd_eui_ ## len ## _ ## wlen ## _ ## sml(void **state) \ { \ struct vpdtest *vt = *state; \ int n, ret; \ /* returned size is always uneven */ \ int exp_len = wlen > 2 * len + 1 ? 2 * len + 1 : \ wlen % 2 == 0 ? wlen - 1 : wlen - 2; \ + int bufsize = sml ? 255 : sizeof(vt->vpdbuf); \ \ - n = create_vpd83(vt->vpdbuf, sizeof(vt->vpdbuf), test_id, \ + n = create_vpd83(vt->vpdbuf, bufsize, test_id, \ 2, 0, len); \ will_return(__wrap_ioctl, n); \ will_return(__wrap_ioctl, vt->vpdbuf); \ + will_return(__wrap_ioctl, n); \ + will_return(__wrap_ioctl, vt->vpdbuf); \ ret = get_vpd_sgio(10, 0x83, vt->wwid, wlen); \ - assert_correct_wwid("test_vpd_eui_" #len "_" #wlen, \ + assert_correct_wwid("test_vpd_eui_" #len "_" #wlen "_" #sml, \ exp_len, ret, '2', 0, true, \ test_id, vt->wwid); \ } @@ -603,25 +613,30 @@ make_test_vpd_vnd(20, 10); make_test_vpd_vnd(10, 10); /* EUI64 tests */ +/* small vpd page test */ +make_test_vpd_eui(8, 32, 1); +make_test_vpd_eui(12, 32, 1); +make_test_vpd_eui(16, 40, 1); + /* 64bit, WWID size: 18 */ -make_test_vpd_eui(8, 32); -make_test_vpd_eui(8, 18); -make_test_vpd_eui(8, 17); -make_test_vpd_eui(8, 16); -make_test_vpd_eui(8, 10); +make_test_vpd_eui(8, 32, 0); +make_test_vpd_eui(8, 18, 0); +make_test_vpd_eui(8, 17, 0); +make_test_vpd_eui(8, 16, 0); +make_test_vpd_eui(8, 10, 0); /* 96 bit, WWID size: 26 */ -make_test_vpd_eui(12, 32); -make_test_vpd_eui(12, 26); -make_test_vpd_eui(12, 25); -make_test_vpd_eui(12, 20); -make_test_vpd_eui(12, 10); +make_test_vpd_eui(12, 32, 0); +make_test_vpd_eui(12, 26, 0); +make_test_vpd_eui(12, 25, 0); +make_test_vpd_eui(12, 20, 0); +make_test_vpd_eui(12, 10, 0); /* 128 bit, WWID size: 34 */ -make_test_vpd_eui(16, 40); -make_test_vpd_eui(16, 34); -make_test_vpd_eui(16, 33); -make_test_vpd_eui(16, 20); +make_test_vpd_eui(16, 40, 0); +make_test_vpd_eui(16, 34, 0); +make_test_vpd_eui(16, 33, 0); +make_test_vpd_eui(16, 20, 0); /* NAA IEEE registered extended (36), WWID size: 34 */ make_test_vpd_naa(6, 40); @@ -722,20 +737,23 @@ static int test_vpd(void) cmocka_unit_test(test_vpd_vnd_19_20), cmocka_unit_test(test_vpd_vnd_20_10), cmocka_unit_test(test_vpd_vnd_10_10), - cmocka_unit_test(test_vpd_eui_8_32), - cmocka_unit_test(test_vpd_eui_8_18), - cmocka_unit_test(test_vpd_eui_8_17), - cmocka_unit_test(test_vpd_eui_8_16), - cmocka_unit_test(test_vpd_eui_8_10), - cmocka_unit_test(test_vpd_eui_12_32), - cmocka_unit_test(test_vpd_eui_12_26), - cmocka_unit_test(test_vpd_eui_12_25), - cmocka_unit_test(test_vpd_eui_12_20), - cmocka_unit_test(test_vpd_eui_12_10), - cmocka_unit_test(test_vpd_eui_16_40), - cmocka_unit_test(test_vpd_eui_16_34), - cmocka_unit_test(test_vpd_eui_16_33), - cmocka_unit_test(test_vpd_eui_16_20), + cmocka_unit_test(test_vpd_eui_8_32_1), + cmocka_unit_test(test_vpd_eui_12_32_1), + cmocka_unit_test(test_vpd_eui_16_40_1), + cmocka_unit_test(test_vpd_eui_8_32_0), + cmocka_unit_test(test_vpd_eui_8_18_0), + cmocka_unit_test(test_vpd_eui_8_17_0), + cmocka_unit_test(test_vpd_eui_8_16_0), + cmocka_unit_test(test_vpd_eui_8_10_0), + cmocka_unit_test(test_vpd_eui_12_32_0), + cmocka_unit_test(test_vpd_eui_12_26_0), + cmocka_unit_test(test_vpd_eui_12_25_0), + cmocka_unit_test(test_vpd_eui_12_20_0), + cmocka_unit_test(test_vpd_eui_12_10_0), + cmocka_unit_test(test_vpd_eui_16_40_0), + cmocka_unit_test(test_vpd_eui_16_34_0), + cmocka_unit_test(test_vpd_eui_16_33_0), + cmocka_unit_test(test_vpd_eui_16_20_0), cmocka_unit_test(test_vpd_naa_6_40), cmocka_unit_test(test_vpd_naa_6_34), cmocka_unit_test(test_vpd_naa_6_33), -- 2.17.2