]>
Commit | Line | Data |
---|---|---|
ac33baed GKH |
1 | From 5e7ff2ca7f2da55fe777167849d0c93403bd0dc8 Mon Sep 17 00:00:00 2001 |
2 | From: Alan Stern <stern@rowland.harvard.edu> | |
3 | Date: Thu, 23 Jun 2016 15:05:26 -0400 | |
4 | Subject: SCSI: fix new bug in scsi_dev_info_list string matching | |
5 | ||
6 | From: Alan Stern <stern@rowland.harvard.edu> | |
7 | ||
8 | commit 5e7ff2ca7f2da55fe777167849d0c93403bd0dc8 upstream. | |
9 | ||
10 | Commit b704f70ce200 ("SCSI: fix bug in scsi_dev_info_list matching") | |
11 | changed the way vendor- and model-string matching was carried out in the | |
12 | routine that looks up entries in a SCSI devinfo list. The new matching | |
13 | code failed to take into account the case of a maximum-length string; in | |
14 | such cases it could end up testing for a terminating '\0' byte beyond | |
15 | the end of the memory allocated to the string. This out-of-bounds bug | |
16 | was detected by UBSAN. | |
17 | ||
18 | I don't know if anybody has actually encountered this bug. The symptom | |
19 | would be that a device entry in the blacklist might not be matched | |
20 | properly if it contained an 8-character vendor name or a 16-character | |
21 | model name. Such entries certainly exist in scsi_static_device_list. | |
22 | ||
23 | This patch fixes the problem by adding a check for a maximum-length | |
24 | string before the '\0' test. | |
25 | ||
26 | Signed-off-by: Alan Stern <stern@rowland.harvard.edu> | |
27 | Fixes: b704f70ce200 ("SCSI: fix bug in scsi_dev_info_list matching") | |
28 | Tested-by: Wilfried Klaebe <linux-kernel@lebenslange-mailadresse.de> | |
29 | Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> | |
30 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
31 | ||
32 | --- | |
33 | drivers/scsi/scsi_devinfo.c | 10 ++++++---- | |
34 | 1 file changed, 6 insertions(+), 4 deletions(-) | |
35 | ||
36 | --- a/drivers/scsi/scsi_devinfo.c | |
37 | +++ b/drivers/scsi/scsi_devinfo.c | |
38 | @@ -429,7 +429,7 @@ static struct scsi_dev_info_list *scsi_d | |
39 | * here, and we don't know what device it is | |
40 | * trying to work with, leave it as-is. | |
41 | */ | |
42 | - vmax = 8; /* max length of vendor */ | |
43 | + vmax = sizeof(devinfo->vendor); | |
44 | vskip = vendor; | |
45 | while (vmax > 0 && *vskip == ' ') { | |
46 | vmax--; | |
47 | @@ -439,7 +439,7 @@ static struct scsi_dev_info_list *scsi_d | |
48 | while (vmax > 0 && vskip[vmax - 1] == ' ') | |
49 | --vmax; | |
50 | ||
51 | - mmax = 16; /* max length of model */ | |
52 | + mmax = sizeof(devinfo->model); | |
53 | mskip = model; | |
54 | while (mmax > 0 && *mskip == ' ') { | |
55 | mmax--; | |
56 | @@ -455,10 +455,12 @@ static struct scsi_dev_info_list *scsi_d | |
57 | * Behave like the older version of get_device_flags. | |
58 | */ | |
59 | if (memcmp(devinfo->vendor, vskip, vmax) || | |
60 | - devinfo->vendor[vmax]) | |
61 | + (vmax < sizeof(devinfo->vendor) && | |
62 | + devinfo->vendor[vmax])) | |
63 | continue; | |
64 | if (memcmp(devinfo->model, mskip, mmax) || | |
65 | - devinfo->model[mmax]) | |
66 | + (mmax < sizeof(devinfo->model) && | |
67 | + devinfo->model[mmax])) | |
68 | continue; | |
69 | return devinfo; | |
70 | } else { |