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 fd9e281c3bfe..94a274645f6f 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c | |||
| @@ -631,12 +631,22 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, | |||
| 631 | * scanning run at their own risk, or supply a user level program | 631 | * scanning run at their own risk, or supply a user level program |
| 632 | * that can correctly scan. | 632 | * that can correctly scan. |
| 633 | */ | 633 | */ |
| 634 | sdev->inquiry = kmalloc(sdev->inquiry_len, GFP_ATOMIC); | 634 | |
| 635 | if (sdev->inquiry == NULL) { | 635 | /* |
| 636 | * Copy at least 36 bytes of INQUIRY data, so that we don't | ||
| 637 | * dereference unallocated memory when accessing the Vendor, | ||
| 638 | * Product, and Revision strings. Badly behaved devices may set | ||
| 639 | * the INQUIRY Additional Length byte to a small value, indicating | ||
| 640 | * these strings are invalid, but often they contain plausible data | ||
| 641 | * nonetheless. It doesn't matter if the device sent < 36 bytes | ||
| 642 | * total, since scsi_probe_lun() initializes inq_result with 0s. | ||
| 643 | */ | ||
| 644 | sdev->inquiry = kmemdup(inq_result, | ||
| 645 | max_t(size_t, sdev->inquiry_len, 36), | ||
| 646 | GFP_ATOMIC); | ||
| 647 | if (sdev->inquiry == NULL) | ||
| 636 | return SCSI_SCAN_NO_RESPONSE; | 648 | return SCSI_SCAN_NO_RESPONSE; |
| 637 | } | ||
| 638 | 649 | ||
| 639 | memcpy(sdev->inquiry, inq_result, sdev->inquiry_len); | ||
| 640 | sdev->vendor = (char *) (sdev->inquiry + 8); | 650 | sdev->vendor = (char *) (sdev->inquiry + 8); |
| 641 | sdev->model = (char *) (sdev->inquiry + 16); | 651 | sdev->model = (char *) (sdev->inquiry + 16); |
| 642 | sdev->rev = (char *) (sdev->inquiry + 32); | 652 | sdev->rev = (char *) (sdev->inquiry + 32); |
