[PATCH] scsi: scsi_debug: fix type in min_t to avoid stack OOB

From: George Kennedy
Date: Tue Nov 02 2021 - 08:50:27 EST


Change min_t() to use type "unsigned int" instead of type "int" to
avoid stack out of bounds. With min_t() type "int" the values get
sign extended and the larger value gets used causing stack out of bounds.

Reported-by: syzkaller <syzkaller@xxxxxxxxxxxxxxxx>
Signed-off-by: George Kennedy <george.kennedy@xxxxxxxxxx>

BUG: KASAN: stack-out-of-bounds in memcpy include/linux/fortify-string.h:191 [inline]
BUG: KASAN: stack-out-of-bounds in sg_copy_buffer+0x1de/0x240 lib/scatterlist.c:976
Read of size 127 at addr ffff888072607128 by task syz-executor.7/18707

CPU: 1 PID: 18707 Comm: syz-executor.7 Not tainted 5.15.0-syzk #1
Hardware name: Red Hat KVM, BIOS 1.13.0-2.module+el8.3.0+7860+a7792d29 04/01/2014
Call Trace:
__dump_stack lib/dump_stack.c:88 [inline]
dump_stack_lvl+0x89/0xb5 lib/dump_stack.c:106
print_address_description.constprop.9+0x28/0x160 mm/kasan/report.c:256
__kasan_report mm/kasan/report.c:442 [inline]
kasan_report.cold.14+0x7d/0x117 mm/kasan/report.c:459
check_region_inline mm/kasan/generic.c:183 [inline]
kasan_check_range+0x1a3/0x210 mm/kasan/generic.c:189
memcpy+0x23/0x60 mm/kasan/shadow.c:65
memcpy include/linux/fortify-string.h:191 [inline]
sg_copy_buffer+0x1de/0x240 lib/scatterlist.c:976
sg_copy_from_buffer+0x33/0x40 lib/scatterlist.c:1000
fill_from_dev_buffer.part.34+0x82/0x130 drivers/scsi/scsi_debug.c:1162
fill_from_dev_buffer drivers/scsi/scsi_debug.c:1888 [inline]
resp_readcap16+0x365/0x3b0 drivers/scsi/scsi_debug.c:1887
schedule_resp+0x4d8/0x1a70 drivers/scsi/scsi_debug.c:5478
scsi_debug_queuecommand+0x8c9/0x1ec0 drivers/scsi/scsi_debug.c:7533
scsi_dispatch_cmd drivers/scsi/scsi_lib.c:1520 [inline]
scsi_queue_rq+0x16b0/0x2d40 drivers/scsi/scsi_lib.c:1699
blk_mq_dispatch_rq_list+0xb9b/0x2700 block/blk-mq.c:1639
__blk_mq_sched_dispatch_requests+0x28f/0x590 block/blk-mq-sched.c:325
blk_mq_sched_dispatch_requests+0x105/0x190 block/blk-mq-sched.c:358
__blk_mq_run_hw_queue+0xe5/0x150 block/blk-mq.c:1761
__blk_mq_delay_run_hw_queue+0x4f8/0x5c0 block/blk-mq.c:1838
blk_mq_run_hw_queue+0x18d/0x350 block/blk-mq.c:1891
blk_mq_sched_insert_request+0x3db/0x4e0 block/blk-mq-sched.c:474
blk_execute_rq_nowait+0x16b/0x1c0 block/blk-exec.c:62
sg_common_write.isra.18+0xeb3/0x2000 drivers/scsi/sg.c:836
sg_new_write.isra.19+0x570/0x8c0 drivers/scsi/sg.c:774
sg_ioctl_common+0x14d6/0x2710 drivers/scsi/sg.c:939
sg_ioctl+0xa2/0x180 drivers/scsi/sg.c:1165
vfs_ioctl fs/ioctl.c:51 [inline]
__do_sys_ioctl fs/ioctl.c:874 [inline]
__se_sys_ioctl fs/ioctl.c:860 [inline]
__x64_sys_ioctl+0x19d/0x220 fs/ioctl.c:860
do_syscall_x64 arch/x86/entry/common.c:50 [inline]
do_syscall_64+0x3a/0x80 arch/x86/entry/common.c:80
entry_SYSCALL_64_after_hwframe+0x44/0xae
---
drivers/scsi/scsi_debug.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 40b473e..e4c48fb 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -1189,7 +1189,7 @@ static int p_fill_from_dev_buffer(struct scsi_cmnd *scp, const void *arr,
__func__, off_dst, scsi_bufflen(scp), act_len,
scsi_get_resid(scp));
n = scsi_bufflen(scp) - (off_dst + act_len);
- scsi_set_resid(scp, min_t(int, scsi_get_resid(scp), n));
+ scsi_set_resid(scp, min_t(unsigned int, scsi_get_resid(scp), n));
return 0;
}

