FROMLIST: scsi: ufs: Fix memory corruption by ufshcd_read_desc_param()
Running the following commands on my test setup triggers stack corruption: cd /sys/devices/platform/14700000.ufs/host0/target0:0:0 && for f in $(ls */unit_descriptor/hpb_pinned_region_start_offset | sort); do grep -aH . $f done The above commands trigger stack corruption because these commands assign the value 37 to the variable 'param_offset' and the value 35 to 'buff_len'. The following code changes param_size from 2 into 254 since 'param_size' has type u8: if (param_offset + param_size > buff_len) param_size = buff_len - param_offset; The next statement triggers stack corruption since 'param_read_buf' points at a two-byte stack array: memcpy(param_read_buf, &desc_buf[param_offset], param_size); With this patch applied, the output of the above command on my test setup is as follows: 0:0:0:0/unit_descriptor/hpb_pinned_region_start_offset:0x0000 0:0:0:1/unit_descriptor/hpb_pinned_region_start_offset:0x0000 0:0:0:2/unit_descriptor/hpb_pinned_region_start_offset:0x0000 0:0:0:3/unit_descriptor/hpb_pinned_region_start_offset:0x0000 grep: 0:0:0:49456/unit_descriptor/hpb_pinned_region_start_offset: Invalid argument grep: 0:0:0:49476/unit_descriptor/hpb_pinned_region_start_offset: Invalid argument grep: 0:0:0:49488/unit_descriptor/hpb_pinned_region_start_offset: Invalid argument Link: https://lore.kernel.org/linux-scsi/20210719231127.869088-1-bvanassche@acm.org/T/#u Bug: 194045295 Change-Id: I305c15b20f3ac3d6e3e97592566fcc51058195bb Signed-off-by: Bart Van Assche <bvanassche@google.com>
This commit is contained in:
@@ -3393,9 +3393,11 @@ int ufshcd_read_desc_param(struct ufs_hba *hba,
|
|||||||
|
|
||||||
if (is_kmalloc) {
|
if (is_kmalloc) {
|
||||||
/* Make sure we don't copy more data than available */
|
/* Make sure we don't copy more data than available */
|
||||||
if (param_offset + param_size > buff_len)
|
if (param_offset >= buff_len)
|
||||||
param_size = buff_len - param_offset;
|
ret = -EINVAL;
|
||||||
memcpy(param_read_buf, &desc_buf[param_offset], param_size);
|
else
|
||||||
|
memcpy(param_read_buf, &desc_buf[param_offset],
|
||||||
|
min_t(u32, param_size, buff_len - param_offset));
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
if (is_kmalloc)
|
if (is_kmalloc)
|
||||||
|
Reference in New Issue
Block a user