From 72aa4f57de83518bf87755545437b578ccadb835 Mon Sep 17 00:00:00 2001 From: yaozichen2025 Date: Sun, 4 Oct 2026 23:41:47 +0800 Subject: [PATCH] block: fix NULL deref and stack overflow in queue_wbt_class_conf_store The wbt_class_conf sysfs store has three input-parsing defects that crash the kernel on malformed input: 1. When the second token contains no \x27=\x27, strsep() sets p to NULL, and kstrtou64() is called with a NULL string before the existing \x27if (!p || rc)\x27 guard can run. The guard is dead code for the NULL case; reading a sysfs attribute value such as \x270 42\x27 dereferences NULL in lib/kstrtox.c. 2. rwb_to_wbt_class_info() returns NULL for wbt_class >= WBT_CLASS_NR after printing an error, but the result is dereferenced without a check. Writing a class index of 3 or more (for example \x275 max_depth=64\x27) faults at ti->min_depth. The sibling store queue_wbt_class_lat_store() already checks for NULL, so this asymmetry was clearly unintended. 3. sscanf() copies the token into tok[64] with an unbounded \x27%s\x27 conversion, so a token longer than 63 bytes overwrites the stack frame. Fix all three by bounding the conversion with \x27%63s\x27, splitting on the \x27=\x27 with strchr() and validating the result before kstrtou64(), and rejecting out-of-range classes with -EINVAL. Verified: with CONFIG_BLK_WBT=y + CONFIG_BLK_CGROUP=y the file builds cleanly; a user-space model of the parse (sscanf/strsep/kstrtou64 semantics of lib/string.c and lib/kstrtox.c) reproduces the oops on all three inputs and shows the fixed parser returns -EINVAL while accepting \x271 max_depth=64\x27 and \x271 max_depth=0x40\x27 unchanged. --- block/blk-wbt.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/block/blk-wbt.c b/block/blk-wbt.c index 61067e846a1b..c92381ee04c9 100644 --- a/block/blk-wbt.c +++ b/block/blk-wbt.c @@ -1714,18 +1714,21 @@ ssize_t queue_wbt_class_conf_store(struct request_queue *q, const char *page, rwb = RQWB(rqos); - if (sscanf(page, "%hu %s", &wbt_class, tok) != 2) + if (sscanf(page, "%hu %63s", &wbt_class, tok) != 2) return -EINVAL; if (tok[0] == '\0') return -EINVAL; - p = tok; - strsep(&p, "="); + p = strchr(tok, '='); + if (!p) + return -EINVAL; + *p++ = '\0'; rc = kstrtou64(p, 0, &val); - - if (!p || rc) + if (rc) return -EINVAL; ti = rwb_to_wbt_class_info(rwb, wbt_class); + if (!ti) + return -EINVAL; blk_mq_freeze_queue(q); blk_mq_quiesce_queue(q); -- Gitee