All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alan Stern <stern@rowland.harvard.edu>
To: James Bottomley <James.Bottomley@HansenPartnership.com>
Cc: Giulio Bernardi <ugilio@gmail.com>,
	SCSI development list <linux-scsi@vger.kernel.org>
Subject: [PATCH 2/2] SCSI: fix bug in scsi_dev_info_list matching
Date: Mon, 3 Aug 2015 11:57:29 -0400 (EDT)	[thread overview]
Message-ID: <Pine.LNX.4.44L0.1508031144150.1667-100000@iolanthe.rowland.org> (raw)

The "compatible" matching algorithm used for looking up old-style
blacklist entries in a scsi_dev_info_list is buggy.  The core of the
algorithm looks like this:

		if (memcmp(devinfo->vendor, vendor,
			    min(max, strlen(devinfo->vendor))))
			/* not a match */

where max is the length of the device's vendor string after leading
spaces have been removed but trailing spaces have not.  Because of the
min() computation, either entry could be a proper substring of the
other and the code would still think that they match.

In the case originally reported, the device's vendor and product
strings were "Inateck " and "                ".  These matched against
the following entry in the global device list:

	{"", "Scanner", "1.80", BLIST_NOLUN}

because "" is a substring of "Inateck " and "" (the result of removing
leading spaces from the device's product string) is a substring of
"Scanner".  The mistaken match prevented the system from scanning and
finding the device's second Logical Unit.

This patch fixes the problem by making two changes.  First, the code
for leading-space removal is hoisted out of the loop.  (This means it
will sometimes run unnecessarily, but since a large percentage of all
lookups involve the "compatible" entries in global device list, this
should be an overall improvement.)  Second and more importantly, the
patch removes trailing spaces and adds a check to verify that the two
resulting strings are exactly the same length.  This prevents matches
where one entry is a proper substring of the other.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Reported-by: Giulio Bernardi <ugilio@gmail.com>
Tested-by: Giulio Bernardi <ugilio@gmail.com>

---


[as1783]


 drivers/scsi/scsi_devinfo.c |   69 ++++++++++++++++++++++----------------------
 1 file changed, 35 insertions(+), 34 deletions(-)

Index: usb-4.2/drivers/scsi/scsi_devinfo.c
===================================================================
--- usb-4.2.orig/drivers/scsi/scsi_devinfo.c
+++ usb-4.2/drivers/scsi/scsi_devinfo.c
@@ -407,51 +407,52 @@ static struct scsi_dev_info_list *scsi_d
 	struct scsi_dev_info_list *devinfo;
 	struct scsi_dev_info_list_table *devinfo_table =
 		scsi_devinfo_lookup_by_key(key);
+	size_t vmax, mmax;
+	const char *vskip, *mskip;
 
 	if (IS_ERR(devinfo_table))
 		return (struct scsi_dev_info_list *) devinfo_table;
 
+	/* Prepare for "compatible" matches */
+
+	/*
+	 * XXX why skip leading spaces? If an odd INQUIRY
+	 * value, that should have been part of the
+	 * scsi_static_device_list[] entry, such as "  FOO"
+	 * rather than "FOO". Since this code is already
+	 * here, and we don't know what device it is
+	 * trying to work with, leave it as-is.
+	 */
+	vmax = 8;	/* max length of vendor */
+	vskip = vendor;
+	while (vmax > 0 && *vskip == ' ') {
+		vmax--;
+		vskip++;
+	}
+	/* Also skip trailing spaces */
+	while (vmax > 0 && vskip[vmax - 1] == ' ')
+		--vmax;
+
+	mmax = 16;	/* max length of model */
+	mskip = model;
+	while (mmax > 0 && *mskip == ' ') {
+		mmax--;
+		mskip++;
+	}
+	while (mmax > 0 && mskip[mmax - 1] == ' ')
+		--mmax;
+
 	list_for_each_entry(devinfo, &devinfo_table->scsi_dev_info_list,
 			    dev_info_list) {
 		if (devinfo->compatible) {
 			/*
 			 * Behave like the older version of get_device_flags.
 			 */
-			size_t max;
-			/*
-			 * XXX why skip leading spaces? If an odd INQUIRY
-			 * value, that should have been part of the
-			 * scsi_static_device_list[] entry, such as "  FOO"
-			 * rather than "FOO". Since this code is already
-			 * here, and we don't know what device it is
-			 * trying to work with, leave it as-is.
-			 */
-			max = 8;	/* max length of vendor */
-			while ((max > 0) && *vendor == ' ') {
-				max--;
-				vendor++;
-			}
-			/*
-			 * XXX removing the following strlen() would be
-			 * good, using it means that for a an entry not in
-			 * the list, we scan every byte of every vendor
-			 * listed in scsi_static_device_list[], and never match
-			 * a single one (and still have to compare at
-			 * least the first byte of each vendor).
-			 */
-			if (memcmp(devinfo->vendor, vendor,
-				    min(max, strlen(devinfo->vendor))))
+			if (memcmp(devinfo->vendor, vskip, vmax) ||
+					devinfo->vendor[vmax])
 				continue;
-			/*
-			 * Skip spaces again.
-			 */
-			max = 16;	/* max length of model */
-			while ((max > 0) && *model == ' ') {
-				max--;
-				model++;
-			}
-			if (memcmp(devinfo->model, model,
-				   min(max, strlen(devinfo->model))))
+			if (memcmp(devinfo->model, mskip, mmax) ||
+					devinfo->model[mmax])
 				continue;
 			return devinfo;
 		} else {


                 reply	other threads:[~2015-08-03 15:57 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=Pine.LNX.4.44L0.1508031144150.1667-100000@iolanthe.rowland.org \
    --to=stern@rowland.harvard.edu \
    --cc=James.Bottomley@HansenPartnership.com \
    --cc=linux-scsi@vger.kernel.org \
    --cc=ugilio@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.