echo -1 or 0 > /sys/module/sg/parameters/scatter_elem_sz exec 4<> /dev/sg0 The above triggers the following UBSAN warning: UBSAN: shift-out-of-bounds in drivers/scsi/sg.c:1888:13 shift exponent 64 is too large for 32-bit type 'int' ..... Call Trace: dump_stack_lvl+0x64/0x80 __ubsan_handle_shift_out_of_bounds+0x1d1/0x380 sg_build_indirect.cold+0x38/0x4b sg_build_reserve+0x59/0x90 sg_add_sfp+0x151/0x240 sg_open+0x169/0x310 chrdev_open+0xbe/0x240 do_dentry_open+0x121/0x480 vfs_open+0x2e/0xf0 do_open+0x265/0x400 path_openat+0x110/0x2b0 do_file_open+0xe4/0x1a0 do_sys_openat2+0x7f/0xe0 __x64_sys_openat+0x56/0xa0 do_syscall_64+0xf5/0x640 entry_SYSCALL_64_after_hwframe+0x76/0x7e The scatter_elem_sz module parameter currently lacks validation. Setting it to -1/0 causes a left shift overflow in sg_build_indirect. Although this overflow does not currently cause other problem, allowing scatter_elem_sz to be set to -1/0 is not appropriate given its intended purpose. Therefore, this patch uses module_param_call to add validation checks: reject non-positive values and values whose order exceeds MAX_PAGE_ORDER, and round the accepted value up to a power-of-two multiple of PAGE_SIZE. Fixes: 6460e75a104d ("[SCSI] sg: fixes for large page_size") Signed-off-by: Yang Erkun --- drivers/scsi/sg.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 74cd4e8a61c2..c56f8460c03f 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -1622,7 +1622,33 @@ sg_remove_device(struct device *cl_dev) kref_put(&sdp->d_ref, sg_device_destroy); } -module_param_named(scatter_elem_sz, scatter_elem_sz, int, S_IRUGO | S_IWUSR); +static int scatter_elem_sz_set(const char *val, const struct kernel_param *kp) +{ + int ret, new_val, order; + + ret = kstrtoint(val, 0, &new_val); + if (ret) + return ret; + + if (new_val <= 0) { + pr_err("sg: scatter_elem_sz must be positive, got %d\n", new_val); + return -EINVAL; + } + + order = get_order(new_val); + if (order > MAX_PAGE_ORDER) { + pr_err("sg: scatter_elem_sz too large (order %d > MAX_PAGE_ORDER %d)\n", + order, MAX_PAGE_ORDER); + return -EINVAL; + } + + scatter_elem_sz = 1 << (PAGE_SHIFT + order); + return 0; +} + +module_param_call(scatter_elem_sz, scatter_elem_sz_set, param_get_int, + &scatter_elem_sz, 0644); + module_param_named(allow_dio, sg_allow_dio, int, S_IRUGO | S_IWUSR); static int def_reserved_size_set(const char *val, const struct kernel_param *kp) -- 2.52.0