From c3fbba80362b715f676aa453aa7b39bb84c64d9d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 7 Feb 2023 13:43:58 +0100 Subject: [PATCH] 5.15-stable patches added patches: bpf-skip-invalid-kfunc-call-in-backtrack_insn.patch f2fs-fix-to-do-sanity-check-on-i_extra_isize-in-is_alive.patch fbdev-smscufx-fix-error-handling-code-in-ufx_usb_probe.patch fs-ntfs3-validate-attribute-data-and-valid-sizes.patch gfs2-always-check-inode-size-of-inline-inodes.patch gfs2-cosmetic-gfs2_dinode_-in-out-cleanup.patch ovl-use-buf-flexible-array-for-memcpy-destination.patch wifi-brcmfmac-check-the-count-value-of-channel-spec-to-prevent-out-of-bounds-reads.patch --- ...invalid-kfunc-call-in-backtrack_insn.patch | 55 ++++ ...y-check-on-i_extra_isize-in-is_alive.patch | 95 +++++++ ...error-handling-code-in-ufx_usb_probe.patch | 160 +++++++++++ ...idate-attribute-data-and-valid-sizes.patch | 46 ++++ ...ys-check-inode-size-of-inline-inodes.patch | 61 +++++ ...cosmetic-gfs2_dinode_-in-out-cleanup.patch | 154 +++++++++++ ...lexible-array-for-memcpy-destination.patch | 49 ++++ queue-5.15/series | 8 + ...-spec-to-prevent-out-of-bounds-reads.patch | 254 ++++++++++++++++++ 9 files changed, 882 insertions(+) create mode 100644 queue-5.15/bpf-skip-invalid-kfunc-call-in-backtrack_insn.patch create mode 100644 queue-5.15/f2fs-fix-to-do-sanity-check-on-i_extra_isize-in-is_alive.patch create mode 100644 queue-5.15/fbdev-smscufx-fix-error-handling-code-in-ufx_usb_probe.patch create mode 100644 queue-5.15/fs-ntfs3-validate-attribute-data-and-valid-sizes.patch create mode 100644 queue-5.15/gfs2-always-check-inode-size-of-inline-inodes.patch create mode 100644 queue-5.15/gfs2-cosmetic-gfs2_dinode_-in-out-cleanup.patch create mode 100644 queue-5.15/ovl-use-buf-flexible-array-for-memcpy-destination.patch create mode 100644 queue-5.15/wifi-brcmfmac-check-the-count-value-of-channel-spec-to-prevent-out-of-bounds-reads.patch diff --git a/queue-5.15/bpf-skip-invalid-kfunc-call-in-backtrack_insn.patch b/queue-5.15/bpf-skip-invalid-kfunc-call-in-backtrack_insn.patch new file mode 100644 index 00000000000..72f07c25971 --- /dev/null +++ b/queue-5.15/bpf-skip-invalid-kfunc-call-in-backtrack_insn.patch @@ -0,0 +1,55 @@ +From d3178e8a434b58678d99257c0387810a24042fb6 Mon Sep 17 00:00:00 2001 +From: Hao Sun +Date: Wed, 4 Jan 2023 09:47:09 +0800 +Subject: bpf: Skip invalid kfunc call in backtrack_insn + +From: Hao Sun + +commit d3178e8a434b58678d99257c0387810a24042fb6 upstream. + +The verifier skips invalid kfunc call in check_kfunc_call(), which +would be captured in fixup_kfunc_call() if such insn is not eliminated +by dead code elimination. However, this can lead to the following +warning in backtrack_insn(), also see [1]: + + ------------[ cut here ]------------ + verifier backtracking bug + WARNING: CPU: 6 PID: 8646 at kernel/bpf/verifier.c:2756 backtrack_insn + kernel/bpf/verifier.c:2756 + __mark_chain_precision kernel/bpf/verifier.c:3065 + mark_chain_precision kernel/bpf/verifier.c:3165 + adjust_reg_min_max_vals kernel/bpf/verifier.c:10715 + check_alu_op kernel/bpf/verifier.c:10928 + do_check kernel/bpf/verifier.c:13821 [inline] + do_check_common kernel/bpf/verifier.c:16289 + [...] + +So make backtracking conservative with this by returning ENOTSUPP. + + [1] https://lore.kernel.org/bpf/CACkBjsaXNceR8ZjkLG=dT3P=4A8SBsg0Z5h5PWLryF5=ghKq=g@mail.gmail.com/ + +Reported-by: syzbot+4da3ff23081bafe74fc2@syzkaller.appspotmail.com +Signed-off-by: Hao Sun +Signed-off-by: Daniel Borkmann +Acked-by: Yonghong Song +Link: https://lore.kernel.org/bpf/20230104014709.9375-1-sunhao.th@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + kernel/bpf/verifier.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -2261,6 +2261,12 @@ static int backtrack_insn(struct bpf_ver + if (opcode == BPF_CALL) { + if (insn->src_reg == BPF_PSEUDO_CALL) + return -ENOTSUPP; ++ /* kfunc with imm==0 is invalid and fixup_kfunc_call will ++ * catch this error later. Make backtracking conservative ++ * with ENOTSUPP. ++ */ ++ if (insn->src_reg == BPF_PSEUDO_KFUNC_CALL && insn->imm == 0) ++ return -ENOTSUPP; + /* regular helper call sets R0 */ + *reg_mask &= ~1; + if (*reg_mask & 0x3f) { diff --git a/queue-5.15/f2fs-fix-to-do-sanity-check-on-i_extra_isize-in-is_alive.patch b/queue-5.15/f2fs-fix-to-do-sanity-check-on-i_extra_isize-in-is_alive.patch new file mode 100644 index 00000000000..18e606b4f4a --- /dev/null +++ b/queue-5.15/f2fs-fix-to-do-sanity-check-on-i_extra_isize-in-is_alive.patch @@ -0,0 +1,95 @@ +From d3b7b4afd6b2c344eabf9cc26b8bfa903c164c7c Mon Sep 17 00:00:00 2001 +From: Chao Yu +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 + +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: + +__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 +Signed-off-by: Jaegeuk Kim +Signed-off-by: Greg Kroah-Hartman +--- + fs/f2fs/gc.c | 18 ++++++++++++------ + 1 file changed, 12 insertions(+), 6 deletions(-) + +--- a/fs/f2fs/gc.c ++++ b/fs/f2fs/gc.c +@@ -1002,7 +1002,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); +@@ -1028,11 +1028,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; + } diff --git a/queue-5.15/fbdev-smscufx-fix-error-handling-code-in-ufx_usb_probe.patch b/queue-5.15/fbdev-smscufx-fix-error-handling-code-in-ufx_usb_probe.patch new file mode 100644 index 00000000000..a766a576fcb --- /dev/null +++ b/queue-5.15/fbdev-smscufx-fix-error-handling-code-in-ufx_usb_probe.patch @@ -0,0 +1,160 @@ +From b76449ee75e21acfe9fa4c653d8598f191ed7d68 Mon Sep 17 00:00:00 2001 +From: Dongliang Mu +Date: Fri, 11 Nov 2022 13:49:49 +0800 +Subject: fbdev: smscufx: fix error handling code in ufx_usb_probe + +From: Dongliang Mu + +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: + [] kmalloc_trace+0x20/0x90 mm/slab_common.c:1045 + [] kmalloc include/linux/slab.h:553 [inline] + [] kzalloc include/linux/slab.h:689 [inline] + [] ufx_alloc_urb_list drivers/video/fbdev/smscufx.c:1873 [inline] + [] ufx_usb_probe+0x11c/0x15a0 drivers/video/fbdev/smscufx.c:1655 + [] usb_probe_interface+0x177/0x370 drivers/usb/core/driver.c:396 + [] call_driver_probe drivers/base/dd.c:560 [inline] + [] really_probe+0x12d/0x390 drivers/base/dd.c:639 + [] __driver_probe_device+0xbf/0x140 drivers/base/dd.c:778 + [] driver_probe_device+0x2a/0x120 drivers/base/dd.c:808 + [] __device_attach_driver+0xf7/0x150 drivers/base/dd.c:936 + [] bus_for_each_drv+0xb7/0x100 drivers/base/bus.c:427 + [] __device_attach+0x105/0x2d0 drivers/base/dd.c:1008 + [] bus_probe_device+0xc6/0xe0 drivers/base/bus.c:487 + [] device_add+0x642/0xdc0 drivers/base/core.c:3517 + [] usb_set_configuration+0x8ef/0xb80 drivers/usb/core/message.c:2170 + [] usb_generic_driver_probe+0x8c/0xc0 drivers/usb/core/generic.c:238 + [] usb_probe_device+0x5c/0x140 drivers/usb/core/driver.c:293 + [] call_driver_probe drivers/base/dd.c:560 [inline] + [] really_probe+0x12d/0x390 drivers/base/dd.c:639 + [] __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 +Tested-by: Dongliang Mu +Signed-off-by: Dongliang Mu +Signed-off-by: Helge Deller +Signed-off-by: Greg Kroah-Hartman +--- + 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) diff --git a/queue-5.15/fs-ntfs3-validate-attribute-data-and-valid-sizes.patch b/queue-5.15/fs-ntfs3-validate-attribute-data-and-valid-sizes.patch new file mode 100644 index 00000000000..819322fa2f2 --- /dev/null +++ b/queue-5.15/fs-ntfs3-validate-attribute-data-and-valid-sizes.patch @@ -0,0 +1,46 @@ +From 019d22eb0eb707fc099e6e8fad9b3933236a06d0 Mon Sep 17 00:00:00 2001 +From: Abdun Nihaal +Date: Tue, 4 Oct 2022 08:45:02 +0530 +Subject: fs/ntfs3: Validate attribute data and valid sizes + +From: Abdun Nihaal + +commit 019d22eb0eb707fc099e6e8fad9b3933236a06d0 upstream. + +The data_size and valid_size fields of non resident attributes should be +less than the its alloc_size field, but this is not checked in +ntfs_read_mft function. + +Syzbot reports a allocation order warning due to a large unchecked value +of data_size getting assigned to inode->i_size which is then passed to +kcalloc. + +Add sanity check for ensuring that the data_size and valid_size fields +are not larger than alloc_size field. + +Link: https://syzkaller.appspot.com/bug?extid=fa4648a5446460b7b963 +Reported-and-tested-by: syzbot+fa4648a5446460b7b963@syzkaller.appspotmail.com +Fixes: (82cae269cfa95) fs/ntfs3: Add initialization of super block +Signed-off-by: Abdun Nihaal +Signed-off-by: Konstantin Komarov +Signed-off-by: Greg Kroah-Hartman +--- + fs/ntfs3/inode.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/fs/ntfs3/inode.c ++++ b/fs/ntfs3/inode.c +@@ -132,6 +132,13 @@ next_attr: + if (le16_to_cpu(attr->name_off) + attr->name_len > asize) + goto out; + ++ if (attr->non_res) { ++ t64 = le64_to_cpu(attr->nres.alloc_size); ++ if (le64_to_cpu(attr->nres.data_size) > t64 || ++ le64_to_cpu(attr->nres.valid_size) > t64) ++ goto out; ++ } ++ + switch (attr->type) { + case ATTR_STD: + if (attr->non_res || diff --git a/queue-5.15/gfs2-always-check-inode-size-of-inline-inodes.patch b/queue-5.15/gfs2-always-check-inode-size-of-inline-inodes.patch new file mode 100644 index 00000000000..4ed1410aefb --- /dev/null +++ b/queue-5.15/gfs2-always-check-inode-size-of-inline-inodes.patch @@ -0,0 +1,61 @@ +From 70376c7ff31221f1d21db5611d8209e677781d3a Mon Sep 17 00:00:00 2001 +From: Andreas Gruenbacher +Date: Sun, 4 Dec 2022 17:00:04 +0100 +Subject: gfs2: Always check inode size of inline inodes + +From: Andreas Gruenbacher + +commit 70376c7ff31221f1d21db5611d8209e677781d3a upstream. + +Check if the inode size of stuffed (inline) inodes is within the allowed +range when reading inodes from disk (gfs2_dinode_in()). This prevents +us from on-disk corruption. + +The two checks in stuffed_readpage() and gfs2_unstuffer_page() that just +truncate inline data to the maximum allowed size don't actually make +sense, and they can be removed now as well. + +Reported-by: syzbot+7bb81dfa9cda07d9cd9d@syzkaller.appspotmail.com +Signed-off-by: Andreas Gruenbacher +Signed-off-by: Greg Kroah-Hartman +--- + fs/gfs2/aops.c | 2 -- + fs/gfs2/bmap.c | 3 --- + fs/gfs2/glops.c | 3 +++ + 3 files changed, 3 insertions(+), 5 deletions(-) + +--- a/fs/gfs2/aops.c ++++ b/fs/gfs2/aops.c +@@ -452,8 +452,6 @@ static int stuffed_readpage(struct gfs2_ + return error; + + kaddr = kmap_atomic(page); +- if (dsize > gfs2_max_stuffed_size(ip)) +- dsize = gfs2_max_stuffed_size(ip); + memcpy(kaddr, dibh->b_data + sizeof(struct gfs2_dinode), dsize); + memset(kaddr + dsize, 0, PAGE_SIZE - dsize); + kunmap_atomic(kaddr); +--- a/fs/gfs2/bmap.c ++++ b/fs/gfs2/bmap.c +@@ -61,9 +61,6 @@ static int gfs2_unstuffer_page(struct gf + void *kaddr = kmap(page); + u64 dsize = i_size_read(inode); + +- if (dsize > gfs2_max_stuffed_size(ip)) +- dsize = gfs2_max_stuffed_size(ip); +- + memcpy(kaddr, dibh->b_data + sizeof(struct gfs2_dinode), dsize); + memset(kaddr + dsize, 0, PAGE_SIZE - dsize); + kunmap(page); +--- a/fs/gfs2/glops.c ++++ b/fs/gfs2/glops.c +@@ -450,6 +450,9 @@ static int gfs2_dinode_in(struct gfs2_in + ip->i_depth = (u8)depth; + ip->i_entries = be32_to_cpu(str->di_entries); + ++ if (gfs2_is_stuffed(ip) && inode->i_size > gfs2_max_stuffed_size(ip)) ++ goto corrupt; ++ + if (S_ISREG(inode->i_mode)) + gfs2_set_aops(inode); + diff --git a/queue-5.15/gfs2-cosmetic-gfs2_dinode_-in-out-cleanup.patch b/queue-5.15/gfs2-cosmetic-gfs2_dinode_-in-out-cleanup.patch new file mode 100644 index 00000000000..95e8d78e6b8 --- /dev/null +++ b/queue-5.15/gfs2-cosmetic-gfs2_dinode_-in-out-cleanup.patch @@ -0,0 +1,154 @@ +From 7db354444ad8429e660b0f8145d425285d4f90ff Mon Sep 17 00:00:00 2001 +From: Andreas Gruenbacher +Date: Sun, 4 Dec 2022 16:50:41 +0100 +Subject: gfs2: Cosmetic gfs2_dinode_{in,out} cleanup + +From: Andreas Gruenbacher + +commit 7db354444ad8429e660b0f8145d425285d4f90ff upstream. + +In each of the two functions, add an inode variable that points to +&ip->i_inode and use that throughout the rest of the function. + +Signed-off-by: Andreas Gruenbacher +Signed-off-by: Greg Kroah-Hartman +--- + fs/gfs2/glops.c | 41 +++++++++++++++++++++-------------------- + fs/gfs2/super.c | 27 ++++++++++++++------------- + 2 files changed, 35 insertions(+), 33 deletions(-) + +--- a/fs/gfs2/glops.c ++++ b/fs/gfs2/glops.c +@@ -398,38 +398,39 @@ static int gfs2_dinode_in(struct gfs2_in + struct timespec64 atime; + u16 height, depth; + umode_t mode = be32_to_cpu(str->di_mode); +- bool is_new = ip->i_inode.i_state & I_NEW; ++ struct inode *inode = &ip->i_inode; ++ bool is_new = inode->i_state & I_NEW; + + if (unlikely(ip->i_no_addr != be64_to_cpu(str->di_num.no_addr))) + goto corrupt; +- if (unlikely(!is_new && inode_wrong_type(&ip->i_inode, mode))) ++ if (unlikely(!is_new && inode_wrong_type(inode, mode))) + goto corrupt; + ip->i_no_formal_ino = be64_to_cpu(str->di_num.no_formal_ino); +- ip->i_inode.i_mode = mode; ++ inode->i_mode = mode; + if (is_new) { +- ip->i_inode.i_rdev = 0; ++ inode->i_rdev = 0; + switch (mode & S_IFMT) { + case S_IFBLK: + case S_IFCHR: +- ip->i_inode.i_rdev = MKDEV(be32_to_cpu(str->di_major), +- be32_to_cpu(str->di_minor)); ++ inode->i_rdev = MKDEV(be32_to_cpu(str->di_major), ++ be32_to_cpu(str->di_minor)); + break; + } + } + +- i_uid_write(&ip->i_inode, be32_to_cpu(str->di_uid)); +- i_gid_write(&ip->i_inode, be32_to_cpu(str->di_gid)); +- set_nlink(&ip->i_inode, be32_to_cpu(str->di_nlink)); +- i_size_write(&ip->i_inode, be64_to_cpu(str->di_size)); +- gfs2_set_inode_blocks(&ip->i_inode, be64_to_cpu(str->di_blocks)); ++ i_uid_write(inode, be32_to_cpu(str->di_uid)); ++ i_gid_write(inode, be32_to_cpu(str->di_gid)); ++ set_nlink(inode, be32_to_cpu(str->di_nlink)); ++ i_size_write(inode, be64_to_cpu(str->di_size)); ++ gfs2_set_inode_blocks(inode, be64_to_cpu(str->di_blocks)); + atime.tv_sec = be64_to_cpu(str->di_atime); + atime.tv_nsec = be32_to_cpu(str->di_atime_nsec); +- if (timespec64_compare(&ip->i_inode.i_atime, &atime) < 0) +- ip->i_inode.i_atime = atime; +- ip->i_inode.i_mtime.tv_sec = be64_to_cpu(str->di_mtime); +- ip->i_inode.i_mtime.tv_nsec = be32_to_cpu(str->di_mtime_nsec); +- ip->i_inode.i_ctime.tv_sec = be64_to_cpu(str->di_ctime); +- ip->i_inode.i_ctime.tv_nsec = be32_to_cpu(str->di_ctime_nsec); ++ if (timespec64_compare(&inode->i_atime, &atime) < 0) ++ inode->i_atime = atime; ++ inode->i_mtime.tv_sec = be64_to_cpu(str->di_mtime); ++ inode->i_mtime.tv_nsec = be32_to_cpu(str->di_mtime_nsec); ++ inode->i_ctime.tv_sec = be64_to_cpu(str->di_ctime); ++ inode->i_ctime.tv_nsec = be32_to_cpu(str->di_ctime_nsec); + + ip->i_goal = be64_to_cpu(str->di_goal_meta); + ip->i_generation = be64_to_cpu(str->di_generation); +@@ -437,7 +438,7 @@ static int gfs2_dinode_in(struct gfs2_in + ip->i_diskflags = be32_to_cpu(str->di_flags); + ip->i_eattr = be64_to_cpu(str->di_eattr); + /* i_diskflags and i_eattr must be set before gfs2_set_inode_flags() */ +- gfs2_set_inode_flags(&ip->i_inode); ++ gfs2_set_inode_flags(inode); + height = be16_to_cpu(str->di_height); + if (unlikely(height > GFS2_MAX_META_HEIGHT)) + goto corrupt; +@@ -449,8 +450,8 @@ static int gfs2_dinode_in(struct gfs2_in + ip->i_depth = (u8)depth; + ip->i_entries = be32_to_cpu(str->di_entries); + +- if (S_ISREG(ip->i_inode.i_mode)) +- gfs2_set_aops(&ip->i_inode); ++ if (S_ISREG(inode->i_mode)) ++ gfs2_set_aops(inode); + + return 0; + corrupt: +--- a/fs/gfs2/super.c ++++ b/fs/gfs2/super.c +@@ -378,6 +378,7 @@ out: + + void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf) + { ++ const struct inode *inode = &ip->i_inode; + struct gfs2_dinode *str = buf; + + str->di_header.mh_magic = cpu_to_be32(GFS2_MAGIC); +@@ -385,15 +386,15 @@ void gfs2_dinode_out(const struct gfs2_i + str->di_header.mh_format = cpu_to_be32(GFS2_FORMAT_DI); + str->di_num.no_addr = cpu_to_be64(ip->i_no_addr); + str->di_num.no_formal_ino = cpu_to_be64(ip->i_no_formal_ino); +- str->di_mode = cpu_to_be32(ip->i_inode.i_mode); +- str->di_uid = cpu_to_be32(i_uid_read(&ip->i_inode)); +- str->di_gid = cpu_to_be32(i_gid_read(&ip->i_inode)); +- str->di_nlink = cpu_to_be32(ip->i_inode.i_nlink); +- str->di_size = cpu_to_be64(i_size_read(&ip->i_inode)); +- str->di_blocks = cpu_to_be64(gfs2_get_inode_blocks(&ip->i_inode)); +- str->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec); +- str->di_mtime = cpu_to_be64(ip->i_inode.i_mtime.tv_sec); +- str->di_ctime = cpu_to_be64(ip->i_inode.i_ctime.tv_sec); ++ str->di_mode = cpu_to_be32(inode->i_mode); ++ str->di_uid = cpu_to_be32(i_uid_read(inode)); ++ str->di_gid = cpu_to_be32(i_gid_read(inode)); ++ str->di_nlink = cpu_to_be32(inode->i_nlink); ++ str->di_size = cpu_to_be64(i_size_read(inode)); ++ str->di_blocks = cpu_to_be64(gfs2_get_inode_blocks(inode)); ++ str->di_atime = cpu_to_be64(inode->i_atime.tv_sec); ++ str->di_mtime = cpu_to_be64(inode->i_mtime.tv_sec); ++ str->di_ctime = cpu_to_be64(inode->i_ctime.tv_sec); + + str->di_goal_meta = cpu_to_be64(ip->i_goal); + str->di_goal_data = cpu_to_be64(ip->i_goal); +@@ -401,16 +402,16 @@ void gfs2_dinode_out(const struct gfs2_i + + str->di_flags = cpu_to_be32(ip->i_diskflags); + str->di_height = cpu_to_be16(ip->i_height); +- str->di_payload_format = cpu_to_be32(S_ISDIR(ip->i_inode.i_mode) && ++ str->di_payload_format = cpu_to_be32(S_ISDIR(inode->i_mode) && + !(ip->i_diskflags & GFS2_DIF_EXHASH) ? + GFS2_FORMAT_DE : 0); + str->di_depth = cpu_to_be16(ip->i_depth); + str->di_entries = cpu_to_be32(ip->i_entries); + + str->di_eattr = cpu_to_be64(ip->i_eattr); +- str->di_atime_nsec = cpu_to_be32(ip->i_inode.i_atime.tv_nsec); +- str->di_mtime_nsec = cpu_to_be32(ip->i_inode.i_mtime.tv_nsec); +- str->di_ctime_nsec = cpu_to_be32(ip->i_inode.i_ctime.tv_nsec); ++ str->di_atime_nsec = cpu_to_be32(inode->i_atime.tv_nsec); ++ str->di_mtime_nsec = cpu_to_be32(inode->i_mtime.tv_nsec); ++ str->di_ctime_nsec = cpu_to_be32(inode->i_ctime.tv_nsec); + } + + /** diff --git a/queue-5.15/ovl-use-buf-flexible-array-for-memcpy-destination.patch b/queue-5.15/ovl-use-buf-flexible-array-for-memcpy-destination.patch new file mode 100644 index 00000000000..681c3d5a77a --- /dev/null +++ b/queue-5.15/ovl-use-buf-flexible-array-for-memcpy-destination.patch @@ -0,0 +1,49 @@ +From cf8aa9bf97cadf85745506c6a3e244b22c268d63 Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Sat, 24 Sep 2022 00:33:15 -0700 +Subject: ovl: Use "buf" flexible array for memcpy() destination + +From: Kees Cook + +commit cf8aa9bf97cadf85745506c6a3e244b22c268d63 upstream. + +The "buf" flexible array needs to be the memcpy() destination to avoid +false positive run-time warning from the recent FORTIFY_SOURCE +hardening: + + memcpy: detected field-spanning write (size 93) of single field "&fh->fb" + at fs/overlayfs/export.c:799 (size 21) + +Reported-by: syzbot+9d14351a171d0d1c7955@syzkaller.appspotmail.com +Link: https://lore.kernel.org/all/000000000000763a6c05e95a5985@google.com/ +Signed-off-by: Kees Cook +Reviewed-by: Gustavo A. R. Silva +Signed-off-by: Miklos Szeredi +Signed-off-by: Greg Kroah-Hartman +--- + fs/overlayfs/export.c | 2 +- + fs/overlayfs/overlayfs.h | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +--- a/fs/overlayfs/export.c ++++ b/fs/overlayfs/export.c +@@ -791,7 +791,7 @@ static struct ovl_fh *ovl_fid_to_fh(stru + return ERR_PTR(-ENOMEM); + + /* Copy unaligned inner fh into aligned buffer */ +- memcpy(&fh->fb, fid, buflen - OVL_FH_WIRE_OFFSET); ++ memcpy(fh->buf, fid, buflen - OVL_FH_WIRE_OFFSET); + return fh; + } + +--- a/fs/overlayfs/overlayfs.h ++++ b/fs/overlayfs/overlayfs.h +@@ -107,7 +107,7 @@ struct ovl_fh { + u8 padding[3]; /* make sure fb.fid is 32bit aligned */ + union { + struct ovl_fb fb; +- u8 buf[0]; ++ DECLARE_FLEX_ARRAY(u8, buf); + }; + } __packed; + diff --git a/queue-5.15/series b/queue-5.15/series index f47bfb61839..7c08d7d1fb1 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -110,3 +110,11 @@ bpf-fix-incorrect-state-pruning-for-8b-spill-fill.patch bpf-do-not-reject-when-the-stack-read-size-is-different-from-the-tracked-scalar-size.patch iio-adc-twl6030-enable-measurement-of-vac.patch powerpc-imc-pmu-revert-nest_init_lock-to-being-a-mutex.patch +fs-ntfs3-validate-attribute-data-and-valid-sizes.patch +ovl-use-buf-flexible-array-for-memcpy-destination.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 +gfs2-cosmetic-gfs2_dinode_-in-out-cleanup.patch +gfs2-always-check-inode-size-of-inline-inodes.patch +bpf-skip-invalid-kfunc-call-in-backtrack_insn.patch diff --git a/queue-5.15/wifi-brcmfmac-check-the-count-value-of-channel-spec-to-prevent-out-of-bounds-reads.patch b/queue-5.15/wifi-brcmfmac-check-the-count-value-of-channel-spec-to-prevent-out-of-bounds-reads.patch new file mode 100644 index 00000000000..5b9f2c40c29 --- /dev/null +++ b/queue-5.15/wifi-brcmfmac-check-the-count-value-of-channel-spec-to-prevent-out-of-bounds-reads.patch @@ -0,0 +1,254 @@ +From 4920ab131b2dbae7464b72bdcac465d070254209 Mon Sep 17 00:00:00 2001 +From: Minsuk Kang +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 + +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 +Reported-by: Jisoo Jang +Reported-by: Minsuk Kang +Reviewed-by: Arend van Spriel +Signed-off-by: Minsuk Kang +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20221116142952.518241-1-linuxlovemin@yonsei.ac.kr +Signed-off-by: Greg Kroah-Hartman +--- + 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)) { +@@ -6557,6 +6560,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); +@@ -6702,6 +6712,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); -- 2.47.3