Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8e454aba authored by Tomas Henzl's avatar Tomas Henzl Committed by Greg Kroah-Hartman
Browse files

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: default avatarTomas Henzl <thenzl@redhat.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 467afb1d
Loading
Loading
Loading
Loading
+26 −9
Original line number Diff line number Diff line
@@ -433,8 +433,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;
@@ -445,22 +445,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 |
@@ -477,6 +487,8 @@ static void ses_process_descriptor(struct enclosure_component *ecomp,
	}
	ecomp->slot = slot;
	scomp->addr = addr;

	return 0;
}

struct efd {
@@ -549,7 +561,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;
@@ -557,6 +569,7 @@ 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) {
@@ -583,10 +596,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);