Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
- kernel/bpf/verifier.c | 25 ++++++++++++++++++-------
+ kernel/bpf/verifier.c | 25 ++++++++++++++++++-------
1 file changed, 18 insertions(+), 7 deletions(-)
-diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
-index e06b84c7b890..7b461a70a0e6 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
-@@ -2278,13 +2278,24 @@ static bool __is_pointer_value(bool allow_ptr_leaks,
+@@ -2274,13 +2274,24 @@ static bool __is_pointer_value(bool allo
return reg->type != SCALAR_VALUE;
}
if (size == BPF_REG_SIZE)
state->stack[spi].spilled_ptr.live |= REG_LIVE_WRITTEN;
-@@ -2612,7 +2623,7 @@ static int check_stack_read_fixed_off(struct bpf_verifier_env *env,
+@@ -2608,7 +2619,7 @@ static int check_stack_read_fixed_off(st
*/
s32 subreg_def = state->regs[dst_regno].subreg_def;
state->regs[dst_regno].subreg_def = subreg_def;
} else {
for (i = 0; i < size; i++) {
-@@ -2639,7 +2650,7 @@ static int check_stack_read_fixed_off(struct bpf_verifier_env *env,
+@@ -2635,7 +2646,7 @@ static int check_stack_read_fixed_off(st
if (dst_regno >= 0) {
/* restore register state from stack */
/* mark reg as written since spilled pointer state likely
* has its liveness marks cleared by is_state_visited()
* which resets stack/reg liveness for state transitions
-@@ -5900,7 +5911,7 @@ static int sanitize_ptr_alu(struct bpf_verifier_env *env,
+@@ -5896,7 +5907,7 @@ do_sim:
*/
if (!ptr_is_dst_reg) {
tmp = *dst_reg;
}
ret = sanitize_speculative_path(env, NULL, env->insn_idx + 1,
env->insn_idx);
-@@ -7154,7 +7165,7 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)
+@@ -7150,7 +7161,7 @@ static int check_alu_op(struct bpf_verif
* to propagate min/max range.
*/
src_reg->id = ++env->id_gen;
dst_reg->live |= REG_LIVE_WRITTEN;
dst_reg->subreg_def = DEF_NOT_SUBREG;
} else {
-@@ -7165,7 +7176,7 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)
+@@ -7161,7 +7172,7 @@ static int check_alu_op(struct bpf_verif
insn->src_reg);
return -EACCES;
} else if (src_reg->type == SCALAR_VALUE) {
/* Make sure ID is cleared otherwise
* dst_reg min/max could be incorrectly
* propagated into src_reg by find_equal_scalars()
-@@ -7985,7 +7996,7 @@ static void find_equal_scalars(struct bpf_verifier_state *vstate,
+@@ -7981,7 +7992,7 @@ static void find_equal_scalars(struct bp
bpf_for_each_reg_in_vstate(vstate, state, reg, ({
if (reg->type == SCALAR_VALUE && reg->id == known_reg->id)
}));
}
---
-2.39.0
-
Stable-dep-of: 71f656a50176 ("bpf: Fix to preserve reg parent/live fields when copying range info")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
- kernel/bpf/verifier.c | 67 +++++++++++++++++++++++++++++++++----------
+ kernel/bpf/verifier.c | 67 ++++++++++++++++++++++++++++++++++++++------------
1 file changed, 52 insertions(+), 15 deletions(-)
-diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
-index a6c931fed39b..e06b84c7b890 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
-@@ -570,6 +570,12 @@ static bool is_spilled_reg(const struct bpf_stack_state *stack)
+@@ -570,6 +570,12 @@ static bool is_spilled_reg(const struct
return stack->slot_type[BPF_REG_SIZE - 1] == STACK_SPILL;
}
static void print_verifier_state(struct bpf_verifier_env *env,
const struct bpf_func_state *state)
{
-@@ -2273,15 +2279,21 @@ static bool __is_pointer_value(bool allow_ptr_leaks,
+@@ -2269,15 +2275,21 @@ static bool __is_pointer_value(bool allo
}
static void save_register_state(struct bpf_func_state *state,
}
/* check_stack_{read,write}_fixed_off functions track spill/fill of registers,
-@@ -2331,7 +2343,7 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env,
+@@ -2327,7 +2339,7 @@ static int check_stack_write_fixed_off(s
env->insn_aux_data[insn_idx].sanitize_stack_spill = true;
}
!register_is_null(reg) && env->bpf_capable) {
if (dst_reg != BPF_REG_FP) {
/* The backtracking logic can only recognize explicit
-@@ -2344,7 +2356,7 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env,
+@@ -2340,7 +2352,7 @@ static int check_stack_write_fixed_off(s
if (err)
return err;
}
} else if (reg && is_spillable_regtype(reg->type)) {
/* register containing pointer is being spilled into stack */
if (size != BPF_REG_SIZE) {
-@@ -2356,7 +2368,7 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env,
+@@ -2352,7 +2364,7 @@ static int check_stack_write_fixed_off(s
verbose(env, "cannot spill pointers to stack into stack frame of the caller\n");
return -EINVAL;
}
} else {
u8 type = STACK_MISC;
-@@ -2365,7 +2377,7 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env,
+@@ -2361,7 +2373,7 @@ static int check_stack_write_fixed_off(s
/* Mark slots as STACK_MISC if they belonged to spilled ptr. */
if (is_spilled_reg(&state->stack[spi]))
for (i = 0; i < BPF_REG_SIZE; i++)
/* only mark the slot as written if all 8 bytes were written
* otherwise read propagation may incorrectly stop too soon
-@@ -2572,23 +2584,50 @@ static int check_stack_read_fixed_off(struct bpf_verifier_env *env,
+@@ -2568,23 +2580,50 @@ static int check_stack_read_fixed_off(st
struct bpf_func_state *state = vstate->frame[vstate->curframe];
int i, slot = -off - 1, spi = slot / BPF_REG_SIZE;
struct bpf_reg_state *reg;
return 0;
}
for (i = 1; i < BPF_REG_SIZE; i++) {
-@@ -2619,8 +2658,6 @@ static int check_stack_read_fixed_off(struct bpf_verifier_env *env,
+@@ -2615,8 +2654,6 @@ static int check_stack_read_fixed_off(st
}
mark_reg_read(env, reg, reg->parent, REG_LIVE_READ64);
} else {
for (i = 0; i < size; i++) {
type = stype[(slot - i) % BPF_REG_SIZE];
if (type == STACK_MISC)
-@@ -4106,7 +4143,7 @@ static int check_stack_range_initialized(
+@@ -4102,7 +4139,7 @@ static int check_stack_range_initialized
if (clobber) {
__mark_reg_unknown(env, &state->stack[spi].spilled_ptr);
for (j = 0; j < BPF_REG_SIZE; j++)
}
goto mark;
}
---
-2.39.0
-
--- /dev/null
+From d3b7b4afd6b2c344eabf9cc26b8bfa903c164c7c Mon Sep 17 00:00:00 2001
+From: Chao Yu <chao@kernel.org>
+Date: Tue, 15 Nov 2022 00:08:47 +0800
+Subject: f2fs: fix to do sanity check on i_extra_isize in is_alive()
+
+From: Chao Yu <chao@kernel.org>
+
+commit d3b7b4afd6b2c344eabf9cc26b8bfa903c164c7c upstream.
+
+syzbot found a f2fs bug:
+
+BUG: KASAN: slab-out-of-bounds in data_blkaddr fs/f2fs/f2fs.h:2891 [inline]
+BUG: KASAN: slab-out-of-bounds in is_alive fs/f2fs/gc.c:1117 [inline]
+BUG: KASAN: slab-out-of-bounds in gc_data_segment fs/f2fs/gc.c:1520 [inline]
+BUG: KASAN: slab-out-of-bounds in do_garbage_collect+0x386a/0x3df0 fs/f2fs/gc.c:1734
+Read of size 4 at addr ffff888076557568 by task kworker/u4:3/52
+
+CPU: 1 PID: 52 Comm: kworker/u4:3 Not tainted 6.1.0-rc4-syzkaller-00362-gfef7fd48922d #0
+Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/26/2022
+Workqueue: writeback wb_workfn (flush-7:0)
+Call Trace:
+<TASK>
+__dump_stack lib/dump_stack.c:88 [inline]
+dump_stack_lvl+0xcd/0x134 lib/dump_stack.c:106
+print_address_description mm/kasan/report.c:284 [inline]
+print_report+0x15e/0x45d mm/kasan/report.c:395
+kasan_report+0xbb/0x1f0 mm/kasan/report.c:495
+data_blkaddr fs/f2fs/f2fs.h:2891 [inline]
+is_alive fs/f2fs/gc.c:1117 [inline]
+gc_data_segment fs/f2fs/gc.c:1520 [inline]
+do_garbage_collect+0x386a/0x3df0 fs/f2fs/gc.c:1734
+f2fs_gc+0x88c/0x20a0 fs/f2fs/gc.c:1831
+f2fs_balance_fs+0x544/0x6b0 fs/f2fs/segment.c:410
+f2fs_write_inode+0x57e/0xe20 fs/f2fs/inode.c:753
+write_inode fs/fs-writeback.c:1440 [inline]
+__writeback_single_inode+0xcfc/0x1440 fs/fs-writeback.c:1652
+writeback_sb_inodes+0x54d/0xf90 fs/fs-writeback.c:1870
+wb_writeback+0x2c5/0xd70 fs/fs-writeback.c:2044
+wb_do_writeback fs/fs-writeback.c:2187 [inline]
+wb_workfn+0x2dc/0x12f0 fs/fs-writeback.c:2227
+process_one_work+0x9bf/0x1710 kernel/workqueue.c:2289
+worker_thread+0x665/0x1080 kernel/workqueue.c:2436
+kthread+0x2e4/0x3a0 kernel/kthread.c:376
+ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:306
+
+The root cause is that we forgot to do sanity check on .i_extra_isize
+in below path, result in accessing invalid address later, fix it.
+- gc_data_segment
+ - is_alive
+ - data_blkaddr
+ - offset_in_addr
+
+Reported-by: syzbot+f8f3dfa4abc489e768a1@syzkaller.appspotmail.com
+Link: https://lore.kernel.org/linux-f2fs-devel/0000000000003cb3c405ed5c17f9@google.com/T/#u
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/gc.c | 18 ++++++++++++------
+ 1 file changed, 12 insertions(+), 6 deletions(-)
+
+--- a/fs/f2fs/gc.c
++++ b/fs/f2fs/gc.c
+@@ -977,7 +977,7 @@ static bool is_alive(struct f2fs_sb_info
+ {
+ struct page *node_page;
+ nid_t nid;
+- unsigned int ofs_in_node, max_addrs;
++ unsigned int ofs_in_node, max_addrs, base;
+ block_t source_blkaddr;
+
+ nid = le32_to_cpu(sum->nid);
+@@ -1003,11 +1003,17 @@ static bool is_alive(struct f2fs_sb_info
+ return false;
+ }
+
+- max_addrs = IS_INODE(node_page) ? DEF_ADDRS_PER_INODE :
+- DEF_ADDRS_PER_BLOCK;
+- if (ofs_in_node >= max_addrs) {
+- f2fs_err(sbi, "Inconsistent ofs_in_node:%u in summary, ino:%u, nid:%u, max:%u",
+- ofs_in_node, dni->ino, dni->nid, max_addrs);
++ if (IS_INODE(node_page)) {
++ base = offset_in_addr(F2FS_INODE(node_page));
++ max_addrs = DEF_ADDRS_PER_INODE;
++ } else {
++ base = 0;
++ max_addrs = DEF_ADDRS_PER_BLOCK;
++ }
++
++ if (base + ofs_in_node >= max_addrs) {
++ f2fs_err(sbi, "Inconsistent blkaddr offset: base:%u, ofs_in_node:%u, max:%u, ino:%u, nid:%u",
++ base, ofs_in_node, max_addrs, dni->ino, dni->nid);
+ f2fs_put_page(node_page, 1);
+ return false;
+ }
--- /dev/null
+From b76449ee75e21acfe9fa4c653d8598f191ed7d68 Mon Sep 17 00:00:00 2001
+From: Dongliang Mu <dzm91@hust.edu.cn>
+Date: Fri, 11 Nov 2022 13:49:49 +0800
+Subject: fbdev: smscufx: fix error handling code in ufx_usb_probe
+
+From: Dongliang Mu <dzm91@hust.edu.cn>
+
+commit b76449ee75e21acfe9fa4c653d8598f191ed7d68 upstream.
+
+The current error handling code in ufx_usb_probe have many unmatching
+issues, e.g., missing ufx_free_usb_list, destroy_modedb label should
+only include framebuffer_release, fb_dealloc_cmap only matches
+fb_alloc_cmap.
+
+My local syzkaller reports a memory leak bug:
+
+memory leak in ufx_usb_probe
+
+BUG: memory leak
+unreferenced object 0xffff88802f879580 (size 128):
+ comm "kworker/0:7", pid 17416, jiffies 4295067474 (age 46.710s)
+ hex dump (first 32 bytes):
+ 80 21 7c 2e 80 88 ff ff 18 d0 d0 0c 80 88 ff ff .!|.............
+ 00 d0 d0 0c 80 88 ff ff e0 ff ff ff 0f 00 00 00 ................
+ backtrace:
+ [<ffffffff814c99a0>] kmalloc_trace+0x20/0x90 mm/slab_common.c:1045
+ [<ffffffff824d219c>] kmalloc include/linux/slab.h:553 [inline]
+ [<ffffffff824d219c>] kzalloc include/linux/slab.h:689 [inline]
+ [<ffffffff824d219c>] ufx_alloc_urb_list drivers/video/fbdev/smscufx.c:1873 [inline]
+ [<ffffffff824d219c>] ufx_usb_probe+0x11c/0x15a0 drivers/video/fbdev/smscufx.c:1655
+ [<ffffffff82d17927>] usb_probe_interface+0x177/0x370 drivers/usb/core/driver.c:396
+ [<ffffffff82712f0d>] call_driver_probe drivers/base/dd.c:560 [inline]
+ [<ffffffff82712f0d>] really_probe+0x12d/0x390 drivers/base/dd.c:639
+ [<ffffffff8271322f>] __driver_probe_device+0xbf/0x140 drivers/base/dd.c:778
+ [<ffffffff827132da>] driver_probe_device+0x2a/0x120 drivers/base/dd.c:808
+ [<ffffffff82713c27>] __device_attach_driver+0xf7/0x150 drivers/base/dd.c:936
+ [<ffffffff82710137>] bus_for_each_drv+0xb7/0x100 drivers/base/bus.c:427
+ [<ffffffff827136b5>] __device_attach+0x105/0x2d0 drivers/base/dd.c:1008
+ [<ffffffff82711d36>] bus_probe_device+0xc6/0xe0 drivers/base/bus.c:487
+ [<ffffffff8270e242>] device_add+0x642/0xdc0 drivers/base/core.c:3517
+ [<ffffffff82d14d5f>] usb_set_configuration+0x8ef/0xb80 drivers/usb/core/message.c:2170
+ [<ffffffff82d2576c>] usb_generic_driver_probe+0x8c/0xc0 drivers/usb/core/generic.c:238
+ [<ffffffff82d16ffc>] usb_probe_device+0x5c/0x140 drivers/usb/core/driver.c:293
+ [<ffffffff82712f0d>] call_driver_probe drivers/base/dd.c:560 [inline]
+ [<ffffffff82712f0d>] really_probe+0x12d/0x390 drivers/base/dd.c:639
+ [<ffffffff8271322f>] __driver_probe_device+0xbf/0x140 drivers/base/dd.c:778
+
+Fix this bug by rewriting the error handling code in ufx_usb_probe.
+
+Reported-by: syzkaller <syzkaller@googlegroups.com>
+Tested-by: Dongliang Mu <dzm91@hust.edu.cn>
+Signed-off-by: Dongliang Mu <dzm91@hust.edu.cn>
+Signed-off-by: Helge Deller <deller@gmx.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/video/fbdev/smscufx.c | 46 ++++++++++++++++++++++++++++--------------
+ 1 file changed, 31 insertions(+), 15 deletions(-)
+
+--- a/drivers/video/fbdev/smscufx.c
++++ b/drivers/video/fbdev/smscufx.c
+@@ -1621,7 +1621,7 @@ static int ufx_usb_probe(struct usb_inte
+ struct usb_device *usbdev;
+ struct ufx_data *dev;
+ struct fb_info *info;
+- int retval;
++ int retval = -ENOMEM;
+ u32 id_rev, fpga_rev;
+
+ /* usb initialization */
+@@ -1653,15 +1653,17 @@ static int ufx_usb_probe(struct usb_inte
+
+ if (!ufx_alloc_urb_list(dev, WRITES_IN_FLIGHT, MAX_TRANSFER)) {
+ dev_err(dev->gdev, "ufx_alloc_urb_list failed\n");
+- goto e_nomem;
++ goto put_ref;
+ }
+
+ /* We don't register a new USB class. Our client interface is fbdev */
+
+ /* allocates framebuffer driver structure, not framebuffer memory */
+ info = framebuffer_alloc(0, &usbdev->dev);
+- if (!info)
+- goto e_nomem;
++ if (!info) {
++ dev_err(dev->gdev, "framebuffer_alloc failed\n");
++ goto free_urb_list;
++ }
+
+ dev->info = info;
+ info->par = dev;
+@@ -1704,22 +1706,34 @@ static int ufx_usb_probe(struct usb_inte
+ check_warn_goto_error(retval, "unable to find common mode for display and adapter");
+
+ retval = ufx_reg_set_bits(dev, 0x4000, 0x00000001);
+- check_warn_goto_error(retval, "error %d enabling graphics engine", retval);
++ if (retval < 0) {
++ dev_err(dev->gdev, "error %d enabling graphics engine", retval);
++ goto setup_modes;
++ }
+
+ /* ready to begin using device */
+ atomic_set(&dev->usb_active, 1);
+
+ dev_dbg(dev->gdev, "checking var");
+ retval = ufx_ops_check_var(&info->var, info);
+- check_warn_goto_error(retval, "error %d ufx_ops_check_var", retval);
++ if (retval < 0) {
++ dev_err(dev->gdev, "error %d ufx_ops_check_var", retval);
++ goto reset_active;
++ }
+
+ dev_dbg(dev->gdev, "setting par");
+ retval = ufx_ops_set_par(info);
+- check_warn_goto_error(retval, "error %d ufx_ops_set_par", retval);
++ if (retval < 0) {
++ dev_err(dev->gdev, "error %d ufx_ops_set_par", retval);
++ goto reset_active;
++ }
+
+ dev_dbg(dev->gdev, "registering framebuffer");
+ retval = register_framebuffer(info);
+- check_warn_goto_error(retval, "error %d register_framebuffer", retval);
++ if (retval < 0) {
++ dev_err(dev->gdev, "error %d register_framebuffer", retval);
++ goto reset_active;
++ }
+
+ dev_info(dev->gdev, "SMSC UDX USB device /dev/fb%d attached. %dx%d resolution."
+ " Using %dK framebuffer memory\n", info->node,
+@@ -1727,21 +1741,23 @@ static int ufx_usb_probe(struct usb_inte
+
+ return 0;
+
+-error:
+- fb_dealloc_cmap(&info->cmap);
+-destroy_modedb:
++reset_active:
++ atomic_set(&dev->usb_active, 0);
++setup_modes:
+ fb_destroy_modedb(info->monspecs.modedb);
+ vfree(info->screen_base);
+ fb_destroy_modelist(&info->modelist);
++error:
++ fb_dealloc_cmap(&info->cmap);
++destroy_modedb:
+ framebuffer_release(info);
++free_urb_list:
++ if (dev->urbs.count > 0)
++ ufx_free_urb_list(dev);
+ put_ref:
+ kref_put(&dev->kref, ufx_free); /* ref for framebuffer */
+ kref_put(&dev->kref, ufx_free); /* last ref from kref_init */
+ return retval;
+-
+-e_nomem:
+- retval = -ENOMEM;
+- goto put_ref;
+ }
+
+ static void ufx_usb_disconnect(struct usb_interface *interface)
udf-avoid-using-stale-lengthofimpuse.patch
serial-8250_dma-fix-dma-rx-completion-race.patch
serial-8250_dma-fix-dma-rx-rearm-race.patch
+fbdev-smscufx-fix-error-handling-code-in-ufx_usb_probe.patch
+f2fs-fix-to-do-sanity-check-on-i_extra_isize-in-is_alive.patch
+wifi-brcmfmac-check-the-count-value-of-channel-spec-to-prevent-out-of-bounds-reads.patch
--- /dev/null
+From 4920ab131b2dbae7464b72bdcac465d070254209 Mon Sep 17 00:00:00 2001
+From: Minsuk Kang <linuxlovemin@yonsei.ac.kr>
+Date: Wed, 16 Nov 2022 23:29:52 +0900
+Subject: wifi: brcmfmac: Check the count value of channel spec to prevent out-of-bounds reads
+
+From: Minsuk Kang <linuxlovemin@yonsei.ac.kr>
+
+commit 4920ab131b2dbae7464b72bdcac465d070254209 upstream.
+
+This patch fixes slab-out-of-bounds reads in brcmfmac that occur in
+brcmf_construct_chaninfo() and brcmf_enable_bw40_2g() when the count
+value of channel specifications provided by the device is greater than
+the length of 'list->element[]', decided by the size of the 'list'
+allocated with kzalloc(). The patch adds checks that make the functions
+free the buffer and return -EINVAL if that is the case. Note that the
+negative return is handled by the caller, brcmf_setup_wiphybands() or
+brcmf_cfg80211_attach().
+
+Found by a modified version of syzkaller.
+
+Crash Report from brcmf_construct_chaninfo():
+==================================================================
+BUG: KASAN: slab-out-of-bounds in brcmf_setup_wiphybands+0x1238/0x1430
+Read of size 4 at addr ffff888115f24600 by task kworker/0:2/1896
+
+CPU: 0 PID: 1896 Comm: kworker/0:2 Tainted: G W O 5.14.0+ #132
+Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.1-0-ga5cab58e9a3f-prebuilt.qemu.org 04/01/2014
+Workqueue: usb_hub_wq hub_event
+Call Trace:
+ dump_stack_lvl+0x57/0x7d
+ print_address_description.constprop.0.cold+0x93/0x334
+ kasan_report.cold+0x83/0xdf
+ brcmf_setup_wiphybands+0x1238/0x1430
+ brcmf_cfg80211_attach+0x2118/0x3fd0
+ brcmf_attach+0x389/0xd40
+ brcmf_usb_probe+0x12de/0x1690
+ usb_probe_interface+0x25f/0x710
+ really_probe+0x1be/0xa90
+ __driver_probe_device+0x2ab/0x460
+ driver_probe_device+0x49/0x120
+ __device_attach_driver+0x18a/0x250
+ bus_for_each_drv+0x123/0x1a0
+ __device_attach+0x207/0x330
+ bus_probe_device+0x1a2/0x260
+ device_add+0xa61/0x1ce0
+ usb_set_configuration+0x984/0x1770
+ usb_generic_driver_probe+0x69/0x90
+ usb_probe_device+0x9c/0x220
+ really_probe+0x1be/0xa90
+ __driver_probe_device+0x2ab/0x460
+ driver_probe_device+0x49/0x120
+ __device_attach_driver+0x18a/0x250
+ bus_for_each_drv+0x123/0x1a0
+ __device_attach+0x207/0x330
+ bus_probe_device+0x1a2/0x260
+ device_add+0xa61/0x1ce0
+ usb_new_device.cold+0x463/0xf66
+ hub_event+0x10d5/0x3330
+ process_one_work+0x873/0x13e0
+ worker_thread+0x8b/0xd10
+ kthread+0x379/0x450
+ ret_from_fork+0x1f/0x30
+
+Allocated by task 1896:
+ kasan_save_stack+0x1b/0x40
+ __kasan_kmalloc+0x7c/0x90
+ kmem_cache_alloc_trace+0x19e/0x330
+ brcmf_setup_wiphybands+0x290/0x1430
+ brcmf_cfg80211_attach+0x2118/0x3fd0
+ brcmf_attach+0x389/0xd40
+ brcmf_usb_probe+0x12de/0x1690
+ usb_probe_interface+0x25f/0x710
+ really_probe+0x1be/0xa90
+ __driver_probe_device+0x2ab/0x460
+ driver_probe_device+0x49/0x120
+ __device_attach_driver+0x18a/0x250
+ bus_for_each_drv+0x123/0x1a0
+ __device_attach+0x207/0x330
+ bus_probe_device+0x1a2/0x260
+ device_add+0xa61/0x1ce0
+ usb_set_configuration+0x984/0x1770
+ usb_generic_driver_probe+0x69/0x90
+ usb_probe_device+0x9c/0x220
+ really_probe+0x1be/0xa90
+ __driver_probe_device+0x2ab/0x460
+ driver_probe_device+0x49/0x120
+ __device_attach_driver+0x18a/0x250
+ bus_for_each_drv+0x123/0x1a0
+ __device_attach+0x207/0x330
+ bus_probe_device+0x1a2/0x260
+ device_add+0xa61/0x1ce0
+ usb_new_device.cold+0x463/0xf66
+ hub_event+0x10d5/0x3330
+ process_one_work+0x873/0x13e0
+ worker_thread+0x8b/0xd10
+ kthread+0x379/0x450
+ ret_from_fork+0x1f/0x30
+
+The buggy address belongs to the object at ffff888115f24000
+ which belongs to the cache kmalloc-2k of size 2048
+The buggy address is located 1536 bytes inside of
+ 2048-byte region [ffff888115f24000, ffff888115f24800)
+
+Memory state around the buggy address:
+ ffff888115f24500: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ ffff888115f24580: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+>ffff888115f24600: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
+ ^
+ ffff888115f24680: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
+ ffff888115f24700: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
+==================================================================
+
+Crash Report from brcmf_enable_bw40_2g():
+==================================================================
+BUG: KASAN: slab-out-of-bounds in brcmf_cfg80211_attach+0x3d11/0x3fd0
+Read of size 4 at addr ffff888103787600 by task kworker/0:2/1896
+
+CPU: 0 PID: 1896 Comm: kworker/0:2 Tainted: G W O 5.14.0+ #132
+Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.1-0-ga5cab58e9a3f-prebuilt.qemu.org 04/01/2014
+Workqueue: usb_hub_wq hub_event
+Call Trace:
+ dump_stack_lvl+0x57/0x7d
+ print_address_description.constprop.0.cold+0x93/0x334
+ kasan_report.cold+0x83/0xdf
+ brcmf_cfg80211_attach+0x3d11/0x3fd0
+ brcmf_attach+0x389/0xd40
+ brcmf_usb_probe+0x12de/0x1690
+ usb_probe_interface+0x25f/0x710
+ really_probe+0x1be/0xa90
+ __driver_probe_device+0x2ab/0x460
+ driver_probe_device+0x49/0x120
+ __device_attach_driver+0x18a/0x250
+ bus_for_each_drv+0x123/0x1a0
+ __device_attach+0x207/0x330
+ bus_probe_device+0x1a2/0x260
+ device_add+0xa61/0x1ce0
+ usb_set_configuration+0x984/0x1770
+ usb_generic_driver_probe+0x69/0x90
+ usb_probe_device+0x9c/0x220
+ really_probe+0x1be/0xa90
+ __driver_probe_device+0x2ab/0x460
+ driver_probe_device+0x49/0x120
+ __device_attach_driver+0x18a/0x250
+ bus_for_each_drv+0x123/0x1a0
+ __device_attach+0x207/0x330
+ bus_probe_device+0x1a2/0x260
+ device_add+0xa61/0x1ce0
+ usb_new_device.cold+0x463/0xf66
+ hub_event+0x10d5/0x3330
+ process_one_work+0x873/0x13e0
+ worker_thread+0x8b/0xd10
+ kthread+0x379/0x450
+ ret_from_fork+0x1f/0x30
+
+Allocated by task 1896:
+ kasan_save_stack+0x1b/0x40
+ __kasan_kmalloc+0x7c/0x90
+ kmem_cache_alloc_trace+0x19e/0x330
+ brcmf_cfg80211_attach+0x3302/0x3fd0
+ brcmf_attach+0x389/0xd40
+ brcmf_usb_probe+0x12de/0x1690
+ usb_probe_interface+0x25f/0x710
+ really_probe+0x1be/0xa90
+ __driver_probe_device+0x2ab/0x460
+ driver_probe_device+0x49/0x120
+ __device_attach_driver+0x18a/0x250
+ bus_for_each_drv+0x123/0x1a0
+ __device_attach+0x207/0x330
+ bus_probe_device+0x1a2/0x260
+ device_add+0xa61/0x1ce0
+ usb_set_configuration+0x984/0x1770
+ usb_generic_driver_probe+0x69/0x90
+ usb_probe_device+0x9c/0x220
+ really_probe+0x1be/0xa90
+ __driver_probe_device+0x2ab/0x460
+ driver_probe_device+0x49/0x120
+ __device_attach_driver+0x18a/0x250
+ bus_for_each_drv+0x123/0x1a0
+ __device_attach+0x207/0x330
+ bus_probe_device+0x1a2/0x260
+ device_add+0xa61/0x1ce0
+ usb_new_device.cold+0x463/0xf66
+ hub_event+0x10d5/0x3330
+ process_one_work+0x873/0x13e0
+ worker_thread+0x8b/0xd10
+ kthread+0x379/0x450
+ ret_from_fork+0x1f/0x30
+
+The buggy address belongs to the object at ffff888103787000
+ which belongs to the cache kmalloc-2k of size 2048
+The buggy address is located 1536 bytes inside of
+ 2048-byte region [ffff888103787000, ffff888103787800)
+
+Memory state around the buggy address:
+ ffff888103787500: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ ffff888103787580: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+>ffff888103787600: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
+ ^
+ ffff888103787680: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
+ ffff888103787700: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
+==================================================================
+
+Reported-by: Dokyung Song <dokyungs@yonsei.ac.kr>
+Reported-by: Jisoo Jang <jisoo.jang@yonsei.ac.kr>
+Reported-by: Minsuk Kang <linuxlovemin@yonsei.ac.kr>
+Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
+Signed-off-by: Minsuk Kang <linuxlovemin@yonsei.ac.kr>
+Signed-off-by: Kalle Valo <kvalo@kernel.org>
+Link: https://lore.kernel.org/r/20221116142952.518241-1-linuxlovemin@yonsei.ac.kr
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 17 ++++++++++++
+ 1 file changed, 17 insertions(+)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+@@ -90,6 +90,9 @@
+ #define BRCMF_ASSOC_PARAMS_FIXED_SIZE \
+ (sizeof(struct brcmf_assoc_params_le) - sizeof(u16))
+
++#define BRCMF_MAX_CHANSPEC_LIST \
++ (BRCMF_DCMD_MEDLEN / sizeof(__le32) - 1)
++
+ static bool check_vif_up(struct brcmf_cfg80211_vif *vif)
+ {
+ if (!test_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state)) {
+@@ -6459,6 +6462,13 @@ static int brcmf_construct_chaninfo(stru
+ band->channels[i].flags = IEEE80211_CHAN_DISABLED;
+
+ total = le32_to_cpu(list->count);
++ if (total > BRCMF_MAX_CHANSPEC_LIST) {
++ bphy_err(drvr, "Invalid count of channel Spec. (%u)\n",
++ total);
++ err = -EINVAL;
++ goto fail_pbuf;
++ }
++
+ for (i = 0; i < total; i++) {
+ ch.chspec = (u16)le32_to_cpu(list->element[i]);
+ cfg->d11inf.decchspec(&ch);
+@@ -6604,6 +6614,13 @@ static int brcmf_enable_bw40_2g(struct b
+ band = cfg_to_wiphy(cfg)->bands[NL80211_BAND_2GHZ];
+ list = (struct brcmf_chanspec_list *)pbuf;
+ num_chan = le32_to_cpu(list->count);
++ if (num_chan > BRCMF_MAX_CHANSPEC_LIST) {
++ bphy_err(drvr, "Invalid count of channel Spec. (%u)\n",
++ num_chan);
++ kfree(pbuf);
++ return -EINVAL;
++ }
++
+ for (i = 0; i < num_chan; i++) {
+ ch.chspec = (u16)le32_to_cpu(list->element[i]);
+ cfg->d11inf.decchspec(&ch);