Commit db95d4df authored by Tomas Henzl's avatar Tomas Henzl Committed by Martin K. Petersen

scsi: ses: Fix possible addl_desc_ptr out-of-bounds accesses

Sanitize possible addl_desc_ptr out-of-bounds accesses in
ses_enclosure_data_process().

Link: https://lore.kernel.org/r/20230202162451.15346-3-thenzl@redhat.com
Cc: stable@vger.kernel.org
Signed-off-by: default avatarTomas Henzl <thenzl@redhat.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 9b4f5028
...@@ -439,8 +439,8 @@ int ses_match_host(struct enclosure_device *edev, void *data) ...@@ -439,8 +439,8 @@ int ses_match_host(struct enclosure_device *edev, void *data)
} }
#endif /* 0 */ #endif /* 0 */
static void ses_process_descriptor(struct enclosure_component *ecomp, static int ses_process_descriptor(struct enclosure_component *ecomp,
unsigned char *desc) unsigned char *desc, int max_desc_len)
{ {
int eip = desc[0] & 0x10; int eip = desc[0] & 0x10;
int invalid = desc[0] & 0x80; int invalid = desc[0] & 0x80;
...@@ -451,22 +451,32 @@ static void ses_process_descriptor(struct enclosure_component *ecomp, ...@@ -451,22 +451,32 @@ static void ses_process_descriptor(struct enclosure_component *ecomp,
unsigned char *d; unsigned char *d;
if (invalid) if (invalid)
return; return 0;
switch (proto) { switch (proto) {
case SCSI_PROTOCOL_FCP: case SCSI_PROTOCOL_FCP:
if (eip) { if (eip) {
if (max_desc_len <= 7)
return 1;
d = desc + 4; d = desc + 4;
slot = d[3]; slot = d[3];
} }
break; break;
case SCSI_PROTOCOL_SAS: case SCSI_PROTOCOL_SAS:
if (eip) { if (eip) {
if (max_desc_len <= 27)
return 1;
d = desc + 4; d = desc + 4;
slot = d[3]; slot = d[3];
d = desc + 8; d = desc + 8;
} else } else {
if (max_desc_len <= 23)
return 1;
d = desc + 4; d = desc + 4;
}
/* only take the phy0 addr */ /* only take the phy0 addr */
addr = (u64)d[12] << 56 | addr = (u64)d[12] << 56 |
(u64)d[13] << 48 | (u64)d[13] << 48 |
...@@ -483,6 +493,8 @@ static void ses_process_descriptor(struct enclosure_component *ecomp, ...@@ -483,6 +493,8 @@ static void ses_process_descriptor(struct enclosure_component *ecomp,
} }
ecomp->slot = slot; ecomp->slot = slot;
scomp->addr = addr; scomp->addr = addr;
return 0;
} }
struct efd { struct efd {
...@@ -555,7 +567,7 @@ static void ses_enclosure_data_process(struct enclosure_device *edev, ...@@ -555,7 +567,7 @@ static void ses_enclosure_data_process(struct enclosure_device *edev,
/* skip past overall descriptor */ /* skip past overall descriptor */
desc_ptr += len + 4; desc_ptr += len + 4;
} }
if (ses_dev->page10) if (ses_dev->page10 && ses_dev->page10_len > 9)
addl_desc_ptr = ses_dev->page10 + 8; addl_desc_ptr = ses_dev->page10 + 8;
type_ptr = ses_dev->page1_types; type_ptr = ses_dev->page1_types;
components = 0; components = 0;
...@@ -563,6 +575,7 @@ static void ses_enclosure_data_process(struct enclosure_device *edev, ...@@ -563,6 +575,7 @@ static void ses_enclosure_data_process(struct enclosure_device *edev,
for (j = 0; j < type_ptr[1]; j++) { for (j = 0; j < type_ptr[1]; j++) {
char *name = NULL; char *name = NULL;
struct enclosure_component *ecomp; struct enclosure_component *ecomp;
int max_desc_len;
if (desc_ptr) { if (desc_ptr) {
if (desc_ptr >= buf + page7_len) { if (desc_ptr >= buf + page7_len) {
...@@ -589,10 +602,14 @@ static void ses_enclosure_data_process(struct enclosure_device *edev, ...@@ -589,10 +602,14 @@ static void ses_enclosure_data_process(struct enclosure_device *edev,
ecomp = &edev->component[components++]; ecomp = &edev->component[components++];
if (!IS_ERR(ecomp)) { if (!IS_ERR(ecomp)) {
if (addl_desc_ptr) if (addl_desc_ptr) {
ses_process_descriptor( max_desc_len = ses_dev->page10_len -
ecomp, (addl_desc_ptr - ses_dev->page10);
addl_desc_ptr); if (ses_process_descriptor(ecomp,
addl_desc_ptr,
max_desc_len))
addl_desc_ptr = NULL;
}
if (create) if (create)
enclosure_component_register( enclosure_component_register(
ecomp); ecomp);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment