diff --git a/0001-sg_vpd-sg_inq-Safe-VPD-page-access.patch b/0001-sg_vpd-sg_inq-Safe-VPD-page-access.patch new file mode 100644 index 0000000..a89871c --- /dev/null +++ b/0001-sg_vpd-sg_inq-Safe-VPD-page-access.patch @@ -0,0 +1,296 @@ +From 199fde9fa26d62cb19af502b99d0100247aff97b Mon Sep 17 00:00:00 2001 +From: Hannes Reinecke +Date: Thu, 28 Apr 2016 14:22:38 +0200 +Subject: [PATCH] sg_vpd, sg_inq: Safe VPD page access + +Check VPD page 0x0 before trying to access individual VPD pages. +Non-conformant drives are know to crash when blindly issuing +a VPD request; checking page 0x0 should avoid that. +The check can be suppressed by using the new option '--force' + +Signed-off-by: Hannes Reinecke +--- + doc/sg_inq.8 | 20 +++++++++++++------- + doc/sg_vpd.8 | 7 ++++++- + src/sg_inq.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++-- + src/sg_vpd.c | 31 ++++++++++++++++++++++++++++--- + 4 files changed, 94 insertions(+), 13 deletions(-) + +diff --git a/doc/sg_inq.8 b/doc/sg_inq.8 +index 11b4c16..db3ee30 100644 +--- a/doc/sg_inq.8 ++++ b/doc/sg_inq.8 +@@ -5,16 +5,17 @@ sg_inq \- issue SCSI INQUIRY command and/or decode its response + .B sg_inq + [\fI\-\-ata\fR] [\fI\-\-block=0|1\fR] [\fI\-\-cmddt\fR] + [\fI\-\-descriptors\fR] [\fI\-\-export\fR] [\fI\-\-extended\fR] +-[\fI\-\-help\fR] [\fI\-\-hex\fR] [\fI\-\-id\fR] [\fI\-\-inhex=FN\fR] +-[\fI\-\-len=LEN\fR] [\fI\-\-maxlen=LEN\fR] [\fI\-\-page=PG\fR] +-[\fI\-\-raw\fR] [\fI\-\-vendor\fR] [\fI\-\-verbose\fR] ++[\fI\-\-force\fR] [\fI\-\-help\fR] [\fI\-\-hex\fR] [\fI\-\-id\fR] ++[\fI\-\-inhex=FN\fR] [\fI\-\-len=LEN\fR] [\fI\-\-maxlen=LEN\fR] ++[\fI\-\-page=PG\fR] [\fI\-\-raw\fR] [\fI\-\-vendor\fR] [\fI\-\-verbose\fR] + [\fI\-\-version\fR] [\fI\-\-vpd\fR] \fIDEVICE\fR + .PP + .B sg_inq +-[\fI\-36\fR] [\fI\-a\fR] [\fI\-A\fR] [\fI\-b\fR] [\fI\-\-B=0|1\fR] [\fI\-c\fR] +-[\fI\-cl\fR] [\fI\-d\fR] [\fI\-e\fR] [\fI\-h\fR] [\fI\-H\fR] [\fI\-i\fR] +-[\fI\-I=FN\fR] [\fI\-l=LEN\fR] [\fI\-m\fR] [\fI\-M\fR] [\fI\-o=OPCODE_PG\fR] +-[\fI\-p=VPD_PG\fR] [\fI\-P\fR] [\fI\-r\fR] [\fI\-s\fR] [\fI\-u\fR] [\fI\-v\fR] ++[\fI\-36\fR] [\fI\-a\fR] [\fI\-A\fR] [\fI\-b\fR] [\fI\-\-B=0|1\fR] ++[\fI\-c\fR] [\fI\-cl\fR] [\fI\-d\fR] [\fI\-e\fR] [\fI\-f\fR] ++[\fI\-h\fR] [\fI\-H\fR] [\fI\-i\fR] [\fI\-I=FN\fR] [\fI\-l=LEN\fR] ++[\fI\-m\fR] [\fI\-M\fR] [\fI\-o=OPCODE_PG\fR] [\fI\-p=VPD_PG\fR] ++[\fI\-P\fR] [\fI\-r\fR] [\fI\-s\fR] [\fI\-u\fR] [\fI\-v\fR] + [\fI\-V\fR] [\fI\-x\fR] [\fI\-36\fR] [\fI\-?\fR] \fIDEVICE\fR + .SH DESCRIPTION + .\" Add any additional description here +@@ -94,6 +95,11 @@ if any. + \fB\-e\fR + see entry below for \fI\-\-vpd\fR. + .TP ++\fB\-f\fR, \fB\-\-force\fR ++skip checking of VPD page 0x0 (SUPPORTED VPD PAGES) before accessing ++the individual VPD page. This is know to crash certain USB devices, ++so use with care. ++.TP + \fB\-u\fR, \fB\-\-export\fR + prints out information obtained from the device. The output can be + modified by selecting a VPD page with \fIPG\fR (from +diff --git a/doc/sg_vpd.8 b/doc/sg_vpd.8 +index 4e3e15d..0aacc08 100644 +--- a/doc/sg_vpd.8 ++++ b/doc/sg_vpd.8 +@@ -6,7 +6,7 @@ sg_vpd \- fetch SCSI VPD page and/or decode its response + [\fI\-\-all\fR] [\fI\-\-enumerate\fR] [\fI\-\-help\fR] [\fI\-\-hex\fR] + [\fI\-\-ident\fR] [\fI\-\-inhex=FN\fR] [\fI\-\-long\fR] [\fI\-\-maxlen=LEN\fR] + [\fI\-\-page=PG\fR] [\fI\-\-quiet\fR] [\fI\-\-raw\fR] [\fI\-\-vendor=VP\fR] +-[\fI\-\-verbose\fR] [\fI\-\-version\fR] [\fIDEVICE\fR] ++[\fI\-\-force\fR] [\fI\-\-verbose\fR] [\fI\-\-version\fR] [\fIDEVICE\fR] + .SH DESCRIPTION + .\" Add any additional description here + .PP +@@ -60,6 +60,11 @@ summary lines of all VPD pages whose number matches \fIPG\fR. May be used + with \fI\-\-vendor=VP\fR to restrict output to known vendor specific pages + for vendor/product \fIVP\fR. + .TP ++\fB\-f\fR, \fB\-\-force\fR ++skip checking of VPD page 0x0 (SUPPORTED VPD PAGES) before accessing ++the individual VPD page. This is know to crash certain USB devices, ++so use with care. ++.TP + \fB\-h\fR, \fB\-\-help\fR + outputs the usage message summarizing command line options then exits. + Ignores \fIDEVICE\fR if given. +diff --git a/src/sg_inq.c b/src/sg_inq.c +index e4bcfd3..24c0ced 100644 +--- a/src/sg_inq.c ++++ b/src/sg_inq.c +@@ -192,6 +192,7 @@ static struct option long_options[] = { + {"descriptors", no_argument, 0, 'd'}, + {"export", no_argument, 0, 'u'}, + {"extended", no_argument, 0, 'x'}, ++ {"force", no_argument, 0, 'f'}, + {"help", no_argument, 0, 'h'}, + {"hex", no_argument, 0, 'H'}, + {"id", no_argument, 0, 'i'}, +@@ -217,6 +218,7 @@ struct opts_t { + int do_cmddt; + int do_descriptors; + int do_export; ++ int do_force; + int do_help; + int do_hex; + int do_raw; +@@ -279,6 +281,7 @@ usage() + " only supported for VPD pages 0x80 and 0x83\n" + " --extended|-E|-x decode extended INQUIRY data VPD page " + "(0x86)\n" ++ " --force|-f skip VPD page 0 checking\n" + " --help|-h print usage message then exit\n" + " --hex|-H output response in hex\n" + " --id|-i decode device identification VPD page " +@@ -400,10 +403,10 @@ cl_new_process(struct opts_t * op, int argc, char * argv[]) + + #ifdef SG_LIB_LINUX + #ifdef SG_SCSI_STRINGS +- c = getopt_long(argc, argv, "aB:cdeEhHiI:l:m:NOp:rsuvVx", ++ c = getopt_long(argc, argv, "aB:cdeEfhHiI:l:m:NOp:rsuvVx", + long_options, &option_index); + #else +- c = getopt_long(argc, argv, "B:cdeEhHiI:l:m:p:rsuvVx", long_options, ++ c = getopt_long(argc, argv, "B:cdeEfhHiI:l:m:p:rsuvVx", long_options, + &option_index); + #endif /* SG_SCSI_STRINGS */ + #else /* SG_LIB_LINUX */ +@@ -452,6 +455,9 @@ cl_new_process(struct opts_t * op, int argc, char * argv[]) + ++op->do_vpd; + op->page_num = VPD_EXT_INQ; + break; ++ case 'f': ++ ++op->do_force; ++ break; + case 'h': + ++op->do_help; + break; +@@ -584,6 +590,9 @@ cl_old_process(struct opts_t * op, int argc, char * argv[]) + case 'e': + ++op->do_vpd; + break; ++ case 'f': ++ ++op->do_force; ++ break; + case 'h': + case 'H': + ++op->do_hex; +@@ -1234,6 +1243,32 @@ decode_supported_vpd(unsigned char * buff, int len, int do_hex) + } + } + ++static bool ++vpd_page_is_supported(unsigned char * buff, int len, int pg) ++{ ++ int vpd, k, rlen; ++ bool supported = false; ++ ++ if (len < 4) ++ return false; ++ ++ rlen = buff[3] + 4; ++ if (rlen > len) ++ pr2serr("Supported VPD pages VPD page truncated, indicates %d, got " ++ "%d\n", rlen, len); ++ else ++ len = rlen; ++ ++ for (k = 0; k < len - 4; ++k) { ++ vpd = buff[4 + k]; ++ if(vpd == pg) { ++ supported = true; ++ break; ++ } ++ } ++ return supported; ++} ++ + /* ASCII Information VPD pages (page numbers: 0x1 to 0x7f) */ + static void + decode_ascii_inf(unsigned char * buff, int len, int do_hex) +@@ -3454,6 +3489,15 @@ vpd_decode(int sg_fd, const struct opts_t * op, int inhex_len) + mxlen = op->resp_len; + else + mxlen = inhex_len; ++ if (sg_fd != -1 && !op->do_force && pn != VPD_SUPPORTED_VPDS) { ++ res = vpd_fetch_page_from_dev(sg_fd, rp, 0, mxlen, vb, &len); ++ if (res) ++ goto out; ++ if (!vpd_page_is_supported(rp, len, pn)) { ++ res = SG_LIB_CAT_ILLEGAL_REQ; ++ goto out; ++ } ++ } + switch (pn) { + case VPD_SUPPORTED_VPDS: + if (!op->do_raw && (op->do_hex < 2)) +@@ -3747,6 +3791,7 @@ vpd_decode(int sg_fd, const struct opts_t * op, int inhex_len) + return vpd_mainly_hex(sg_fd, op, inhex_len); + } + } ++out: + if (res) { + char b[80]; + +diff --git a/src/sg_vpd.c b/src/sg_vpd.c +index 831b0aa..530dd85 100644 +--- a/src/sg_vpd.c ++++ b/src/sg_vpd.c +@@ -45,6 +45,7 @@ static const char * version_str = "1.14 20160217"; /* spc5r08 + sbc4r10 */ + struct opts_t { + int do_all; + int do_enum; ++ int do_force; + int do_hex; + int num_vpd; + int do_ident; +@@ -151,6 +152,7 @@ static void decode_transport_id(const char * leadin, unsigned char * ucp, + static struct option long_options[] = { + {"all", no_argument, 0, 'a'}, + {"enumerate", no_argument, 0, 'e'}, ++ {"force", no_argument, 0, 'f'}, + {"help", no_argument, 0, 'h'}, + {"hex", no_argument, 0, 'H'}, + {"ident", no_argument, 0, 'i'}, +@@ -231,7 +233,7 @@ static struct svpd_values_name_t standard_vpd_pg[] = { + static void + usage() + { +- pr2serr("Usage: sg_vpd [--all] [--enumerate] [--help] [--hex] " ++ pr2serr("Usage: sg_vpd [--all] [--enumerate] [--force] [--help] [--hex] " + "[--ident]\n" + " [--inhex=FN] [--long] [--maxlen=LEN] " + "[--page=PG] [--quiet]\n" +@@ -244,6 +246,7 @@ usage() + " --enumerate|-e enumerate known VPD pages names (ignore " + "DEVICE),\n" + " can be used with --page=num to search\n" ++ " --force|-f skip VPD page 0 checking\n" + " --help|-h output this usage message then exit\n" + " --hex|-H output page in ASCII hexadecimal\n" + " --ident|-i output device identification VPD page, " +@@ -3034,7 +3037,7 @@ static int + svpd_decode_t10(int sg_fd, struct opts_t * op, int subvalue, int off) + { + int len, pdt, num, k, resid, alloc_len, pn, vb, allow_name, long_notquiet; +- int res = 0; ++ int res = 0, vpd_supported = 0; + char b[48]; + const struct svpd_values_name_t * vnp; + char obuff[DEF_ALLOC_LEN]; +@@ -3049,6 +3052,25 @@ svpd_decode_t10(int sg_fd, struct opts_t * op, int subvalue, int off) + else + allow_name = 1; + rp = rsp_buff + off; ++ if (sg_fd != -1 && !op->do_force && ++ pn != VPD_NO_RATHER_STD_INQ && ++ pn != VPD_SUPPORTED_VPDS) { ++ res = vpd_fetch_page_from_dev(sg_fd, rp, 0, op->maxlen, vb, &len); ++ if (res) ++ return res; ++ ++ num = rp[3]; ++ if (num > (len - 4)) ++ num = (len - 4); ++ for (k = 0; k < num; ++k) { ++ if (pn == rp[4 + k]) { ++ vpd_supported = 1; ++ break; ++ } ++ } ++ if (!vpd_supported) ++ return SG_LIB_CAT_ILLEGAL_REQ; ++ } + switch(pn) { + case VPD_NO_RATHER_STD_INQ: /* -2 (want standard inquiry response) */ + if (sg_fd >= 0) { +@@ -3772,7 +3794,7 @@ main(int argc, char * argv[]) + while (1) { + int option_index = 0; + +- c = getopt_long(argc, argv, "aehHiI:lm:M:p:qrvV", long_options, ++ c = getopt_long(argc, argv, "aefhHiI:lm:M:p:qrvV", long_options, + &option_index); + if (c == -1) + break; +@@ -3784,6 +3806,9 @@ main(int argc, char * argv[]) + case 'e': + ++op->do_enum; + break; ++ case 'f': ++ ++op->do_force; ++ break; + case 'h': + case '?': + usage(); +-- +2.6.6 + diff --git a/sg3_utils.changes b/sg3_utils.changes index 7064d19..79bf0a2 100644 --- a/sg3_utils.changes +++ b/sg3_utils.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Thu Apr 28 14:38:24 CEST 2016 - hare@suse.de + +- sg_inq,sg_vpd: Safe VPD page access (bsc#945094) + * Add 0001-sg_vpd-sg_inq-Safe-VPD-page-access.patch + ------------------------------------------------------------------- Thu Feb 18 09:41:03 CET 2016 - hare@suse.de diff --git a/sg3_utils.spec b/sg3_utils.spec index bb779d2..8004dc5 100644 --- a/sg3_utils.spec +++ b/sg3_utils.spec @@ -28,6 +28,7 @@ Url: http://sg.danny.cz/sg/sg3_utils.html Source: http://sg.danny.cz/sg/p/%name-%version.tar.xz Source1: 40-usb-blacklist.rules Patch1: sgut-libversioning.diff +Patch2: 0001-sg_vpd-sg_inq-Safe-VPD-page-access.patch BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildRequires: libtool BuildRequires: udev @@ -84,6 +85,7 @@ applications that want to make use of libsgutils. %prep %setup -q %patch1 -p1 +%patch2 -p1 %build autoreconf -fi