From: Yang Erkun <yangerkun@huawei.com>
To: dgilbert@interlog.com, James.Bottomley@HansenPartnership.com,
martin.petersen@oracle.com, yukuai@kernel.org, hch@lst.de,
axboe@kernel.dk
Cc: linux-scsi@vger.kernel.org, linux-block@vger.kernel.org,
yangerkun@huawei.com
Subject: [PATCH] scsi: sg: validate and round up scatter_elem_sz module parameter
Date: Wed, 8 Jul 2026 14:30:45 +0800 [thread overview]
Message-ID: <20260708063045.2008478-1-yangerkun@huawei.com> (raw)
echo -1 or 0 > /sys/module/sg/parameters/scatter_elem_sz
exec 4<> /dev/sg0
The preferred shell trigger 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:
<TASK>
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.
Additionally, the code handling scatter_elem_sz is refactored for
clarity: the scatter_elem_sz_prev variable and the runtime fixup logic
in sg_build_indirect() are removed. The entry fixup (syncing
scatter_elem_sz_prev to scatter_elem_sz) was fragile -- it updated
scatter_elem_sz_prev but not the local variable "num", which is the
exact source of the UBSAN warning. The in-loop fixup (updating
scatter_elem_sz to ret_sz when ret_sz > scatter_elem_sz_prev) is no
longer needed because the .set callback rounds up scatter_elem_sz to a
power-of-two multiple of PAGE_SIZE, making it always equal to ret_sz.
The init_sg boot-time clamp is also removed as SG_SCATTER_SZ (32768)
is always >= PAGE_SIZE.
Fixes: 6460e75a104d ("[SCSI] sg: fixes for large page_size")
Signed-off-by: Yang Erkun <yangerkun@huawei.com>
---
drivers/scsi/sg.c | 68 +++++++++++++++++++++++------------------------
1 file changed, 34 insertions(+), 34 deletions(-)
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 74cd4e8a61c2..377c3e1dee7f 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -92,7 +92,6 @@ static int def_reserved_size = SG_DEF_RESERVED_SIZE;
static int sg_allow_dio = SG_ALLOW_DIO_DEF;
static int scatter_elem_sz = SG_SCATTER_SZ;
-static int scatter_elem_sz_prev = SG_SCATTER_SZ;
#define SG_SECTOR_SZ 512
@@ -1622,8 +1621,34 @@ 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);
-module_param_named(allow_dio, sg_allow_dio, 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, 0644);
static int def_reserved_size_set(const char *val, const struct kernel_param *kp)
{
@@ -1649,8 +1674,7 @@ static const struct kernel_param_ops def_reserved_size_ops = {
.get = param_get_int,
};
-module_param_cb(def_reserved_size, &def_reserved_size_ops, &def_reserved_size,
- S_IRUGO | S_IWUSR);
+module_param_cb(def_reserved_size, &def_reserved_size_ops, &def_reserved_size, 0644);
MODULE_AUTHOR("Douglas Gilbert");
MODULE_DESCRIPTION("SCSI generic (sg) driver");
@@ -1668,11 +1692,6 @@ init_sg(void)
{
int rc;
- if (scatter_elem_sz < PAGE_SIZE) {
- scatter_elem_sz = PAGE_SIZE;
- scatter_elem_sz_prev = scatter_elem_sz;
- }
-
rc = register_chrdev_region(MKDEV(SCSI_GENERIC_MAJOR, 0),
SG_MAX_DEVS, "sg");
if (rc)
@@ -1854,9 +1873,10 @@ sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp, int tablesize)
static int
sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size)
{
- int ret_sz = 0, i, k, rem_sz, num, mx_sc_elems;
+ int ret_sz = 0, i, k, rem_sz, mx_sc_elems;
int sg_tablesize = sfp->parentdp->sg_tablesize;
int blk_size = buff_size, order;
+ int elem_sz = scatter_elem_sz;
gfp_t gfp_mask = GFP_ATOMIC | __GFP_COMP | __GFP_NOWARN | __GFP_ZERO;
if (blk_size < 0)
@@ -1874,39 +1894,19 @@ sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size)
if (mx_sc_elems < 0)
return mx_sc_elems; /* most likely -ENOMEM */
- num = scatter_elem_sz;
- if (unlikely(num != scatter_elem_sz_prev)) {
- if (num < PAGE_SIZE) {
- scatter_elem_sz = PAGE_SIZE;
- scatter_elem_sz_prev = PAGE_SIZE;
- } else
- scatter_elem_sz_prev = num;
- }
-
- order = get_order(num);
+ order = get_order(elem_sz);
retry:
ret_sz = 1 << (PAGE_SHIFT + order);
for (k = 0, rem_sz = blk_size; rem_sz > 0 && k < mx_sc_elems;
k++, rem_sz -= ret_sz) {
-
- num = (rem_sz > scatter_elem_sz_prev) ?
- scatter_elem_sz_prev : rem_sz;
-
schp->pages[k] = alloc_pages(gfp_mask, order);
if (!schp->pages[k])
goto out;
- if (num == scatter_elem_sz_prev) {
- if (unlikely(ret_sz > scatter_elem_sz_prev)) {
- scatter_elem_sz = ret_sz;
- scatter_elem_sz_prev = ret_sz;
- }
- }
-
SCSI_LOG_TIMEOUT(5, sg_printk(KERN_INFO, sfp->parentdp,
- "sg_build_indirect: k=%d, num=%d, ret_sz=%d\n",
- k, num, ret_sz));
+ "%s: k=%d, ret_sz=%d\n",
+ __func__, k, ret_sz));
} /* end of for loop */
schp->page_order = order;
--
2.52.0
next reply other threads:[~2026-07-08 6:38 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-08 6:30 Yang Erkun [this message]
2026-07-08 16:10 ` [PATCH] scsi: sg: validate and round up scatter_elem_sz module parameter Bart Van Assche
2026-07-09 0:59 ` yangerkun
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260708063045.2008478-1-yangerkun@huawei.com \
--to=yangerkun@huawei.com \
--cc=James.Bottomley@HansenPartnership.com \
--cc=axboe@kernel.dk \
--cc=dgilbert@interlog.com \
--cc=hch@lst.de \
--cc=linux-block@vger.kernel.org \
--cc=linux-scsi@vger.kernel.org \
--cc=martin.petersen@oracle.com \
--cc=yukuai@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox