udev/scsi-id: check for invalid header from kernel buffer
This commit is contained in:
@@ -542,7 +542,9 @@ static int check_fill_0x83_prespc3(struct scsi_id_device *dev_scsi,
|
||||
/* serial has been memset to zero before */
|
||||
j = strlen(serial); /* j = 1; */
|
||||
|
||||
for (i = 0; (i < page_83[3]) && (j < max_len-3); ++i) {
|
||||
/* Cap reported page length to buffer size in case of malformed responses */
|
||||
int page_len = MIN((int)page_83[3], SCSI_INQ_BUFF_LEN - 4);
|
||||
for (i = 0; (i < page_len) && (j < max_len-3); ++i) {
|
||||
serial[j++] = hexchar(page_83[4+i] >> 4);
|
||||
serial[j++] = hexchar(page_83[4+i]);
|
||||
}
|
||||
@@ -610,12 +612,25 @@ static int do_scsi_page83_inquiry(struct scsi_id_device *dev_scsi, int fd,
|
||||
* Search for a match in the prioritized id_search_list - since WWN ids
|
||||
* come first we can pick up the WWN in check_fill_0x83_id().
|
||||
*/
|
||||
|
||||
/* Cap reported page length to buffer size in case of malformed responses.
|
||||
* Below, j can equal page_end, and at that point page_83[j + 3] (the first descriptor data byte)
|
||||
* must still be readable before the inner bounds check, so page_end + 4 < SCSI_INQ_BUFF_LEN
|
||||
* requires page_end <= SCSI_INQ_BUFF_LEN - 5. */
|
||||
unsigned page_end = MIN(((unsigned)page_83[2] << 8) + (unsigned)page_83[3] + 3U,
|
||||
(unsigned)SCSI_INQ_BUFF_LEN - 5U);
|
||||
|
||||
FOREACH_ELEMENT(search_value, id_search_list) {
|
||||
/*
|
||||
* Examine each descriptor returned. There is normally only
|
||||
* one or a small number of descriptors.
|
||||
*/
|
||||
for (unsigned j = 4; j <= ((unsigned)page_83[2] << 8) + (unsigned)page_83[3] + 3; j += page_83[j + 3] + 4) {
|
||||
for (unsigned j = 4; j <= page_end; j += page_83[j + 3] + 4) {
|
||||
/* Ensure the full descriptor fits within the buffer, including
|
||||
* fixed-offset accesses up to page_83[7] in the TGTGROUP path
|
||||
* of check_fill_0x83_id(), so require at least 8 bytes from j */
|
||||
if (j + MAX(4U + (unsigned)page_83[j + 3], 8U) > (unsigned)SCSI_INQ_BUFF_LEN)
|
||||
break;
|
||||
retval = check_fill_0x83_id(dev_scsi, page_83 + j,
|
||||
search_value,
|
||||
serial, serial_short, len,
|
||||
@@ -688,7 +703,9 @@ static int do_scsi_page83_prespc3_inquiry(struct scsi_id_device *dev_scsi, int f
|
||||
* using two bytes of ASCII for each byte
|
||||
* in the page_83.
|
||||
*/
|
||||
while (i < (page_83[3]+4)) {
|
||||
/* Cap reported page length to buffer size in case of malformed responses */
|
||||
int page_len = MIN((int)page_83[3] + 4, SCSI_INQ_BUFF_LEN);
|
||||
while (i < page_len && j + 2 < len) {
|
||||
serial[j++] = hexchar(page_83[i] >> 4);
|
||||
serial[j++] = hexchar(page_83[i]);
|
||||
i++;
|
||||
@@ -725,7 +742,8 @@ static int do_scsi_page80_inquiry(struct scsi_id_device *dev_scsi, int fd,
|
||||
* Prepend 'S' to avoid unlikely collision with page 0x83 vendor
|
||||
* specific type where we prepend '0' + vendor + model.
|
||||
*/
|
||||
len = buf[3];
|
||||
/* Cap reported page length to buffer size in case of malformed responses */
|
||||
len = MIN((int)buf[3], SCSI_INQ_BUFF_LEN - 4);
|
||||
if (serial) {
|
||||
serial[0] = 'S';
|
||||
ser_ind = append_vendor_model(dev_scsi, serial + 1);
|
||||
@@ -860,7 +878,10 @@ int scsi_get_serial(struct scsi_id_device *dev_scsi, const char *devname,
|
||||
goto completed;
|
||||
}
|
||||
|
||||
for (ind = 4; ind <= page0[3] + 3; ind++)
|
||||
/* Cap reported page length to buffer size in case of malformed responses */
|
||||
int page0_end = MIN((int)page0[3] + 3, SCSI_INQ_BUFF_LEN - 1);
|
||||
|
||||
for (ind = 4; ind <= page0_end; ind++)
|
||||
if (page0[ind] == PAGE_83)
|
||||
if (!do_scsi_page83_inquiry(dev_scsi, fd,
|
||||
dev_scsi->serial, dev_scsi->serial_short, len, dev_scsi->unit_serial_number, dev_scsi->wwn, dev_scsi->wwn_vendor_extension, dev_scsi->tgpt_group)) {
|
||||
@@ -871,7 +892,7 @@ int scsi_get_serial(struct scsi_id_device *dev_scsi, const char *devname,
|
||||
goto completed;
|
||||
}
|
||||
|
||||
for (ind = 4; ind <= page0[3] + 3; ind++)
|
||||
for (ind = 4; ind <= page0_end; ind++)
|
||||
if (page0[ind] == PAGE_80)
|
||||
if (!do_scsi_page80_inquiry(dev_scsi, fd,
|
||||
dev_scsi->serial, dev_scsi->serial_short, len)) {
|
||||
|
||||
Reference in New Issue
Block a user