From: Greg Kroah-Hartman Date: Wed, 23 Nov 2022 08:17:11 +0000 (+0100) Subject: 6.0-stable patches X-Git-Tag: v4.9.334~12 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=39b07317efb3222a9f442105b1fb5319af385544;p=thirdparty%2Fkernel%2Fstable-queue.git 6.0-stable patches added patches: 9p-trans_fd-always-use-o_nonblock-read-write.patch 9p-trans_fd-p9_conn_cancel-drop-client-lock-earlier.patch gfs2-check-sb_bsize_shift-after-reading-superblock.patch gfs2-switch-from-strlcpy-to-strscpy.patch kcm-avoid-potential-race-in-kcm_tx_work.patch kvm-x86-xen-fix-eventfd-error-handling-in-kvm_xen_eventfd_assign.patch macvlan-enforce-a-consistent-minimal-mtu.patch mm-fs-initialize-fsdata-passed-to-write_begin-write_end-interface.patch netlink-bounds-check-struct-nlmsgerr-creation.patch rseq-use-pr_warn_once-when-deprecated-unknown-abi-flags-are-encountered.patch tcp-cdg-allow-tcp_cdg_release-to-be-called-multiple-times.patch wifi-wext-use-flex-array-destination-for-memcpy.patch --- diff --git a/queue-6.0/9p-trans_fd-always-use-o_nonblock-read-write.patch b/queue-6.0/9p-trans_fd-always-use-o_nonblock-read-write.patch new file mode 100644 index 00000000000..bb92e06ba62 --- /dev/null +++ b/queue-6.0/9p-trans_fd-always-use-o_nonblock-read-write.patch @@ -0,0 +1,71 @@ +From ef575281b21e9a34dfae544a187c6aac2ae424a9 Mon Sep 17 00:00:00 2001 +From: Tetsuo Handa +Date: Sat, 27 Aug 2022 00:27:46 +0900 +Subject: 9p/trans_fd: always use O_NONBLOCK read/write + +From: Tetsuo Handa + +commit ef575281b21e9a34dfae544a187c6aac2ae424a9 upstream. + +syzbot is reporting hung task at p9_fd_close() [1], for p9_mux_poll_stop() + from p9_conn_destroy() from p9_fd_close() is failing to interrupt already +started kernel_read() from p9_fd_read() from p9_read_work() and/or +kernel_write() from p9_fd_write() from p9_write_work() requests. + +Since p9_socket_open() sets O_NONBLOCK flag, p9_mux_poll_stop() does not +need to interrupt kernel_read()/kernel_write(). However, since p9_fd_open() +does not set O_NONBLOCK flag, but pipe blocks unless signal is pending, +p9_mux_poll_stop() needs to interrupt kernel_read()/kernel_write() when +the file descriptor refers to a pipe. In other words, pipe file descriptor +needs to be handled as if socket file descriptor. + +We somehow need to interrupt kernel_read()/kernel_write() on pipes. + +A minimal change, which this patch is doing, is to set O_NONBLOCK flag + from p9_fd_open(), for O_NONBLOCK flag does not affect reading/writing +of regular files. But this approach changes O_NONBLOCK flag on userspace- +supplied file descriptors (which might break userspace programs), and +O_NONBLOCK flag could be changed by userspace. It would be possible to set +O_NONBLOCK flag every time p9_fd_read()/p9_fd_write() is invoked, but still +remains small race window for clearing O_NONBLOCK flag. + +If we don't want to manipulate O_NONBLOCK flag, we might be able to +surround kernel_read()/kernel_write() with set_thread_flag(TIF_SIGPENDING) +and recalc_sigpending(). Since p9_read_work()/p9_write_work() works are +processed by kernel threads which process global system_wq workqueue, +signals could not be delivered from remote threads when p9_mux_poll_stop() + from p9_conn_destroy() from p9_fd_close() is called. Therefore, calling +set_thread_flag(TIF_SIGPENDING)/recalc_sigpending() every time would be +needed if we count on signals for making kernel_read()/kernel_write() +non-blocking. + +Link: https://lkml.kernel.org/r/345de429-a88b-7097-d177-adecf9fed342@I-love.SAKURA.ne.jp +Link: https://syzkaller.appspot.com/bug?extid=8b41a1365f1106fd0f33 [1] +Reported-by: syzbot +Signed-off-by: Tetsuo Handa +Tested-by: syzbot +Reviewed-by: Christian Schoenebeck +[Dominique: add comment at Christian's suggestion] +Signed-off-by: Dominique Martinet +Signed-off-by: Greg Kroah-Hartman +--- + net/9p/trans_fd.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/net/9p/trans_fd.c ++++ b/net/9p/trans_fd.c +@@ -822,11 +822,14 @@ static int p9_fd_open(struct p9_client * + goto out_free_ts; + if (!(ts->rd->f_mode & FMODE_READ)) + goto out_put_rd; ++ /* prevent workers from hanging on IO when fd is a pipe */ ++ ts->rd->f_flags |= O_NONBLOCK; + ts->wr = fget(wfd); + if (!ts->wr) + goto out_put_rd; + if (!(ts->wr->f_mode & FMODE_WRITE)) + goto out_put_wr; ++ ts->wr->f_flags |= O_NONBLOCK; + + client->trans = ts; + client->status = Connected; diff --git a/queue-6.0/9p-trans_fd-p9_conn_cancel-drop-client-lock-earlier.patch b/queue-6.0/9p-trans_fd-p9_conn_cancel-drop-client-lock-earlier.patch new file mode 100644 index 00000000000..d4e8b36ad27 --- /dev/null +++ b/queue-6.0/9p-trans_fd-p9_conn_cancel-drop-client-lock-earlier.patch @@ -0,0 +1,41 @@ +From 52f1c45dde9136f964d63a77d19826c8a74e2c7f Mon Sep 17 00:00:00 2001 +From: Dominique Martinet +Date: Wed, 17 Aug 2022 14:58:44 +0900 +Subject: 9p: trans_fd/p9_conn_cancel: drop client lock earlier + +From: Dominique Martinet + +commit 52f1c45dde9136f964d63a77d19826c8a74e2c7f upstream. + +syzbot reported a double-lock here and we no longer need this +lock after requests have been moved off to local list: +just drop the lock earlier. + +Link: https://lkml.kernel.org/r/20220904064028.1305220-1-asmadeus@codewreck.org +Reported-by: syzbot+50f7e8d06c3768dd97f3@syzkaller.appspotmail.com +Signed-off-by: Dominique Martinet +Tested-by: Schspa Shi +Signed-off-by: Greg Kroah-Hartman +--- + net/9p/trans_fd.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/net/9p/trans_fd.c ++++ b/net/9p/trans_fd.c +@@ -205,6 +205,8 @@ static void p9_conn_cancel(struct p9_con + list_move(&req->req_list, &cancel_list); + } + ++ spin_unlock(&m->client->lock); ++ + list_for_each_entry_safe(req, rtmp, &cancel_list, req_list) { + p9_debug(P9_DEBUG_ERROR, "call back req %p\n", req); + list_del(&req->req_list); +@@ -212,7 +214,6 @@ static void p9_conn_cancel(struct p9_con + req->t_err = err; + p9_client_cb(m->client, req, REQ_STATUS_ERROR); + } +- spin_unlock(&m->client->lock); + } + + static __poll_t diff --git a/queue-6.0/gfs2-check-sb_bsize_shift-after-reading-superblock.patch b/queue-6.0/gfs2-check-sb_bsize_shift-after-reading-superblock.patch new file mode 100644 index 00000000000..f0df3684e32 --- /dev/null +++ b/queue-6.0/gfs2-check-sb_bsize_shift-after-reading-superblock.patch @@ -0,0 +1,59 @@ +From 670f8ce56dd0632dc29a0322e188cc73ce3c6b92 Mon Sep 17 00:00:00 2001 +From: Andrew Price +Date: Wed, 17 Aug 2022 13:22:00 +0100 +Subject: gfs2: Check sb_bsize_shift after reading superblock + +From: Andrew Price + +commit 670f8ce56dd0632dc29a0322e188cc73ce3c6b92 upstream. + +Fuzzers like to scribble over sb_bsize_shift but in reality it's very +unlikely that this field would be corrupted on its own. Nevertheless it +should be checked to avoid the possibility of messy mount errors due to +bad calculations. It's always a fixed value based on the block size so +we can just check that it's the expected value. + +Tested with: + + mkfs.gfs2 -O -p lock_nolock /dev/vdb + for i in 0 -1 64 65 32 33; do + gfs2_edit -p sb field sb_bsize_shift $i /dev/vdb + mount /dev/vdb /mnt/test && umount /mnt/test + done + +Before this patch we get a withdraw after + +[ 76.413681] gfs2: fsid=loop0.0: fatal: invalid metadata block +[ 76.413681] bh = 19 (type: exp=5, found=4) +[ 76.413681] function = gfs2_meta_buffer, file = fs/gfs2/meta_io.c, line = 492 + +and with UBSAN configured we also get complaints like + +[ 76.373395] UBSAN: shift-out-of-bounds in fs/gfs2/ops_fstype.c:295:19 +[ 76.373815] shift exponent 4294967287 is too large for 64-bit type 'long unsigned int' + +After the patch, these complaints don't appear, mount fails immediately +and we get an explanation in dmesg. + +Reported-by: syzbot+dcf33a7aae997956fe06@syzkaller.appspotmail.com +Signed-off-by: Andrew Price +Signed-off-by: Andreas Gruenbacher +Signed-off-by: Greg Kroah-Hartman +--- + fs/gfs2/ops_fstype.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/fs/gfs2/ops_fstype.c ++++ b/fs/gfs2/ops_fstype.c +@@ -178,7 +178,10 @@ static int gfs2_check_sb(struct gfs2_sbd + pr_warn("Invalid block size\n"); + return -EINVAL; + } +- ++ if (sb->sb_bsize_shift != ffs(sb->sb_bsize) - 1) { ++ pr_warn("Invalid block size shift\n"); ++ return -EINVAL; ++ } + return 0; + } + diff --git a/queue-6.0/gfs2-switch-from-strlcpy-to-strscpy.patch b/queue-6.0/gfs2-switch-from-strlcpy-to-strscpy.patch new file mode 100644 index 00000000000..fdbfa9d41f0 --- /dev/null +++ b/queue-6.0/gfs2-switch-from-strlcpy-to-strscpy.patch @@ -0,0 +1,55 @@ +From 204c0300c4e99707e9fb6e57840aa1127060e63f Mon Sep 17 00:00:00 2001 +From: Andreas Gruenbacher +Date: Fri, 26 Aug 2022 15:12:17 +0200 +Subject: gfs2: Switch from strlcpy to strscpy + +From: Andreas Gruenbacher + +commit 204c0300c4e99707e9fb6e57840aa1127060e63f upstream. + +Switch from strlcpy to strscpy and make sure that @count is the size of +the smaller of the source and destination buffers. This prevents +reading beyond the end of the source buffer when the source string isn't +null terminated. + +Found by a modified version of syzkaller. + +Suggested-by: Wolfram Sang +Signed-off-by: Andreas Gruenbacher +Signed-off-by: Greg Kroah-Hartman +--- + fs/gfs2/ops_fstype.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +--- a/fs/gfs2/ops_fstype.c ++++ b/fs/gfs2/ops_fstype.c +@@ -384,8 +384,10 @@ static int init_names(struct gfs2_sbd *s + if (!table[0]) + table = sdp->sd_vfs->s_id; + +- strlcpy(sdp->sd_proto_name, proto, GFS2_FSNAME_LEN); +- strlcpy(sdp->sd_table_name, table, GFS2_FSNAME_LEN); ++ BUILD_BUG_ON(GFS2_LOCKNAME_LEN > GFS2_FSNAME_LEN); ++ ++ strscpy(sdp->sd_proto_name, proto, GFS2_LOCKNAME_LEN); ++ strscpy(sdp->sd_table_name, table, GFS2_LOCKNAME_LEN); + + table = sdp->sd_table_name; + while ((table = strchr(table, '/'))) +@@ -1442,13 +1444,13 @@ static int gfs2_parse_param(struct fs_co + + switch (o) { + case Opt_lockproto: +- strlcpy(args->ar_lockproto, param->string, GFS2_LOCKNAME_LEN); ++ strscpy(args->ar_lockproto, param->string, GFS2_LOCKNAME_LEN); + break; + case Opt_locktable: +- strlcpy(args->ar_locktable, param->string, GFS2_LOCKNAME_LEN); ++ strscpy(args->ar_locktable, param->string, GFS2_LOCKNAME_LEN); + break; + case Opt_hostdata: +- strlcpy(args->ar_hostdata, param->string, GFS2_LOCKNAME_LEN); ++ strscpy(args->ar_hostdata, param->string, GFS2_LOCKNAME_LEN); + break; + case Opt_spectator: + args->ar_spectator = 1; diff --git a/queue-6.0/input-i8042-fix-leaking-of-platform-device-on-module.patch b/queue-6.0/input-i8042-fix-leaking-of-platform-device-on-module.patch index 4c69b4b07aa..02e4237240e 100644 --- a/queue-6.0/input-i8042-fix-leaking-of-platform-device-on-module.patch +++ b/queue-6.0/input-i8042-fix-leaking-of-platform-device-on-module.patch @@ -17,14 +17,12 @@ Link: https://lore.kernel.org/r/20221109034148.23821-1-chenjun102@huawei.com Signed-off-by: Dmitry Torokhov Signed-off-by: Sasha Levin --- - drivers/input/serio/i8042.c | 4 ---- + drivers/input/serio/i8042.c | 4 ---- 1 file changed, 4 deletions(-) -diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c -index 3fc0a89cc785..f132d6dfc25e 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c -@@ -1543,8 +1543,6 @@ static int i8042_probe(struct platform_device *dev) +@@ -1543,8 +1543,6 @@ static int i8042_probe(struct platform_d { int error; @@ -33,7 +31,7 @@ index 3fc0a89cc785..f132d6dfc25e 100644 if (i8042_reset == I8042_RESET_ALWAYS) { error = i8042_controller_selftest(); if (error) -@@ -1582,7 +1580,6 @@ static int i8042_probe(struct platform_device *dev) +@@ -1582,7 +1580,6 @@ static int i8042_probe(struct platform_d i8042_free_aux_ports(); /* in case KBD failed but AUX not */ i8042_free_irqs(); i8042_controller_reset(false); @@ -41,7 +39,7 @@ index 3fc0a89cc785..f132d6dfc25e 100644 return error; } -@@ -1592,7 +1589,6 @@ static int i8042_remove(struct platform_device *dev) +@@ -1592,7 +1589,6 @@ static int i8042_remove(struct platform_ i8042_unregister_ports(); i8042_free_irqs(); i8042_controller_reset(false); @@ -49,6 +47,3 @@ index 3fc0a89cc785..f132d6dfc25e 100644 return 0; } --- -2.35.1 - diff --git a/queue-6.0/kcm-avoid-potential-race-in-kcm_tx_work.patch b/queue-6.0/kcm-avoid-potential-race-in-kcm_tx_work.patch new file mode 100644 index 00000000000..a0f3a7323f7 --- /dev/null +++ b/queue-6.0/kcm-avoid-potential-race-in-kcm_tx_work.patch @@ -0,0 +1,72 @@ +From ec7eede369fe5b0d085ac51fdbb95184f87bfc6c Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Wed, 12 Oct 2022 13:34:12 +0000 +Subject: kcm: avoid potential race in kcm_tx_work + +From: Eric Dumazet + +commit ec7eede369fe5b0d085ac51fdbb95184f87bfc6c upstream. + +syzbot found that kcm_tx_work() could crash [1] in: + + /* Primarily for SOCK_SEQPACKET sockets */ + if (likely(sk->sk_socket) && + test_bit(SOCK_NOSPACE, &sk->sk_socket->flags)) { +<<*>> clear_bit(SOCK_NOSPACE, &sk->sk_socket->flags); + sk->sk_write_space(sk); + } + +I think the reason is that another thread might concurrently +run in kcm_release() and call sock_orphan(sk) while sk is not +locked. kcm_tx_work() find sk->sk_socket being NULL. + +[1] +BUG: KASAN: null-ptr-deref in instrument_atomic_write include/linux/instrumented.h:86 [inline] +BUG: KASAN: null-ptr-deref in clear_bit include/asm-generic/bitops/instrumented-atomic.h:41 [inline] +BUG: KASAN: null-ptr-deref in kcm_tx_work+0xff/0x160 net/kcm/kcmsock.c:742 +Write of size 8 at addr 0000000000000008 by task kworker/u4:3/53 + +CPU: 0 PID: 53 Comm: kworker/u4:3 Not tainted 5.19.0-rc3-next-20220621-syzkaller #0 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 +Workqueue: kkcmd kcm_tx_work +Call Trace: + +__dump_stack lib/dump_stack.c:88 [inline] +dump_stack_lvl+0xcd/0x134 lib/dump_stack.c:106 +kasan_report+0xbe/0x1f0 mm/kasan/report.c:495 +check_region_inline mm/kasan/generic.c:183 [inline] +kasan_check_range+0x13d/0x180 mm/kasan/generic.c:189 +instrument_atomic_write include/linux/instrumented.h:86 [inline] +clear_bit include/asm-generic/bitops/instrumented-atomic.h:41 [inline] +kcm_tx_work+0xff/0x160 net/kcm/kcmsock.c:742 +process_one_work+0x996/0x1610 kernel/workqueue.c:2289 +worker_thread+0x665/0x1080 kernel/workqueue.c:2436 +kthread+0x2e9/0x3a0 kernel/kthread.c:376 +ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:302 + + +Fixes: ab7ac4eb9832 ("kcm: Kernel Connection Multiplexor module") +Reported-by: syzbot +Signed-off-by: Eric Dumazet +Cc: Tom Herbert +Link: https://lore.kernel.org/r/20221012133412.519394-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Greg Kroah-Hartman +--- + net/kcm/kcmsock.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/kcm/kcmsock.c ++++ b/net/kcm/kcmsock.c +@@ -1799,10 +1799,10 @@ static int kcm_release(struct socket *so + kcm = kcm_sk(sk); + mux = kcm->mux; + ++ lock_sock(sk); + sock_orphan(sk); + kfree_skb(kcm->seq_skb); + +- lock_sock(sk); + /* Purge queue under lock to avoid race condition with tx_work trying + * to act when queue is nonempty. If tx_work runs after this point + * it will just return. diff --git a/queue-6.0/kvm-x86-xen-fix-eventfd-error-handling-in-kvm_xen_eventfd_assign.patch b/queue-6.0/kvm-x86-xen-fix-eventfd-error-handling-in-kvm_xen_eventfd_assign.patch new file mode 100644 index 00000000000..fde663d9029 --- /dev/null +++ b/queue-6.0/kvm-x86-xen-fix-eventfd-error-handling-in-kvm_xen_eventfd_assign.patch @@ -0,0 +1,54 @@ +From 7353633814f6e5b4899fb9ee1483709d6bb0e1cd Mon Sep 17 00:00:00 2001 +From: Eiichi Tsukata +Date: Fri, 28 Oct 2022 09:26:31 +0000 +Subject: KVM: x86/xen: Fix eventfd error handling in kvm_xen_eventfd_assign() + +From: Eiichi Tsukata + +commit 7353633814f6e5b4899fb9ee1483709d6bb0e1cd upstream. + +Should not call eventfd_ctx_put() in case of error. + +Fixes: 2fd6df2f2b47 ("KVM: x86/xen: intercept EVTCHNOP_send from guests") +Reported-by: syzbot+6f0c896c5a9449a10ded@syzkaller.appspotmail.com +Signed-off-by: Eiichi Tsukata +Message-Id: <20221028092631.117438-1-eiichi.tsukata@nutanix.com> +[Introduce new goto target instead. - Paolo] +Signed-off-by: Paolo Bonzini +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kvm/xen.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +--- a/arch/x86/kvm/xen.c ++++ b/arch/x86/kvm/xen.c +@@ -1667,18 +1667,18 @@ static int kvm_xen_eventfd_assign(struct + case EVTCHNSTAT_ipi: + /* IPI must map back to the same port# */ + if (data->u.evtchn.deliver.port.port != data->u.evtchn.send_port) +- goto out; /* -EINVAL */ ++ goto out_noeventfd; /* -EINVAL */ + break; + + case EVTCHNSTAT_interdomain: + if (data->u.evtchn.deliver.port.port) { + if (data->u.evtchn.deliver.port.port >= max_evtchn_port(kvm)) +- goto out; /* -EINVAL */ ++ goto out_noeventfd; /* -EINVAL */ + } else { + eventfd = eventfd_ctx_fdget(data->u.evtchn.deliver.eventfd.fd); + if (IS_ERR(eventfd)) { + ret = PTR_ERR(eventfd); +- goto out; ++ goto out_noeventfd; + } + } + break; +@@ -1718,6 +1718,7 @@ static int kvm_xen_eventfd_assign(struct + out: + if (eventfd) + eventfd_ctx_put(eventfd); ++out_noeventfd: + kfree(evtchnfd); + return ret; + } diff --git a/queue-6.0/macvlan-enforce-a-consistent-minimal-mtu.patch b/queue-6.0/macvlan-enforce-a-consistent-minimal-mtu.patch new file mode 100644 index 00000000000..472d67a22e1 --- /dev/null +++ b/queue-6.0/macvlan-enforce-a-consistent-minimal-mtu.patch @@ -0,0 +1,45 @@ +From b64085b00044bdf3cd1c9825e9ef5b2e0feae91a Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Fri, 7 Oct 2022 15:57:43 -0700 +Subject: macvlan: enforce a consistent minimal mtu + +From: Eric Dumazet + +commit b64085b00044bdf3cd1c9825e9ef5b2e0feae91a upstream. + +macvlan should enforce a minimal mtu of 68, even at link creation. + +This patch avoids the current behavior (which could lead to crashes +in ipv6 stack if the link is brought up) + +$ ip link add macvlan1 link eno1 mtu 8 type macvlan # This should fail ! +$ ip link sh dev macvlan1 +5: macvlan1@eno1: mtu 8 qdisc noop + state DOWN mode DEFAULT group default qlen 1000 + link/ether 02:47:6c:24:74:82 brd ff:ff:ff:ff:ff:ff +$ ip link set macvlan1 mtu 67 +Error: mtu less than device minimum. +$ ip link set macvlan1 mtu 68 +$ ip link set macvlan1 mtu 8 +Error: mtu less than device minimum. + +Fixes: 91572088e3fd ("net: use core MTU range checking in core net infra") +Reported-by: syzbot +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/macvlan.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/macvlan.c ++++ b/drivers/net/macvlan.c +@@ -1192,7 +1192,7 @@ void macvlan_common_setup(struct net_dev + { + ether_setup(dev); + +- dev->min_mtu = 0; ++ /* ether_setup() has set dev->min_mtu to ETH_MIN_MTU. */ + dev->max_mtu = ETH_MAX_MTU; + dev->priv_flags &= ~IFF_TX_SKB_SHARING; + netif_keep_dst(dev); diff --git a/queue-6.0/mm-fs-initialize-fsdata-passed-to-write_begin-write_end-interface.patch b/queue-6.0/mm-fs-initialize-fsdata-passed-to-write_begin-write_end-interface.patch new file mode 100644 index 00000000000..767fa0e3334 --- /dev/null +++ b/queue-6.0/mm-fs-initialize-fsdata-passed-to-write_begin-write_end-interface.patch @@ -0,0 +1,115 @@ +From 1468c6f4558b1bcd92aa0400f2920f9dc7588402 Mon Sep 17 00:00:00 2001 +From: Alexander Potapenko +Date: Thu, 15 Sep 2022 17:04:16 +0200 +Subject: mm: fs: initialize fsdata passed to write_begin/write_end interface + +From: Alexander Potapenko + +commit 1468c6f4558b1bcd92aa0400f2920f9dc7588402 upstream. + +Functions implementing the a_ops->write_end() interface accept the `void +*fsdata` parameter that is supposed to be initialized by the corresponding +a_ops->write_begin() (which accepts `void **fsdata`). + +However not all a_ops->write_begin() implementations initialize `fsdata` +unconditionally, so it may get passed uninitialized to a_ops->write_end(), +resulting in undefined behavior. + +Fix this by initializing fsdata with NULL before the call to +write_begin(), rather than doing so in all possible a_ops implementations. + +This patch covers only the following cases found by running x86 KMSAN +under syzkaller: + + - generic_perform_write() + - cont_expand_zero() and generic_cont_expand_simple() + - page_symlink() + +Other cases of passing uninitialized fsdata may persist in the codebase. + +Link: https://lkml.kernel.org/r/20220915150417.722975-43-glider@google.com +Signed-off-by: Alexander Potapenko +Cc: Alexander Viro +Cc: Alexei Starovoitov +Cc: Andrey Konovalov +Cc: Andrey Konovalov +Cc: Andy Lutomirski +Cc: Arnd Bergmann +Cc: Borislav Petkov +Cc: Christoph Hellwig +Cc: Christoph Lameter +Cc: David Rientjes +Cc: Dmitry Vyukov +Cc: Eric Biggers +Cc: Eric Biggers +Cc: Eric Dumazet +Cc: Greg Kroah-Hartman +Cc: Herbert Xu +Cc: Ilya Leoshkevich +Cc: Ingo Molnar +Cc: Jens Axboe +Cc: Joonsoo Kim +Cc: Kees Cook +Cc: Marco Elver +Cc: Mark Rutland +Cc: Matthew Wilcox +Cc: Michael S. Tsirkin +Cc: Pekka Enberg +Cc: Peter Zijlstra +Cc: Petr Mladek +Cc: Stephen Rothwell +Cc: Steven Rostedt +Cc: Thomas Gleixner +Cc: Vasily Gorbik +Cc: Vegard Nossum +Cc: Vlastimil Babka +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + fs/buffer.c | 4 ++-- + fs/namei.c | 2 +- + mm/filemap.c | 2 +- + 3 files changed, 4 insertions(+), 4 deletions(-) + +--- a/fs/buffer.c ++++ b/fs/buffer.c +@@ -2352,7 +2352,7 @@ int generic_cont_expand_simple(struct in + struct address_space *mapping = inode->i_mapping; + const struct address_space_operations *aops = mapping->a_ops; + struct page *page; +- void *fsdata; ++ void *fsdata = NULL; + int err; + + err = inode_newsize_ok(inode, size); +@@ -2378,7 +2378,7 @@ static int cont_expand_zero(struct file + const struct address_space_operations *aops = mapping->a_ops; + unsigned int blocksize = i_blocksize(inode); + struct page *page; +- void *fsdata; ++ void *fsdata = NULL; + pgoff_t index, curidx; + loff_t curpos; + unsigned zerofrom, offset, len; +--- a/fs/namei.c ++++ b/fs/namei.c +@@ -5088,7 +5088,7 @@ int page_symlink(struct inode *inode, co + const struct address_space_operations *aops = mapping->a_ops; + bool nofs = !mapping_gfp_constraint(mapping, __GFP_FS); + struct page *page; +- void *fsdata; ++ void *fsdata = NULL; + int err; + unsigned int flags; + +--- a/mm/filemap.c ++++ b/mm/filemap.c +@@ -3712,7 +3712,7 @@ ssize_t generic_perform_write(struct kio + unsigned long offset; /* Offset into pagecache page */ + unsigned long bytes; /* Bytes to write to page */ + size_t copied; /* Bytes copied from user */ +- void *fsdata; ++ void *fsdata = NULL; + + offset = (pos & (PAGE_SIZE - 1)); + bytes = min_t(unsigned long, PAGE_SIZE - offset, diff --git a/queue-6.0/netlink-bounds-check-struct-nlmsgerr-creation.patch b/queue-6.0/netlink-bounds-check-struct-nlmsgerr-creation.patch new file mode 100644 index 00000000000..2cf7697c058 --- /dev/null +++ b/queue-6.0/netlink-bounds-check-struct-nlmsgerr-creation.patch @@ -0,0 +1,74 @@ +From 710d21fdff9a98d621cd4e64167f3ef8af4e2fd1 Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Fri, 2 Sep 2022 21:37:49 -0700 +Subject: netlink: Bounds-check struct nlmsgerr creation + +From: Kees Cook + +commit 710d21fdff9a98d621cd4e64167f3ef8af4e2fd1 upstream. + +In preparation for FORTIFY_SOURCE doing bounds-check on memcpy(), +switch from __nlmsg_put to nlmsg_put(), and explain the bounds check +for dealing with the memcpy() across a composite flexible array struct. +Avoids this future run-time warning: + + memcpy: detected field-spanning write (size 32) of single field "&errmsg->msg" at net/netlink/af_netlink.c:2447 (size 16) + +Cc: Jakub Kicinski +Cc: Pablo Neira Ayuso +Cc: Jozsef Kadlecsik +Cc: Florian Westphal +Cc: "David S. Miller" +Cc: Eric Dumazet +Cc: Paolo Abeni +Cc: syzbot +Cc: netfilter-devel@vger.kernel.org +Cc: coreteam@netfilter.org +Cc: netdev@vger.kernel.org +Signed-off-by: Kees Cook +Link: https://lore.kernel.org/r/20220901071336.1418572-1-keescook@chromium.org +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/netfilter/ipset/ip_set_core.c | 8 +++++--- + net/netlink/af_netlink.c | 8 +++++--- + 2 files changed, 10 insertions(+), 6 deletions(-) + +--- a/net/netfilter/ipset/ip_set_core.c ++++ b/net/netfilter/ipset/ip_set_core.c +@@ -1719,11 +1719,13 @@ call_ad(struct net *net, struct sock *ct + skb2 = nlmsg_new(payload, GFP_KERNEL); + if (!skb2) + return -ENOMEM; +- rep = __nlmsg_put(skb2, NETLINK_CB(skb).portid, +- nlh->nlmsg_seq, NLMSG_ERROR, payload, 0); ++ rep = nlmsg_put(skb2, NETLINK_CB(skb).portid, ++ nlh->nlmsg_seq, NLMSG_ERROR, payload, 0); + errmsg = nlmsg_data(rep); + errmsg->error = ret; +- memcpy(&errmsg->msg, nlh, nlh->nlmsg_len); ++ unsafe_memcpy(&errmsg->msg, nlh, nlh->nlmsg_len, ++ /* Bounds checked by the skb layer. */); ++ + cmdattr = (void *)&errmsg->msg + min_len; + + ret = nla_parse(cda, IPSET_ATTR_CMD_MAX, cmdattr, +--- a/net/netlink/af_netlink.c ++++ b/net/netlink/af_netlink.c +@@ -2440,11 +2440,13 @@ void netlink_ack(struct sk_buff *in_skb, + return; + } + +- rep = __nlmsg_put(skb, NETLINK_CB(in_skb).portid, nlh->nlmsg_seq, +- NLMSG_ERROR, payload, flags); ++ rep = nlmsg_put(skb, NETLINK_CB(in_skb).portid, nlh->nlmsg_seq, ++ NLMSG_ERROR, payload, flags); + errmsg = nlmsg_data(rep); + errmsg->error = err; +- memcpy(&errmsg->msg, nlh, payload > sizeof(*errmsg) ? nlh->nlmsg_len : sizeof(*nlh)); ++ unsafe_memcpy(&errmsg->msg, nlh, payload > sizeof(*errmsg) ++ ? nlh->nlmsg_len : sizeof(*nlh), ++ /* Bounds checked by the skb layer. */); + + if (nlk_has_extack && extack) { + if (extack->_msg) { diff --git a/queue-6.0/rseq-use-pr_warn_once-when-deprecated-unknown-abi-flags-are-encountered.patch b/queue-6.0/rseq-use-pr_warn_once-when-deprecated-unknown-abi-flags-are-encountered.patch new file mode 100644 index 00000000000..df5073a4acd --- /dev/null +++ b/queue-6.0/rseq-use-pr_warn_once-when-deprecated-unknown-abi-flags-are-encountered.patch @@ -0,0 +1,72 @@ +From 448dca8c88755b768552e19bd1618be34ef6d1ff Mon Sep 17 00:00:00 2001 +From: Mathieu Desnoyers +Date: Wed, 2 Nov 2022 09:06:35 -0400 +Subject: rseq: Use pr_warn_once() when deprecated/unknown ABI flags are encountered + +From: Mathieu Desnoyers + +commit 448dca8c88755b768552e19bd1618be34ef6d1ff upstream. + +These commits use WARN_ON_ONCE() and kill the offending processes when +deprecated and unknown flags are encountered: + +commit c17a6ff93213 ("rseq: Kill process when unknown flags are encountered in ABI structures") +commit 0190e4198e47 ("rseq: Deprecate RSEQ_CS_FLAG_NO_RESTART_ON_* flags") + +The WARN_ON_ONCE() triggered by userspace input prevents use of +Syzkaller to fuzz the rseq system call. + +Replace this WARN_ON_ONCE() by pr_warn_once() messages which contain +actually useful information. + +Reported-by: Mark Rutland +Signed-off-by: Mathieu Desnoyers +Signed-off-by: Peter Zijlstra (Intel) +Acked-by: Mark Rutland +Acked-by: Paul E. McKenney +Link: https://lkml.kernel.org/r/20221102130635.7379-1-mathieu.desnoyers@efficios.com +Signed-off-by: Greg Kroah-Hartman +--- + kernel/rseq.c | 19 +++++++++++++++++-- + 1 file changed, 17 insertions(+), 2 deletions(-) + +--- a/kernel/rseq.c ++++ b/kernel/rseq.c +@@ -171,12 +171,27 @@ static int rseq_get_rseq_cs(struct task_ + return 0; + } + ++static bool rseq_warn_flags(const char *str, u32 flags) ++{ ++ u32 test_flags; ++ ++ if (!flags) ++ return false; ++ test_flags = flags & RSEQ_CS_NO_RESTART_FLAGS; ++ if (test_flags) ++ pr_warn_once("Deprecated flags (%u) in %s ABI structure", test_flags, str); ++ test_flags = flags & ~RSEQ_CS_NO_RESTART_FLAGS; ++ if (test_flags) ++ pr_warn_once("Unknown flags (%u) in %s ABI structure", test_flags, str); ++ return true; ++} ++ + static int rseq_need_restart(struct task_struct *t, u32 cs_flags) + { + u32 flags, event_mask; + int ret; + +- if (WARN_ON_ONCE(cs_flags & RSEQ_CS_NO_RESTART_FLAGS) || cs_flags) ++ if (rseq_warn_flags("rseq_cs", cs_flags)) + return -EINVAL; + + /* Get thread flags. */ +@@ -184,7 +199,7 @@ static int rseq_need_restart(struct task + if (ret) + return ret; + +- if (WARN_ON_ONCE(flags & RSEQ_CS_NO_RESTART_FLAGS) || flags) ++ if (rseq_warn_flags("rseq", flags)) + return -EINVAL; + + /* diff --git a/queue-6.0/series b/queue-6.0/series index cb4208817c1..72c24276ac3 100644 --- a/queue-6.0/series +++ b/queue-6.0/series @@ -295,3 +295,15 @@ kprobes-skip-clearing-aggrprobe-s-post_handler-in-kp.patch tracing-fix-potential-null-pointer-access-of-entry-i.patch arm64-mm-fix-incorrect-file_map_count-for-non-leaf-p.patch input-i8042-fix-leaking-of-platform-device-on-module.patch +macvlan-enforce-a-consistent-minimal-mtu.patch +tcp-cdg-allow-tcp_cdg_release-to-be-called-multiple-times.patch +kcm-avoid-potential-race-in-kcm_tx_work.patch +kvm-x86-xen-fix-eventfd-error-handling-in-kvm_xen_eventfd_assign.patch +9p-trans_fd-p9_conn_cancel-drop-client-lock-earlier.patch +gfs2-check-sb_bsize_shift-after-reading-superblock.patch +gfs2-switch-from-strlcpy-to-strscpy.patch +9p-trans_fd-always-use-o_nonblock-read-write.patch +netlink-bounds-check-struct-nlmsgerr-creation.patch +wifi-wext-use-flex-array-destination-for-memcpy.patch +rseq-use-pr_warn_once-when-deprecated-unknown-abi-flags-are-encountered.patch +mm-fs-initialize-fsdata-passed-to-write_begin-write_end-interface.patch diff --git a/queue-6.0/tcp-cdg-allow-tcp_cdg_release-to-be-called-multiple-times.patch b/queue-6.0/tcp-cdg-allow-tcp_cdg_release-to-be-called-multiple-times.patch new file mode 100644 index 00000000000..6148722f794 --- /dev/null +++ b/queue-6.0/tcp-cdg-allow-tcp_cdg_release-to-be-called-multiple-times.patch @@ -0,0 +1,155 @@ +From 72e560cb8c6f80fc2b4afc5d3634a32465e13a51 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Tue, 11 Oct 2022 15:07:48 -0700 +Subject: tcp: cdg: allow tcp_cdg_release() to be called multiple times + +From: Eric Dumazet + +commit 72e560cb8c6f80fc2b4afc5d3634a32465e13a51 upstream. + +Apparently, mptcp is able to call tcp_disconnect() on an already +disconnected flow. This is generally fine, unless current congestion +control is CDG, because it might trigger a double-free [1] + +Instead of fixing MPTCP, and future bugs, we can make tcp_disconnect() +more resilient. + +[1] +BUG: KASAN: double-free in slab_free mm/slub.c:3539 [inline] +BUG: KASAN: double-free in kfree+0xe2/0x580 mm/slub.c:4567 + +CPU: 0 PID: 3645 Comm: kworker/0:7 Not tainted 6.0.0-syzkaller-02734-g0326074ff465 #0 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 09/22/2022 +Workqueue: events mptcp_worker +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:317 [inline] +print_report.cold+0x2ba/0x719 mm/kasan/report.c:433 +kasan_report_invalid_free+0x81/0x190 mm/kasan/report.c:462 +____kasan_slab_free+0x18b/0x1c0 mm/kasan/common.c:356 +kasan_slab_free include/linux/kasan.h:200 [inline] +slab_free_hook mm/slub.c:1759 [inline] +slab_free_freelist_hook+0x8b/0x1c0 mm/slub.c:1785 +slab_free mm/slub.c:3539 [inline] +kfree+0xe2/0x580 mm/slub.c:4567 +tcp_disconnect+0x980/0x1e20 net/ipv4/tcp.c:3145 +__mptcp_close_ssk+0x5ca/0x7e0 net/mptcp/protocol.c:2327 +mptcp_do_fastclose net/mptcp/protocol.c:2592 [inline] +mptcp_worker+0x78c/0xff0 net/mptcp/protocol.c:2627 +process_one_work+0x991/0x1610 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 + + +Allocated by task 3671: +kasan_save_stack+0x1e/0x40 mm/kasan/common.c:38 +kasan_set_track mm/kasan/common.c:45 [inline] +set_alloc_info mm/kasan/common.c:437 [inline] +____kasan_kmalloc mm/kasan/common.c:516 [inline] +____kasan_kmalloc mm/kasan/common.c:475 [inline] +__kasan_kmalloc+0xa9/0xd0 mm/kasan/common.c:525 +kmalloc_array include/linux/slab.h:640 [inline] +kcalloc include/linux/slab.h:671 [inline] +tcp_cdg_init+0x10d/0x170 net/ipv4/tcp_cdg.c:380 +tcp_init_congestion_control+0xab/0x550 net/ipv4/tcp_cong.c:193 +tcp_reinit_congestion_control net/ipv4/tcp_cong.c:217 [inline] +tcp_set_congestion_control+0x96c/0xaa0 net/ipv4/tcp_cong.c:391 +do_tcp_setsockopt+0x505/0x2320 net/ipv4/tcp.c:3513 +tcp_setsockopt+0xd4/0x100 net/ipv4/tcp.c:3801 +mptcp_setsockopt+0x35f/0x2570 net/mptcp/sockopt.c:844 +__sys_setsockopt+0x2d6/0x690 net/socket.c:2252 +__do_sys_setsockopt net/socket.c:2263 [inline] +__se_sys_setsockopt net/socket.c:2260 [inline] +__x64_sys_setsockopt+0xba/0x150 net/socket.c:2260 +do_syscall_x64 arch/x86/entry/common.c:50 [inline] +do_syscall_64+0x35/0xb0 arch/x86/entry/common.c:80 +entry_SYSCALL_64_after_hwframe+0x63/0xcd + +Freed by task 16: +kasan_save_stack+0x1e/0x40 mm/kasan/common.c:38 +kasan_set_track+0x21/0x30 mm/kasan/common.c:45 +kasan_set_free_info+0x20/0x30 mm/kasan/generic.c:370 +____kasan_slab_free mm/kasan/common.c:367 [inline] +____kasan_slab_free+0x166/0x1c0 mm/kasan/common.c:329 +kasan_slab_free include/linux/kasan.h:200 [inline] +slab_free_hook mm/slub.c:1759 [inline] +slab_free_freelist_hook+0x8b/0x1c0 mm/slub.c:1785 +slab_free mm/slub.c:3539 [inline] +kfree+0xe2/0x580 mm/slub.c:4567 +tcp_cleanup_congestion_control+0x70/0x120 net/ipv4/tcp_cong.c:226 +tcp_v4_destroy_sock+0xdd/0x750 net/ipv4/tcp_ipv4.c:2254 +tcp_v6_destroy_sock+0x11/0x20 net/ipv6/tcp_ipv6.c:1969 +inet_csk_destroy_sock+0x196/0x440 net/ipv4/inet_connection_sock.c:1157 +tcp_done+0x23b/0x340 net/ipv4/tcp.c:4649 +tcp_rcv_state_process+0x40e7/0x4990 net/ipv4/tcp_input.c:6624 +tcp_v6_do_rcv+0x3fc/0x13c0 net/ipv6/tcp_ipv6.c:1525 +tcp_v6_rcv+0x2e8e/0x3830 net/ipv6/tcp_ipv6.c:1759 +ip6_protocol_deliver_rcu+0x2db/0x1950 net/ipv6/ip6_input.c:439 +ip6_input_finish+0x14c/0x2c0 net/ipv6/ip6_input.c:484 +NF_HOOK include/linux/netfilter.h:302 [inline] +NF_HOOK include/linux/netfilter.h:296 [inline] +ip6_input+0x9c/0xd0 net/ipv6/ip6_input.c:493 +dst_input include/net/dst.h:455 [inline] +ip6_rcv_finish+0x193/0x2c0 net/ipv6/ip6_input.c:79 +ip_sabotage_in net/bridge/br_netfilter_hooks.c:874 [inline] +ip_sabotage_in+0x1fa/0x260 net/bridge/br_netfilter_hooks.c:865 +nf_hook_entry_hookfn include/linux/netfilter.h:142 [inline] +nf_hook_slow+0xc5/0x1f0 net/netfilter/core.c:614 +nf_hook.constprop.0+0x3ac/0x650 include/linux/netfilter.h:257 +NF_HOOK include/linux/netfilter.h:300 [inline] +ipv6_rcv+0x9e/0x380 net/ipv6/ip6_input.c:309 +__netif_receive_skb_one_core+0x114/0x180 net/core/dev.c:5485 +__netif_receive_skb+0x1f/0x1c0 net/core/dev.c:5599 +netif_receive_skb_internal net/core/dev.c:5685 [inline] +netif_receive_skb+0x12f/0x8d0 net/core/dev.c:5744 +NF_HOOK include/linux/netfilter.h:302 [inline] +NF_HOOK include/linux/netfilter.h:296 [inline] +br_pass_frame_up+0x303/0x410 net/bridge/br_input.c:68 +br_handle_frame_finish+0x909/0x1aa0 net/bridge/br_input.c:199 +br_nf_hook_thresh+0x2f8/0x3d0 net/bridge/br_netfilter_hooks.c:1041 +br_nf_pre_routing_finish_ipv6+0x695/0xef0 net/bridge/br_netfilter_ipv6.c:207 +NF_HOOK include/linux/netfilter.h:302 [inline] +br_nf_pre_routing_ipv6+0x417/0x7c0 net/bridge/br_netfilter_ipv6.c:237 +br_nf_pre_routing+0x1496/0x1fe0 net/bridge/br_netfilter_hooks.c:507 +nf_hook_entry_hookfn include/linux/netfilter.h:142 [inline] +nf_hook_bridge_pre net/bridge/br_input.c:255 [inline] +br_handle_frame+0x9c9/0x12d0 net/bridge/br_input.c:399 +__netif_receive_skb_core+0x9fe/0x38f0 net/core/dev.c:5379 +__netif_receive_skb_one_core+0xae/0x180 net/core/dev.c:5483 +__netif_receive_skb+0x1f/0x1c0 net/core/dev.c:5599 +process_backlog+0x3a0/0x7c0 net/core/dev.c:5927 +__napi_poll+0xb3/0x6d0 net/core/dev.c:6494 +napi_poll net/core/dev.c:6561 [inline] +net_rx_action+0x9c1/0xd90 net/core/dev.c:6672 +__do_softirq+0x1d0/0x9c8 kernel/softirq.c:571 + +Fixes: 2b0a8c9eee81 ("tcp: add CDG congestion control") +Reported-by: syzbot +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/tcp_cdg.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/net/ipv4/tcp_cdg.c ++++ b/net/ipv4/tcp_cdg.c +@@ -375,6 +375,7 @@ static void tcp_cdg_init(struct sock *sk + struct cdg *ca = inet_csk_ca(sk); + struct tcp_sock *tp = tcp_sk(sk); + ++ ca->gradients = NULL; + /* We silently fall back to window = 1 if allocation fails. */ + if (window > 1) + ca->gradients = kcalloc(window, sizeof(ca->gradients[0]), +@@ -388,6 +389,7 @@ static void tcp_cdg_release(struct sock + struct cdg *ca = inet_csk_ca(sk); + + kfree(ca->gradients); ++ ca->gradients = NULL; + } + + static struct tcp_congestion_ops tcp_cdg __read_mostly = { diff --git a/queue-6.0/wifi-wext-use-flex-array-destination-for-memcpy.patch b/queue-6.0/wifi-wext-use-flex-array-destination-for-memcpy.patch new file mode 100644 index 00000000000..21177fce2a6 --- /dev/null +++ b/queue-6.0/wifi-wext-use-flex-array-destination-for-memcpy.patch @@ -0,0 +1,128 @@ +From e3e6e1d16a4cf7b63159ec71774e822194071954 Mon Sep 17 00:00:00 2001 +From: Hawkins Jiawei +Date: Tue, 27 Sep 2022 07:34:59 +0800 +Subject: wifi: wext: use flex array destination for memcpy() + +From: Hawkins Jiawei + +commit e3e6e1d16a4cf7b63159ec71774e822194071954 upstream. + +Syzkaller reports buffer overflow false positive as follows: +------------[ cut here ]------------ +memcpy: detected field-spanning write (size 8) of single field + "&compat_event->pointer" at net/wireless/wext-core.c:623 (size 4) +WARNING: CPU: 0 PID: 3607 at net/wireless/wext-core.c:623 + wireless_send_event+0xab5/0xca0 net/wireless/wext-core.c:623 +Modules linked in: +CPU: 1 PID: 3607 Comm: syz-executor659 Not tainted + 6.0.0-rc6-next-20220921-syzkaller #0 +[...] +Call Trace: + + ioctl_standard_call+0x155/0x1f0 net/wireless/wext-core.c:1022 + wireless_process_ioctl+0xc8/0x4c0 net/wireless/wext-core.c:955 + wext_ioctl_dispatch net/wireless/wext-core.c:988 [inline] + wext_ioctl_dispatch net/wireless/wext-core.c:976 [inline] + wext_handle_ioctl+0x26b/0x280 net/wireless/wext-core.c:1049 + sock_ioctl+0x285/0x640 net/socket.c:1220 + vfs_ioctl fs/ioctl.c:51 [inline] + __do_sys_ioctl fs/ioctl.c:870 [inline] + __se_sys_ioctl fs/ioctl.c:856 [inline] + __x64_sys_ioctl+0x193/0x200 fs/ioctl.c:856 + do_syscall_x64 arch/x86/entry/common.c:50 [inline] + do_syscall_64+0x35/0xb0 arch/x86/entry/common.c:80 + entry_SYSCALL_64_after_hwframe+0x63/0xcd + [...] + + +Wireless events will be sent on the appropriate channels in +wireless_send_event(). Different wireless events may have different +payload structure and size, so kernel uses **len** and **cmd** field +in struct __compat_iw_event as wireless event common LCP part, uses +**pointer** as a label to mark the position of remaining different part. + +Yet the problem is that, **pointer** is a compat_caddr_t type, which may +be smaller than the relative structure at the same position. So during +wireless_send_event() tries to parse the wireless events payload, it may +trigger the memcpy() run-time destination buffer bounds checking when the +relative structure's data is copied to the position marked by **pointer**. + +This patch solves it by introducing flexible-array field **ptr_bytes**, +to mark the position of the wireless events remaining part next to +LCP part. What's more, this patch also adds **ptr_len** variable in +wireless_send_event() to improve its maintainability. + +Reported-and-tested-by: syzbot+473754e5af963cf014cf@syzkaller.appspotmail.com +Link: https://lore.kernel.org/all/00000000000070db2005e95a5984@google.com/ +Suggested-by: Kees Cook +Reviewed-by: Kees Cook +Signed-off-by: Hawkins Jiawei +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/wireless.h | 10 +++++++++- + net/wireless/wext-core.c | 17 ++++++++++------- + 2 files changed, 19 insertions(+), 8 deletions(-) + +--- a/include/linux/wireless.h ++++ b/include/linux/wireless.h +@@ -26,7 +26,15 @@ struct compat_iw_point { + struct __compat_iw_event { + __u16 len; /* Real length of this stuff */ + __u16 cmd; /* Wireless IOCTL */ +- compat_caddr_t pointer; ++ ++ union { ++ compat_caddr_t pointer; ++ ++ /* we need ptr_bytes to make memcpy() run-time destination ++ * buffer bounds checking happy, nothing special ++ */ ++ DECLARE_FLEX_ARRAY(__u8, ptr_bytes); ++ }; + }; + #define IW_EV_COMPAT_LCP_LEN offsetof(struct __compat_iw_event, pointer) + #define IW_EV_COMPAT_POINT_OFF offsetof(struct compat_iw_point, length) +--- a/net/wireless/wext-core.c ++++ b/net/wireless/wext-core.c +@@ -468,6 +468,7 @@ void wireless_send_event(struct net_devi + struct __compat_iw_event *compat_event; + struct compat_iw_point compat_wrqu; + struct sk_buff *compskb; ++ int ptr_len; + #endif + + /* +@@ -582,6 +583,9 @@ void wireless_send_event(struct net_devi + nlmsg_end(skb, nlh); + #ifdef CONFIG_COMPAT + hdr_len = compat_event_type_size[descr->header_type]; ++ ++ /* ptr_len is remaining size in event header apart from LCP */ ++ ptr_len = hdr_len - IW_EV_COMPAT_LCP_LEN; + event_len = hdr_len + extra_len; + + compskb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); +@@ -612,16 +616,15 @@ void wireless_send_event(struct net_devi + if (descr->header_type == IW_HEADER_TYPE_POINT) { + compat_wrqu.length = wrqu->data.length; + compat_wrqu.flags = wrqu->data.flags; +- memcpy(&compat_event->pointer, +- ((char *) &compat_wrqu) + IW_EV_COMPAT_POINT_OFF, +- hdr_len - IW_EV_COMPAT_LCP_LEN); ++ memcpy(compat_event->ptr_bytes, ++ ((char *)&compat_wrqu) + IW_EV_COMPAT_POINT_OFF, ++ ptr_len); + if (extra_len) +- memcpy(((char *) compat_event) + hdr_len, +- extra, extra_len); ++ memcpy(&compat_event->ptr_bytes[ptr_len], ++ extra, extra_len); + } else { + /* extra_len must be zero, so no if (extra) needed */ +- memcpy(&compat_event->pointer, wrqu, +- hdr_len - IW_EV_COMPAT_LCP_LEN); ++ memcpy(compat_event->ptr_bytes, wrqu, ptr_len); + } + + nlmsg_end(compskb, nlh);