scsi: ses: Fix possible addl_desc_ptr out-of-bounds accesses
commit db95d4df71cb55506425b6e4a5f8d68e3a765b63 upstream. 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: Tomas Henzl <thenzl@redhat.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:

committed by
Greg Kroah-Hartman

parent
e4dd25da78
commit
2ecd344173
@@ -433,8 +433,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;
|
||||||
@@ -445,22 +445,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 |
|
||||||
@@ -477,6 +487,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 {
|
||||||
@@ -549,7 +561,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;
|
||||||
@@ -557,6 +569,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) {
|
||||||
@@ -583,10 +596,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);
|
||||||
|
Reference in New Issue
Block a user