summaryrefslogtreecommitdiff
path: root/drivers/scsi/ses.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2023-03-03 14:41:50 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2023-03-03 14:41:50 -0800
commit06caa751545512fae98c21f282006a7fff852daf (patch)
tree7bbec6d252acda50dd5a9ccfe54b13ba2214d504 /drivers/scsi/ses.c
parent0a3f9a6b0265b64c02226fcabb5e9a958307913b (diff)
parent901b894af5b933cf6576eec05746f34b46e2ac83 (diff)
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull more SCSI updates from James Bottomley: "Updates that missed the first pull, mostly because of needing more soak time. Driver updates (zfcp, ufs, mpi3mr, plus two ipr bug fixes), an enclosure services (ses) update (mostly bug fixes) and other minor bug fixes and changes" * tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (32 commits) scsi: zfcp: Trace when request remove fails after qdio send fails scsi: zfcp: Change the type of all fsf request id fields and variables to u64 scsi: zfcp: Make the type for accessing request hashtable buckets size_t scsi: ufs: core: Simplify ufshcd_execute_start_stop() scsi: ufs: core: Rely on the block layer for setting RQF_PM scsi: core: Extend struct scsi_exec_args scsi: lpfc: Fix double word in comments scsi: core: Remove the /proc/scsi/${proc_name} directory earlier scsi: core: Fix a source code comment scsi: cxgbi: Remove unneeded version.h include scsi: qedi: Remove unneeded version.h include scsi: mpi3mr: Remove unneeded version.h include scsi: mpi3mr: Fix missing mrioc->evtack_cmds initialization scsi: mpi3mr: Use number of bits to manage bitmap sizes scsi: mpi3mr: Remove unnecessary memcpy() to alltgt_info->dmi scsi: mpi3mr: Fix issues in mpi3mr_get_all_tgt_info() scsi: mpi3mr: Fix an issue found by KASAN scsi: mpi3mr: Replace 1-element array with flex-array scsi: ipr: Work around fortify-string warning scsi: ipr: Make ipr_probe_ioa_part2() return void ...
Diffstat (limited to 'drivers/scsi/ses.c')
-rw-r--r--drivers/scsi/ses.c64
1 files changed, 47 insertions, 17 deletions
diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c
index 869ca9c7f23f..b11a9162e73a 100644
--- a/drivers/scsi/ses.c
+++ b/drivers/scsi/ses.c
@@ -439,8 +439,8 @@ int ses_match_host(struct enclosure_device *edev, void *data)
}
#endif /* 0 */
-static void ses_process_descriptor(struct enclosure_component *ecomp,
- unsigned char *desc)
+static int ses_process_descriptor(struct enclosure_component *ecomp,
+ unsigned char *desc, int max_desc_len)
{
int eip = desc[0] & 0x10;
int invalid = desc[0] & 0x80;
@@ -451,22 +451,32 @@ static void ses_process_descriptor(struct enclosure_component *ecomp,
unsigned char *d;
if (invalid)
- return;
+ return 0;
switch (proto) {
case SCSI_PROTOCOL_FCP:
if (eip) {
+ if (max_desc_len <= 7)
+ return 1;
d = desc + 4;
slot = d[3];
}
break;
case SCSI_PROTOCOL_SAS:
+
if (eip) {
+ if (max_desc_len <= 27)
+ return 1;
d = desc + 4;
slot = d[3];
d = desc + 8;
- } else
+ } else {
+ if (max_desc_len <= 23)
+ return 1;
d = desc + 4;
+ }
+
+
/* only take the phy0 addr */
addr = (u64)d[12] << 56 |
(u64)d[13] << 48 |
@@ -483,6 +493,8 @@ static void ses_process_descriptor(struct enclosure_component *ecomp,
}
ecomp->slot = slot;
scomp->addr = addr;
+
+ return 0;
}
struct efd {
@@ -555,7 +567,7 @@ static void ses_enclosure_data_process(struct enclosure_device *edev,
/* skip past overall descriptor */
desc_ptr += len + 4;
}
- if (ses_dev->page10)
+ if (ses_dev->page10 && ses_dev->page10_len > 9)
addl_desc_ptr = ses_dev->page10 + 8;
type_ptr = ses_dev->page1_types;
components = 0;
@@ -563,17 +575,22 @@ static void ses_enclosure_data_process(struct enclosure_device *edev,
for (j = 0; j < type_ptr[1]; j++) {
char *name = NULL;
struct enclosure_component *ecomp;
+ int max_desc_len;
if (desc_ptr) {
- if (desc_ptr >= buf + page7_len) {
+ if (desc_ptr + 3 >= buf + page7_len) {
desc_ptr = NULL;
} else {
len = (desc_ptr[2] << 8) + desc_ptr[3];
desc_ptr += 4;
- /* Add trailing zero - pushes into
- * reserved space */
- desc_ptr[len] = '\0';
- name = desc_ptr;
+ if (desc_ptr + len > buf + page7_len)
+ desc_ptr = NULL;
+ else {
+ /* Add trailing zero - pushes into
+ * reserved space */
+ desc_ptr[len] = '\0';
+ name = desc_ptr;
+ }
}
}
if (type_ptr[0] == ENCLOSURE_COMPONENT_DEVICE ||
@@ -589,10 +606,14 @@ static void ses_enclosure_data_process(struct enclosure_device *edev,
ecomp = &edev->component[components++];
if (!IS_ERR(ecomp)) {
- if (addl_desc_ptr)
- ses_process_descriptor(
- ecomp,
- addl_desc_ptr);
+ if (addl_desc_ptr) {
+ max_desc_len = ses_dev->page10_len -
+ (addl_desc_ptr - ses_dev->page10);
+ if (ses_process_descriptor(ecomp,
+ addl_desc_ptr,
+ max_desc_len))
+ addl_desc_ptr = NULL;
+ }
if (create)
enclosure_component_register(
ecomp);
@@ -609,9 +630,11 @@ static void ses_enclosure_data_process(struct enclosure_device *edev,
/* these elements are optional */
type_ptr[0] == ENCLOSURE_COMPONENT_SCSI_TARGET_PORT ||
type_ptr[0] == ENCLOSURE_COMPONENT_SCSI_INITIATOR_PORT ||
- type_ptr[0] == ENCLOSURE_COMPONENT_CONTROLLER_ELECTRONICS))
+ type_ptr[0] == ENCLOSURE_COMPONENT_CONTROLLER_ELECTRONICS)) {
addl_desc_ptr += addl_desc_ptr[1] + 2;
-
+ if (addl_desc_ptr + 1 >= ses_dev->page10 + ses_dev->page10_len)
+ addl_desc_ptr = NULL;
+ }
}
}
kfree(buf);
@@ -710,6 +733,12 @@ static int ses_intf_add(struct device *cdev,
type_ptr[0] == ENCLOSURE_COMPONENT_ARRAY_DEVICE)
components += type_ptr[1];
}
+
+ if (components == 0) {
+ sdev_printk(KERN_WARNING, sdev, "enclosure has no enumerated components\n");
+ goto err_free;
+ }
+
ses_dev->page1 = buf;
ses_dev->page1_len = len;
buf = NULL;
@@ -833,7 +862,8 @@ static void ses_intf_remove_enclosure(struct scsi_device *sdev)
kfree(ses_dev->page2);
kfree(ses_dev);
- kfree(edev->component[0].scratch);
+ if (edev->components)
+ kfree(edev->component[0].scratch);
put_device(&edev->edev);
enclosure_unregister(edev);