SCSI: fix new bug in scsi_dev_info_list string matching

Commit b704f70ce200 ("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: Alan Stern <stern@rowland.harvard.edu>
Fixes: b704f70ce200 ("SCSI: fix bug in scsi_dev_info_list matching")
Tested-by: Wilfried Klaebe <linux-kernel@lebenslange-mailadresse.de>
CC: <stable@vger.kernel.org> # v4.4+
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by Alan Stern and committed by Martin K. Petersen 5e7ff2ca 54e430bb

Changed files
+6 -4
drivers
+6 -4
drivers/scsi/scsi_devinfo.c
··· 429 429 * here, and we don't know what device it is 430 430 * trying to work with, leave it as-is. 431 431 */ 432 - vmax = 8; /* max length of vendor */ 432 + vmax = sizeof(devinfo->vendor); 433 433 vskip = vendor; 434 434 while (vmax > 0 && *vskip == ' ') { 435 435 vmax--; ··· 439 439 while (vmax > 0 && vskip[vmax - 1] == ' ') 440 440 --vmax; 441 441 442 - mmax = 16; /* max length of model */ 442 + mmax = sizeof(devinfo->model); 443 443 mskip = model; 444 444 while (mmax > 0 && *mskip == ' ') { 445 445 mmax--; ··· 455 455 * Behave like the older version of get_device_flags. 456 456 */ 457 457 if (memcmp(devinfo->vendor, vskip, vmax) || 458 - devinfo->vendor[vmax]) 458 + (vmax < sizeof(devinfo->vendor) && 459 + devinfo->vendor[vmax])) 459 460 continue; 460 461 if (memcmp(devinfo->model, mskip, mmax) || 461 - devinfo->model[mmax]) 462 + (mmax < sizeof(devinfo->model) && 463 + devinfo->model[mmax])) 462 464 continue; 463 465 return devinfo; 464 466 } else {