aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShivasharan S <shivasharan.srikanteshwara@broadcom.com>2017-02-10 03:59:19 -0500
committerMartin K. Petersen <martin.petersen@oracle.com>2017-02-13 07:26:22 -0500
commitd2d0358bcd09139a8e71afbca35bcd6b219dd1bf (patch)
tree2cfbc620a3d8fe974026c7a2db3b9599fb471d88
parenta09454ce5dd11184c5040ed536d323e2a302a579 (diff)
scsi: megaraid_sas: MR_TargetIdToLdGet u8 to u16 and avoid invalid raid-map access
Change MR_TargetIdToLdGet return type from u8 to u16. ld id range check is added at two places in this patch - @megasas_build_ldio_fusion and @megasas_build_ld_nonrw_fusion. Previous driver code used different data type for lds TargetId returned from MR_TargetIdToLdGet. Prior to this change, above two functions was safeguarded due to function always return u8 and maximum value of ld id returned was 255. In below check, fw_supported_vd_count as of today is 64 or 256 and valid range to support is either 0-63 or 0-255. Ideally want to filter accessing raid map for ld ids which are not valid. With the u16 change, invalid ld id value is 0xFFFF and we will see kernel panic due to random memory access in MR_LdRaidGet. The changes will ensure we do not call MR_LdRaidGet if ld id is beyond size of ldSpanMap array. if (ld < instance->fw_supported_vd_count) >From firmware perspective,ld id 0xFF is invalid and even though current driver code forward such command, firmware fails with target not available. ld target id issue occurs mainly whenever driver loops to populate raid map (ea. MR_ValidateMapInfo). These are the only two places where we may see out of range target ids and wants to protect raid map access based on range provided by Firmware API. Signed-off-by: Shivasharan S <shivasharan.srikanteshwara@broadcom.com> Signed-off-by: Kashyap Desai <kashyap.desai@broadcom.com> Reviewed-by: Tomas Henzl <thenzl@redhat.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.h2
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fp.c5
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fusion.c25
3 files changed, 18 insertions, 14 deletions
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
index 0a20fff04192..efc01a374a6e 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -2448,7 +2448,7 @@ MR_BuildRaidContext(struct megasas_instance *instance,
2448 struct IO_REQUEST_INFO *io_info, 2448 struct IO_REQUEST_INFO *io_info,
2449 struct RAID_CONTEXT *pRAID_Context, 2449 struct RAID_CONTEXT *pRAID_Context,
2450 struct MR_DRV_RAID_MAP_ALL *map, u8 **raidLUN); 2450 struct MR_DRV_RAID_MAP_ALL *map, u8 **raidLUN);
2451u8 MR_TargetIdToLdGet(u32 ldTgtId, struct MR_DRV_RAID_MAP_ALL *map); 2451u16 MR_TargetIdToLdGet(u32 ldTgtId, struct MR_DRV_RAID_MAP_ALL *map);
2452struct MR_LD_RAID *MR_LdRaidGet(u32 ld, struct MR_DRV_RAID_MAP_ALL *map); 2452struct MR_LD_RAID *MR_LdRaidGet(u32 ld, struct MR_DRV_RAID_MAP_ALL *map);
2453u16 MR_ArPdGet(u32 ar, u32 arm, struct MR_DRV_RAID_MAP_ALL *map); 2453u16 MR_ArPdGet(u32 ar, u32 arm, struct MR_DRV_RAID_MAP_ALL *map);
2454u16 MR_LdSpanArrayGet(u32 ld, u32 span, struct MR_DRV_RAID_MAP_ALL *map); 2454u16 MR_LdSpanArrayGet(u32 ld, u32 span, struct MR_DRV_RAID_MAP_ALL *map);
diff --git a/drivers/scsi/megaraid/megaraid_sas_fp.c b/drivers/scsi/megaraid/megaraid_sas_fp.c
index a0b0e68158ea..9d5d4851c0c4 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fp.c
+++ b/drivers/scsi/megaraid/megaraid_sas_fp.c
@@ -165,7 +165,7 @@ u16 MR_GetLDTgtId(u32 ld, struct MR_DRV_RAID_MAP_ALL *map)
165 return le16_to_cpu(map->raidMap.ldSpanMap[ld].ldRaid.targetId); 165 return le16_to_cpu(map->raidMap.ldSpanMap[ld].ldRaid.targetId);
166} 166}
167 167
168u8 MR_TargetIdToLdGet(u32 ldTgtId, struct MR_DRV_RAID_MAP_ALL *map) 168u16 MR_TargetIdToLdGet(u32 ldTgtId, struct MR_DRV_RAID_MAP_ALL *map)
169{ 169{
170 return map->raidMap.ldTgtIdToLd[ldTgtId]; 170 return map->raidMap.ldTgtIdToLd[ldTgtId];
171} 171}
@@ -1151,7 +1151,7 @@ MR_BuildRaidContext(struct megasas_instance *instance,
1151{ 1151{
1152 struct fusion_context *fusion; 1152 struct fusion_context *fusion;
1153 struct MR_LD_RAID *raid; 1153 struct MR_LD_RAID *raid;
1154 u32 ld, stripSize, stripe_mask; 1154 u32 stripSize, stripe_mask;
1155 u64 endLba, endStrip, endRow, start_row, start_strip; 1155 u64 endLba, endStrip, endRow, start_row, start_strip;
1156 u64 regStart; 1156 u64 regStart;
1157 u32 regSize; 1157 u32 regSize;
@@ -1163,6 +1163,7 @@ MR_BuildRaidContext(struct megasas_instance *instance,
1163 u8 retval = 0; 1163 u8 retval = 0;
1164 u8 startlba_span = SPAN_INVALID; 1164 u8 startlba_span = SPAN_INVALID;
1165 u64 *pdBlock = &io_info->pdBlock; 1165 u64 *pdBlock = &io_info->pdBlock;
1166 u16 ld;
1166 1167
1167 ldStartBlock = io_info->ldStartBlock; 1168 ldStartBlock = io_info->ldStartBlock;
1168 numBlocks = io_info->numBlocks; 1169 numBlocks = io_info->numBlocks;
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c
index 9019b82b467f..4aaf30769c94 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c
+++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c
@@ -1121,7 +1121,8 @@ megasas_sync_map_info(struct megasas_instance *instance)
1121 int i; 1121 int i;
1122 struct megasas_cmd *cmd; 1122 struct megasas_cmd *cmd;
1123 struct megasas_dcmd_frame *dcmd; 1123 struct megasas_dcmd_frame *dcmd;
1124 u32 size_sync_info, num_lds; 1124 u16 num_lds;
1125 u32 size_sync_info;
1125 struct fusion_context *fusion; 1126 struct fusion_context *fusion;
1126 struct MR_LD_TARGET_SYNC *ci = NULL; 1127 struct MR_LD_TARGET_SYNC *ci = NULL;
1127 struct MR_DRV_RAID_MAP_ALL *map; 1128 struct MR_DRV_RAID_MAP_ALL *map;
@@ -1870,7 +1871,7 @@ megasas_set_pd_lba(struct MPI2_RAID_SCSI_IO_REQUEST *io_request, u8 cdb_len,
1870 struct MR_DRV_RAID_MAP_ALL *local_map_ptr, u32 ref_tag) 1871 struct MR_DRV_RAID_MAP_ALL *local_map_ptr, u32 ref_tag)
1871{ 1872{
1872 struct MR_LD_RAID *raid; 1873 struct MR_LD_RAID *raid;
1873 u32 ld; 1874 u16 ld;
1874 u64 start_blk = io_info->pdBlock; 1875 u64 start_blk = io_info->pdBlock;
1875 u8 *cdb = io_request->CDB.CDB32; 1876 u8 *cdb = io_request->CDB.CDB32;
1876 u32 num_blocks = io_info->numBlocks; 1877 u32 num_blocks = io_info->numBlocks;
@@ -2303,10 +2304,11 @@ megasas_build_ldio_fusion(struct megasas_instance *instance,
2303 2304
2304 local_map_ptr = fusion->ld_drv_map[(instance->map_id & 1)]; 2305 local_map_ptr = fusion->ld_drv_map[(instance->map_id & 1)];
2305 ld = MR_TargetIdToLdGet(device_id, local_map_ptr); 2306 ld = MR_TargetIdToLdGet(device_id, local_map_ptr);
2306 raid = MR_LdRaidGet(ld, local_map_ptr);
2307 2307
2308 if ((MR_TargetIdToLdGet(device_id, local_map_ptr) >= 2308 if (ld < instance->fw_supported_vd_count)
2309 instance->fw_supported_vd_count) || (!fusion->fast_path_io)) { 2309 raid = MR_LdRaidGet(ld, local_map_ptr);
2310
2311 if (!raid || (!fusion->fast_path_io)) {
2310 io_request->RaidContext.raid_context.reg_lock_flags = 0; 2312 io_request->RaidContext.raid_context.reg_lock_flags = 0;
2311 fp_possible = false; 2313 fp_possible = false;
2312 } else { 2314 } else {
@@ -2478,12 +2480,12 @@ static void megasas_build_ld_nonrw_fusion(struct megasas_instance *instance,
2478{ 2480{
2479 u32 device_id; 2481 u32 device_id;
2480 struct MPI2_RAID_SCSI_IO_REQUEST *io_request; 2482 struct MPI2_RAID_SCSI_IO_REQUEST *io_request;
2481 u16 pd_index = 0; 2483 u16 pd_index = 0, ld;
2482 struct MR_DRV_RAID_MAP_ALL *local_map_ptr; 2484 struct MR_DRV_RAID_MAP_ALL *local_map_ptr;
2483 struct fusion_context *fusion = instance->ctrl_context; 2485 struct fusion_context *fusion = instance->ctrl_context;
2484 u8 span, physArm; 2486 u8 span, physArm;
2485 __le16 devHandle; 2487 __le16 devHandle;
2486 u32 ld, arRef, pd; 2488 u32 arRef, pd;
2487 struct MR_LD_RAID *raid; 2489 struct MR_LD_RAID *raid;
2488 struct RAID_CONTEXT *pRAID_Context; 2490 struct RAID_CONTEXT *pRAID_Context;
2489 u8 fp_possible = 1; 2491 u8 fp_possible = 1;
@@ -2506,10 +2508,11 @@ static void megasas_build_ld_nonrw_fusion(struct megasas_instance *instance,
2506 ld = MR_TargetIdToLdGet(device_id, local_map_ptr); 2508 ld = MR_TargetIdToLdGet(device_id, local_map_ptr);
2507 if (ld >= instance->fw_supported_vd_count) 2509 if (ld >= instance->fw_supported_vd_count)
2508 fp_possible = 0; 2510 fp_possible = 0;
2509 2511 else {
2510 raid = MR_LdRaidGet(ld, local_map_ptr); 2512 raid = MR_LdRaidGet(ld, local_map_ptr);
2511 if (!(raid->capability.fpNonRWCapable)) 2513 if (!(raid->capability.fpNonRWCapable))
2512 fp_possible = 0; 2514 fp_possible = 0;
2515 }
2513 } else 2516 } else
2514 fp_possible = 0; 2517 fp_possible = 0;
2515 2518