diff options
Diffstat (limited to 'drivers/scsi/scsi_scan.c')
| -rw-r--r-- | drivers/scsi/scsi_scan.c | 18 |
1 files changed, 14 insertions, 4 deletions
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 148e24cc3222..aa1b1e0e9d22 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c | |||
| @@ -700,12 +700,22 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, | |||
| 700 | * scanning run at their own risk, or supply a user level program | 700 | * scanning run at their own risk, or supply a user level program |
| 701 | * that can correctly scan. | 701 | * that can correctly scan. |
| 702 | */ | 702 | */ |
| 703 | sdev->inquiry = kmalloc(sdev->inquiry_len, GFP_ATOMIC); | 703 | |
| 704 | if (sdev->inquiry == NULL) { | 704 | /* |
| 705 | * Copy at least 36 bytes of INQUIRY data, so that we don't | ||
| 706 | * dereference unallocated memory when accessing the Vendor, | ||
| 707 | * Product, and Revision strings. Badly behaved devices may set | ||
| 708 | * the INQUIRY Additional Length byte to a small value, indicating | ||
| 709 | * these strings are invalid, but often they contain plausible data | ||
| 710 | * nonetheless. It doesn't matter if the device sent < 36 bytes | ||
| 711 | * total, since scsi_probe_lun() initializes inq_result with 0s. | ||
| 712 | */ | ||
| 713 | sdev->inquiry = kmemdup(inq_result, | ||
| 714 | max_t(size_t, sdev->inquiry_len, 36), | ||
| 715 | GFP_ATOMIC); | ||
| 716 | if (sdev->inquiry == NULL) | ||
| 705 | return SCSI_SCAN_NO_RESPONSE; | 717 | return SCSI_SCAN_NO_RESPONSE; |
| 706 | } | ||
| 707 | 718 | ||
| 708 | memcpy(sdev->inquiry, inq_result, sdev->inquiry_len); | ||
| 709 | sdev->vendor = (char *) (sdev->inquiry + 8); | 719 | sdev->vendor = (char *) (sdev->inquiry + 8); |
| 710 | sdev->model = (char *) (sdev->inquiry + 16); | 720 | sdev->model = (char *) (sdev->inquiry + 16); |
| 711 | sdev->rev = (char *) (sdev->inquiry + 32); | 721 | sdev->rev = (char *) (sdev->inquiry + 32); |
