Commit 5e7ff2ca authored by Alan Stern's avatar Alan Stern Committed by Martin K. Petersen

SCSI: fix new bug in scsi_dev_info_list string matching

Commit b704f70c ("SCSI: fix bug in scsi_dev_info_list matching")
changed the way vendor- and model-string matching was carried out in the
routine that looks up entries in a SCSI devinfo list.  The new matching
code failed to take into account the case of a maximum-length string; in
such cases it could end up testing for a terminating '\0' byte beyond
the end of the memory allocated to the string.  This out-of-bounds bug
was detected by UBSAN.

I don't know if anybody has actually encountered this bug.  The symptom
would be that a device entry in the blacklist might not be matched
properly if it contained an 8-character vendor name or a 16-character
model name.  Such entries certainly exist in scsi_static_device_list.

This patch fixes the problem by adding a check for a maximum-length
string before the '\0' test.
Signed-off-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Fixes: b704f70c ("SCSI: fix bug in scsi_dev_info_list matching")
Tested-by: default avatarWilfried Klaebe <linux-kernel@lebenslange-mailadresse.de>
CC: <stable@vger.kernel.org> # v4.4+
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 54e430bb
...@@ -429,7 +429,7 @@ static struct scsi_dev_info_list *scsi_dev_info_list_find(const char *vendor, ...@@ -429,7 +429,7 @@ static struct scsi_dev_info_list *scsi_dev_info_list_find(const char *vendor,
* here, and we don't know what device it is * here, and we don't know what device it is
* trying to work with, leave it as-is. * trying to work with, leave it as-is.
*/ */
vmax = 8; /* max length of vendor */ vmax = sizeof(devinfo->vendor);
vskip = vendor; vskip = vendor;
while (vmax > 0 && *vskip == ' ') { while (vmax > 0 && *vskip == ' ') {
vmax--; vmax--;
...@@ -439,7 +439,7 @@ static struct scsi_dev_info_list *scsi_dev_info_list_find(const char *vendor, ...@@ -439,7 +439,7 @@ static struct scsi_dev_info_list *scsi_dev_info_list_find(const char *vendor,
while (vmax > 0 && vskip[vmax - 1] == ' ') while (vmax > 0 && vskip[vmax - 1] == ' ')
--vmax; --vmax;
mmax = 16; /* max length of model */ mmax = sizeof(devinfo->model);
mskip = model; mskip = model;
while (mmax > 0 && *mskip == ' ') { while (mmax > 0 && *mskip == ' ') {
mmax--; mmax--;
...@@ -455,10 +455,12 @@ static struct scsi_dev_info_list *scsi_dev_info_list_find(const char *vendor, ...@@ -455,10 +455,12 @@ static struct scsi_dev_info_list *scsi_dev_info_list_find(const char *vendor,
* Behave like the older version of get_device_flags. * Behave like the older version of get_device_flags.
*/ */
if (memcmp(devinfo->vendor, vskip, vmax) || if (memcmp(devinfo->vendor, vskip, vmax) ||
devinfo->vendor[vmax]) (vmax < sizeof(devinfo->vendor) &&
devinfo->vendor[vmax]))
continue; continue;
if (memcmp(devinfo->model, mskip, mmax) || if (memcmp(devinfo->model, mskip, mmax) ||
devinfo->model[mmax]) (mmax < sizeof(devinfo->model) &&
devinfo->model[mmax]))
continue; continue;
return devinfo; return devinfo;
} else { } else {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment