[PATCH] scsi: megaraid_sas: validate dynamic RAID map descriptor element counts

Pengpeng Hou posted 1 patch 1 week, 3 days ago
drivers/scsi/megaraid/megaraid_sas_fp.c | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
[PATCH] scsi: megaraid_sas: validate dynamic RAID map descriptor element counts
Posted by Pengpeng Hou 1 week, 3 days ago
MR_PopulateDrvRaidMap() uses raid_map_desc_elements from the firmware's
dynamic RAID map to drive memcpy() sizes and array-copy loops into the
driver-owned devHndlInfo[], ldTgtIdToLd[], arMapInfo[] and ldSpanMap[]
buffers. Those destinations are fixed-size arrays, but the descriptor
element counts are currently trusted without checking that they fit the
corresponding driver map arrays.

Reject dynamic RAID map descriptors whose element counts exceed the
destination array capacities before copying them into the driver map.

Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
---
 drivers/scsi/megaraid/megaraid_sas_fp.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/drivers/scsi/megaraid/megaraid_sas_fp.c b/drivers/scsi/megaraid/megaraid_sas_fp.c
index 4e65583ca19d..01ff44619c27 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fp.c
+++ b/drivers/scsi/megaraid/megaraid_sas_fp.c
@@ -164,6 +164,7 @@ static int MR_PopulateDrvRaidMap(struct megasas_instance *instance, u64 map_id)
 	struct MR_FW_RAID_MAP_DYNAMIC *fw_map_dyn;
 	struct MR_FW_RAID_MAP_EXT *fw_map_ext;
 	struct MR_RAID_MAP_DESC_TABLE *desc_table;
+	u32 desc_elements;
 
 
 	struct MR_DRV_RAID_MAP_ALL *drv_map =
@@ -195,8 +196,15 @@ static int MR_PopulateDrvRaidMap(struct megasas_instance *instance, u64 map_id)
 			le32_to_cpu(fw_map_dyn->desc_table_size);
 
 		for (i = 0; i < le32_to_cpu(fw_map_dyn->desc_table_num_elements); ++i) {
+			desc_elements = le32_to_cpu(desc_table->raid_map_desc_elements);
 			switch (le32_to_cpu(desc_table->raid_map_desc_type)) {
 			case RAID_MAP_DESC_TYPE_DEVHDL_INFO:
+				if (desc_elements > MAX_RAIDMAP_PHYSICAL_DEVICES_DYN) {
+					dev_dbg(&instance->pdev->dev,
+						"invalid dev handle descriptor count %u\n",
+						desc_elements);
+					return 1;
+				}
 				fw_map_dyn->dev_hndl_info =
 				(struct MR_DEV_HANDLE_INFO *)(raid_map_data + le32_to_cpu(desc_table->raid_map_desc_offset));
 				memcpy(pDrvRaidMap->devHndlInfo,
@@ -205,6 +213,12 @@ static int MR_PopulateDrvRaidMap(struct megasas_instance *instance, u64 map_id)
 					le32_to_cpu(desc_table->raid_map_desc_elements));
 			break;
 			case RAID_MAP_DESC_TYPE_TGTID_INFO:
+				if (desc_elements > MAX_LOGICAL_DRIVES_DYN) {
+					dev_dbg(&instance->pdev->dev,
+						"invalid target id descriptor count %u\n",
+						desc_elements);
+					return 1;
+				}
 				fw_map_dyn->ld_tgt_id_to_ld =
 					(u16 *)(raid_map_data +
 					le32_to_cpu(desc_table->raid_map_desc_offset));
@@ -214,6 +228,12 @@ static int MR_PopulateDrvRaidMap(struct megasas_instance *instance, u64 map_id)
 				}
 			break;
 			case RAID_MAP_DESC_TYPE_ARRAY_INFO:
+				if (desc_elements > MAX_API_ARRAYS_DYN) {
+					dev_dbg(&instance->pdev->dev,
+						"invalid array descriptor count %u\n",
+						desc_elements);
+					return 1;
+				}
 				fw_map_dyn->ar_map_info =
 					(struct MR_ARRAY_INFO *)
 					(raid_map_data + le32_to_cpu(desc_table->raid_map_desc_offset));
@@ -223,6 +243,12 @@ static int MR_PopulateDrvRaidMap(struct megasas_instance *instance, u64 map_id)
 				       le32_to_cpu(desc_table->raid_map_desc_elements));
 			break;
 			case RAID_MAP_DESC_TYPE_SPAN_INFO:
+				if (desc_elements > MAX_LOGICAL_DRIVES_DYN) {
+					dev_dbg(&instance->pdev->dev,
+						"invalid span descriptor count %u\n",
+						desc_elements);
+					return 1;
+				}
 				fw_map_dyn->ld_span_map =
 					(struct MR_LD_SPAN_MAP *)
 					(raid_map_data +
-- 
2.50.1 (Apple Git-155)
Re: [PATCH] scsi: megaraid_sas: validate dynamic RAID map descriptor element counts
Posted by James Bottomley 1 week, 2 days ago
On Tue, 2026-03-24 at 16:52 +0800, Pengpeng Hou wrote:
> MR_PopulateDrvRaidMap() uses raid_map_desc_elements from the
> firmware's dynamic RAID map to drive memcpy() sizes and array-copy
> loops into the driver-owned devHndlInfo[], ldTgtIdToLd[], arMapInfo[]
> and ldSpanMap[] buffers. Those destinations are fixed-size arrays,
> but the descriptor element counts are currently trusted without
> checking that they fit the corresponding driver map arrays.

The values for the array sizes come from the driver headers, which are
supposed to be in sync with the firmware.  They're also pretty huge
(mostly 512) so what makes you think there's an actual problem here?

> Reject dynamic RAID map descriptors whose element counts exceed the
> destination array capacities before copying them into the driver map.

Even assuming there was some way the firmware and the driver could get
out of sync over the maximum, wouldn't the best thing we could do be to
warn and truncate?

Regards,

James