@@ -1714,7 +1714,7 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
}
put_unaligned_be16(0x2100, arr + n); /* SPL-4 no version claimed */
ret = fill_from_dev_buffer(scp, arr,
- min_t(int, alloc_len, SDEBUG_LONG_INQ_SZ));
+ min_t(unsigned int, alloc_len, SDEBUG_LONG_INQ_SZ));
kfree(arr);
return ret;
}
@@ -1774,7 +1774,7 @@ static int resp_requests(struct scsi_cmnd *scp,
arr[7] = 0xa;
}
}
- return fill_from_dev_buffer(scp, arr, min_t(int, len, alloc_len));
+ return fill_from_dev_buffer(scp, arr, min_t(unsigned int, len, alloc_len));
}

static int resp_start_stop(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
@@ -1885,7 +1885,7 @@ static int resp_readcap16(struct scsi_cmnd *scp,
}

return fill_from_dev_buffer(scp, arr,
- min_t(int, alloc_len, SDEBUG_READCAP16_ARR_SZ));
+ min_t(unsigned int, alloc_len, SDEBUG_READCAP16_ARR_SZ));
}

#define SDEBUG_MAX_TGTPGS_ARR_SZ 1412
@@ -1959,9 +1959,9 @@ static int resp_report_tgtpgs(struct scsi_cmnd *scp,
* - The constructed command length
* - The maximum array size
*/
- rlen = min_t(int, alen, n);
+ rlen = min_t(unsigned int, alen, n);
ret = fill_from_dev_buffer(scp, arr,
- min_t(int, rlen, SDEBUG_MAX_TGTPGS_ARR_SZ));
+ min_t(unsigned int, rlen, SDEBUG_MAX_TGTPGS_ARR_SZ));
kfree(arr);
return ret;
}
@@ -2467,7 +2467,7 @@ static int resp_mode_sense(struct scsi_cmnd *scp,
arr[0] = offset - 1;
else
put_unaligned_be16((offset - 2), arr + 0);
- return fill_from_dev_buffer(scp, arr, min_t(int, alloc_len, offset));
+ return fill_from_dev_buffer(scp, arr, min_t(unsigned int, alloc_len, offset));
}

#define SDEBUG_MAX_MSELECT_SZ 512
@@ -2652,9 +2652,9 @@ static int resp_log_sense(struct scsi_cmnd *scp,
mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1);
return check_condition_result;
}
- len = min_t(int, get_unaligned_be16(arr + 2) + 4, alloc_len);
+ len = min_t(unsigned int, get_unaligned_be16(arr + 2) + 4, alloc_len);
return fill_from_dev_buffer(scp, arr,
- min_t(int, len, SDEBUG_MAX_INQ_ARR_SZ));
+ min_t(unsigned int, len, SDEBUG_MAX_INQ_ARR_SZ));
}

static inline bool sdebug_dev_is_zoned(struct sdebug_dev_info *devip)
@@ -4425,7 +4425,7 @@ static int resp_report_zones(struct scsi_cmnd *scp,
put_unaligned_be64(sdebug_capacity - 1, arr + 8);

rep_len = (unsigned long)desc - (unsigned long)arr;
- ret = fill_from_dev_buffer(scp, arr, min_t(int, alloc_len, rep_len));
+ ret = fill_from_dev_buffer(scp, arr, min_t(unsigned int, alloc_len, rep_len));

fini:
read_unlock(macc_lckp);
--
1.8.3.1