device-mapper-multipath/SOURCES/0007-libmultipath-fix-sgio_...

205 lines
7.2 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
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 <bmarzins@redhat.com>
---
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