From f5ac1750969a3a6eb4bcdcd94dbde523edfc225e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 23 Nov 2022 09:16:08 +0100 Subject: [PATCH] 4.14-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 mm-fs-initialize-fsdata-passed-to-write_begin-write_end-interface.patch --- ..._fd-always-use-o_nonblock-read-write.patch | 71 +++++++++++ ...conn_cancel-drop-client-lock-earlier.patch | 41 +++++++ ...bsize_shift-after-reading-superblock.patch | 59 +++++++++ .../gfs2-switch-from-strlcpy-to-strscpy.patch | 38 ++++++ ...d-to-write_begin-write_end-interface.patch | 115 ++++++++++++++++++ queue-4.14/series | 5 + 6 files changed, 329 insertions(+) create mode 100644 queue-4.14/9p-trans_fd-always-use-o_nonblock-read-write.patch create mode 100644 queue-4.14/9p-trans_fd-p9_conn_cancel-drop-client-lock-earlier.patch create mode 100644 queue-4.14/gfs2-check-sb_bsize_shift-after-reading-superblock.patch create mode 100644 queue-4.14/gfs2-switch-from-strlcpy-to-strscpy.patch create mode 100644 queue-4.14/mm-fs-initialize-fsdata-passed-to-write_begin-write_end-interface.patch diff --git a/queue-4.14/9p-trans_fd-always-use-o_nonblock-read-write.patch b/queue-4.14/9p-trans_fd-always-use-o_nonblock-read-write.patch new file mode 100644 index 00000000000..1fe6f8b984e --- /dev/null +++ b/queue-4.14/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 +@@ -834,11 +834,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-4.14/9p-trans_fd-p9_conn_cancel-drop-client-lock-earlier.patch b/queue-4.14/9p-trans_fd-p9_conn_cancel-drop-client-lock-earlier.patch new file mode 100644 index 00000000000..239644c5e92 --- /dev/null +++ b/queue-4.14/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 +@@ -219,6 +219,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); +@@ -226,7 +228,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 int diff --git a/queue-4.14/gfs2-check-sb_bsize_shift-after-reading-superblock.patch b/queue-4.14/gfs2-check-sb_bsize_shift-after-reading-superblock.patch new file mode 100644 index 00000000000..367bbda0e11 --- /dev/null +++ b/queue-4.14/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 +@@ -172,7 +172,10 @@ static int gfs2_check_sb(struct gfs2_sbd + pr_warn("Invalid superblock 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-4.14/gfs2-switch-from-strlcpy-to-strscpy.patch b/queue-4.14/gfs2-switch-from-strlcpy-to-strscpy.patch new file mode 100644 index 00000000000..3dfeaa6e879 --- /dev/null +++ b/queue-4.14/gfs2-switch-from-strlcpy-to-strscpy.patch @@ -0,0 +1,38 @@ +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 | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/fs/gfs2/ops_fstype.c ++++ b/fs/gfs2/ops_fstype.c +@@ -391,8 +391,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, '/'))) diff --git a/queue-4.14/mm-fs-initialize-fsdata-passed-to-write_begin-write_end-interface.patch b/queue-4.14/mm-fs-initialize-fsdata-passed-to-write_begin-write_end-interface.patch new file mode 100644 index 00000000000..29d7254693e --- /dev/null +++ b/queue-4.14/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 +@@ -2378,7 +2378,7 @@ int generic_cont_expand_simple(struct in + { + struct address_space *mapping = inode->i_mapping; + struct page *page; +- void *fsdata; ++ void *fsdata = NULL; + int err; + + err = inode_newsize_ok(inode, size); +@@ -2404,7 +2404,7 @@ static int cont_expand_zero(struct file + struct inode *inode = mapping->host; + 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 +@@ -4847,7 +4847,7 @@ int __page_symlink(struct inode *inode, + { + struct address_space *mapping = inode->i_mapping; + struct page *page; +- void *fsdata; ++ void *fsdata = NULL; + int err; + unsigned int flags = 0; + if (nofs) +--- a/mm/filemap.c ++++ b/mm/filemap.c +@@ -3025,7 +3025,7 @@ ssize_t generic_perform_write(struct fil + 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-4.14/series b/queue-4.14/series index 2525bacd91a..7a2ff1ded9a 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -78,3 +78,8 @@ tcp-cdg-allow-tcp_cdg_release-to-be-called-multiple-times.patch kcm-avoid-potential-race-in-kcm_tx_work.patch bpf-test_run-fix-alignment-problem-in-bpf_prog_test_run_skb.patch kcm-close-race-conditions-on-sk_receive_queue.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 +mm-fs-initialize-fsdata-passed-to-write_begin-write_end-interface.patch -- 2.47.3