]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.1-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 13 Feb 2025 13:13:59 +0000 (14:13 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 13 Feb 2025 13:13:59 +0000 (14:13 +0100)
added patches:
btrfs-avoid-monopolizing-a-core-when-activating-a-swap-file.patch
cachefiles-fix-null-pointer-dereference-in-object-file.patch
ext4-filesystems-without-casefold-feature-cannot-be-mounted-with-siphash.patch
maple_tree-fix-static-analyser-cppcheck-issue.patch
maple_tree-simplify-split-calculation.patch
mptcp-pm-only-set-fullmesh-for-subflow-endp.patch
mptcp-prevent-excessive-coalescing-on-receive.patch
ocfs2-check-dir-i_size-in-ocfs2_find_entry.patch
pps-fix-a-use-after-free.patch
revert-btrfs-avoid-monopolizing-a-core-when-activating-a-swap-file.patch
tty-xilinx_uartps-split-sysrq-handling.patch

13 files changed:
queue-6.1/btrfs-avoid-monopolizing-a-core-when-activating-a-swap-file.patch [new file with mode: 0644]
queue-6.1/cachefiles-fix-null-pointer-dereference-in-object-file.patch [new file with mode: 0644]
queue-6.1/drm-sti-hdmi-use-eld_mutex-to-protect-access-to-conn.patch [deleted file]
queue-6.1/ext4-filesystems-without-casefold-feature-cannot-be-mounted-with-siphash.patch [new file with mode: 0644]
queue-6.1/maple_tree-fix-static-analyser-cppcheck-issue.patch [new file with mode: 0644]
queue-6.1/maple_tree-simplify-split-calculation.patch [new file with mode: 0644]
queue-6.1/mptcp-pm-only-set-fullmesh-for-subflow-endp.patch [new file with mode: 0644]
queue-6.1/mptcp-prevent-excessive-coalescing-on-receive.patch [new file with mode: 0644]
queue-6.1/ocfs2-check-dir-i_size-in-ocfs2_find_entry.patch [new file with mode: 0644]
queue-6.1/pps-fix-a-use-after-free.patch [new file with mode: 0644]
queue-6.1/revert-btrfs-avoid-monopolizing-a-core-when-activating-a-swap-file.patch [new file with mode: 0644]
queue-6.1/series
queue-6.1/tty-xilinx_uartps-split-sysrq-handling.patch [new file with mode: 0644]

diff --git a/queue-6.1/btrfs-avoid-monopolizing-a-core-when-activating-a-swap-file.patch b/queue-6.1/btrfs-avoid-monopolizing-a-core-when-activating-a-swap-file.patch
new file mode 100644 (file)
index 0000000..f58e66d
--- /dev/null
@@ -0,0 +1,42 @@
+From stable+bounces-114132-greg=kroah.com@vger.kernel.org Thu Feb  6 17:21:33 2025
+From: Koichiro Den <koichiro.den@canonical.com>
+Date: Fri,  7 Feb 2025 01:20:55 +0900
+Subject: btrfs: avoid monopolizing a core when activating a swap file
+To: gregkh@linuxfoundation.org, stable@vger.kernel.org
+Cc: wqu@suse.com, fdmanana@suse.com, dsterba@suse.com
+Message-ID: <20250206162055.1387169-2-koichiro.den@canonical.com>
+
+From: Filipe Manana <fdmanana@suse.com>
+
+commit 2c8507c63f5498d4ee4af404a8e44ceae4345056 upstream.
+
+This commit re-attempts the backport of the change to the linux-6.1.y
+branch. Commit bb8e287f596b ("btrfs: avoid monopolizing a core when
+activating a swap file") on this branch was reverted.
+
+During swap activation we iterate over the extents of a file and we can
+have many thousands of them, so we can end up in a busy loop monopolizing
+a core. Avoid this by doing a voluntary reschedule after processing each
+extent.
+
+CC: stable@vger.kernel.org # 5.4+
+Reviewed-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Koichiro Den <koichiro.den@canonical.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/btrfs/inode.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -11368,6 +11368,8 @@ static int btrfs_swap_activate(struct sw
+               }
+               start += len;
++
++              cond_resched();
+       }
+       if (bsi.block_len)
diff --git a/queue-6.1/cachefiles-fix-null-pointer-dereference-in-object-file.patch b/queue-6.1/cachefiles-fix-null-pointer-dereference-in-object-file.patch
new file mode 100644 (file)
index 0000000..d716313
--- /dev/null
@@ -0,0 +1,138 @@
+From 31ad74b20227ce6b40910ff78b1c604e42975cf1 Mon Sep 17 00:00:00 2001
+From: Zizhi Wo <wozizhi@huawei.com>
+Date: Thu, 7 Nov 2024 19:06:48 +0800
+Subject: cachefiles: Fix NULL pointer dereference in object->file
+
+From: Zizhi Wo <wozizhi@huawei.com>
+
+commit 31ad74b20227ce6b40910ff78b1c604e42975cf1 upstream.
+
+At present, the object->file has the NULL pointer dereference problem in
+ondemand-mode. The root cause is that the allocated fd and object->file
+lifetime are inconsistent, and the user-space invocation to anon_fd uses
+object->file. Following is the process that triggers the issue:
+
+         [write fd]                            [umount]
+cachefiles_ondemand_fd_write_iter
+                                      fscache_cookie_state_machine
+                                        cachefiles_withdraw_cookie
+  if (!file) return -ENOBUFS
+                                          cachefiles_clean_up_object
+                                            cachefiles_unmark_inode_in_use
+                                            fput(object->file)
+                                            object->file = NULL
+  // file NULL pointer dereference!
+  __cachefiles_write(..., file, ...)
+
+Fix this issue by add an additional reference count to the object->file
+before write/llseek, and decrement after it finished.
+
+Fixes: c8383054506c ("cachefiles: notify the user daemon when looking up cookie")
+Signed-off-by: Zizhi Wo <wozizhi@huawei.com>
+Link: https://lore.kernel.org/r/20241107110649.3980193-5-wozizhi@huawei.com
+Reviewed-by: David Howells <dhowells@redhat.com>
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Bin Lan <lanbincn@qq.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/cachefiles/interface.c |   14 ++++++++++----
+ fs/cachefiles/ondemand.c  |   30 ++++++++++++++++++++++++------
+ 2 files changed, 34 insertions(+), 10 deletions(-)
+
+--- a/fs/cachefiles/interface.c
++++ b/fs/cachefiles/interface.c
+@@ -327,6 +327,8 @@ static void cachefiles_commit_object(str
+ static void cachefiles_clean_up_object(struct cachefiles_object *object,
+                                      struct cachefiles_cache *cache)
+ {
++      struct file *file;
++
+       if (test_bit(FSCACHE_COOKIE_RETIRED, &object->cookie->flags)) {
+               if (!test_bit(CACHEFILES_OBJECT_USING_TMPFILE, &object->flags)) {
+                       cachefiles_see_object(object, cachefiles_obj_see_clean_delete);
+@@ -342,10 +344,14 @@ static void cachefiles_clean_up_object(s
+       }
+       cachefiles_unmark_inode_in_use(object, object->file);
+-      if (object->file) {
+-              fput(object->file);
+-              object->file = NULL;
+-      }
++
++      spin_lock(&object->lock);
++      file = object->file;
++      object->file = NULL;
++      spin_unlock(&object->lock);
++
++      if (file)
++              fput(file);
+ }
+ /*
+--- a/fs/cachefiles/ondemand.c
++++ b/fs/cachefiles/ondemand.c
+@@ -61,20 +61,26 @@ static ssize_t cachefiles_ondemand_fd_wr
+ {
+       struct cachefiles_object *object = kiocb->ki_filp->private_data;
+       struct cachefiles_cache *cache = object->volume->cache;
+-      struct file *file = object->file;
++      struct file *file;
+       size_t len = iter->count;
+       loff_t pos = kiocb->ki_pos;
+       const struct cred *saved_cred;
+       int ret;
+-      if (!file)
++      spin_lock(&object->lock);
++      file = object->file;
++      if (!file) {
++              spin_unlock(&object->lock);
+               return -ENOBUFS;
++      }
++      get_file(file);
++      spin_unlock(&object->lock);
+       cachefiles_begin_secure(cache, &saved_cred);
+       ret = __cachefiles_prepare_write(object, file, &pos, &len, true);
+       cachefiles_end_secure(cache, saved_cred);
+       if (ret < 0)
+-              return ret;
++              goto out;
+       trace_cachefiles_ondemand_fd_write(object, file_inode(file), pos, len);
+       ret = __cachefiles_write(object, file, pos, iter, NULL, NULL);
+@@ -83,6 +89,8 @@ static ssize_t cachefiles_ondemand_fd_wr
+               kiocb->ki_pos += ret;
+       }
++out:
++      fput(file);
+       return ret;
+ }
+@@ -90,12 +98,22 @@ static loff_t cachefiles_ondemand_fd_lls
+                                           int whence)
+ {
+       struct cachefiles_object *object = filp->private_data;
+-      struct file *file = object->file;
++      struct file *file;
++      loff_t ret;
+-      if (!file)
++      spin_lock(&object->lock);
++      file = object->file;
++      if (!file) {
++              spin_unlock(&object->lock);
+               return -ENOBUFS;
++      }
++      get_file(file);
++      spin_unlock(&object->lock);
+-      return vfs_llseek(file, pos, whence);
++      ret = vfs_llseek(file, pos, whence);
++      fput(file);
++
++      return ret;
+ }
+ static long cachefiles_ondemand_fd_ioctl(struct file *filp, unsigned int ioctl,
diff --git a/queue-6.1/drm-sti-hdmi-use-eld_mutex-to-protect-access-to-conn.patch b/queue-6.1/drm-sti-hdmi-use-eld_mutex-to-protect-access-to-conn.patch
deleted file mode 100644 (file)
index d4aa6f4..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-From 60ef10ac7a15a6cfc0d7c5f9f5381d9893946e3c Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Fri, 6 Dec 2024 11:43:12 +0200
-Subject: drm/sti: hdmi: use eld_mutex to protect access to connector->eld
-
-From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
-
-[ Upstream commit e99c0b517bcd53cf61f998a3c4291333401cb391 ]
-
-Reading access to connector->eld can happen at the same time the
-drm_edid_to_eld() updates the data. Take the newly added eld_mutex in
-order to protect connector->eld from concurrent access.
-
-Reviewed-by: Maxime Ripard <mripard@kernel.org>
-Acked-by: Raphael Gallais-Pou <rgallaispou@gmail.com>
-Link: https://patchwork.freedesktop.org/patch/msgid/20241206-drm-connector-eld-mutex-v2-9-c9bce1ee8bea@linaro.org
-Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/gpu/drm/sti/sti_hdmi.c | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
-index 8539fe1fedc4c..fdb28e05720ad 100644
---- a/drivers/gpu/drm/sti/sti_hdmi.c
-+++ b/drivers/gpu/drm/sti/sti_hdmi.c
-@@ -1220,7 +1220,9 @@ static int hdmi_audio_get_eld(struct device *dev, void *data, uint8_t *buf, size
-       struct drm_connector *connector = hdmi->drm_connector;
-       DRM_DEBUG_DRIVER("\n");
-+      mutex_lock(&connector->eld_mutex);
-       memcpy(buf, connector->eld, min(sizeof(connector->eld), len));
-+      mutex_unlock(&connector->eld_mutex);
-       return 0;
- }
--- 
-2.39.5
-
diff --git a/queue-6.1/ext4-filesystems-without-casefold-feature-cannot-be-mounted-with-siphash.patch b/queue-6.1/ext4-filesystems-without-casefold-feature-cannot-be-mounted-with-siphash.patch
new file mode 100644 (file)
index 0000000..e593084
--- /dev/null
@@ -0,0 +1,40 @@
+From 985b67cd86392310d9e9326de941c22fc9340eec Mon Sep 17 00:00:00 2001
+From: Lizhi Xu <lizhi.xu@windriver.com>
+Date: Wed, 5 Jun 2024 09:23:35 +0800
+Subject: ext4: filesystems without casefold feature cannot be mounted with siphash
+
+From: Lizhi Xu <lizhi.xu@windriver.com>
+
+commit 985b67cd86392310d9e9326de941c22fc9340eec upstream.
+
+When mounting the ext4 filesystem, if the default hash version is set to
+DX_HASH_SIPHASH but the casefold feature is not set, exit the mounting.
+
+Reported-by: syzbot+340581ba9dceb7e06fb3@syzkaller.appspotmail.com
+Signed-off-by: Lizhi Xu <lizhi.xu@windriver.com>
+Link: https://patch.msgid.link/20240605012335.44086-1-lizhi.xu@windriver.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Bruno VERNAY <bruno.vernay@se.com>
+Signed-off-by: Victor Giraud <vgiraud.opensource@witekio.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/super.c |    8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3547,6 +3547,14 @@ int ext4_feature_set_ok(struct super_blo
+       }
+ #endif
++      if (EXT4_SB(sb)->s_es->s_def_hash_version == DX_HASH_SIPHASH &&
++          !ext4_has_feature_casefold(sb)) {
++              ext4_msg(sb, KERN_ERR,
++                       "Filesystem without casefold feature cannot be "
++                       "mounted with siphash");
++              return 0;
++      }
++
+       if (readonly)
+               return 1;
diff --git a/queue-6.1/maple_tree-fix-static-analyser-cppcheck-issue.patch b/queue-6.1/maple_tree-fix-static-analyser-cppcheck-issue.patch
new file mode 100644 (file)
index 0000000..a60ed74
--- /dev/null
@@ -0,0 +1,68 @@
+From 5729e06c819184b7ba40869c1ad53e1a463040b2 Mon Sep 17 00:00:00 2001
+From: "Liam R. Howlett" <Liam.Howlett@oracle.com>
+Date: Thu, 18 May 2023 10:55:10 -0400
+Subject: maple_tree: fix static analyser cppcheck issue
+
+From: Liam R. Howlett <Liam.Howlett@oracle.com>
+
+commit 5729e06c819184b7ba40869c1ad53e1a463040b2 upstream.
+
+Patch series "Maple tree mas_{next,prev}_range() and cleanup", v4.
+
+This patchset contains a number of clean ups to the code to make it more
+usable (next/prev range), the addition of debug output formatting, the
+addition of printing the maple state information in the WARN_ON/BUG_ON
+code.
+
+There is also work done here to keep nodes active during iterations to
+reduce the necessity of re-walking the tree.
+
+Finally, there is a new interface added to move to the next or previous
+range in the tree, even if it is empty.
+
+The organisation of the patches is as follows:
+
+0001-0004 - Small clean ups
+0005-0018 - Additional debug options and WARN_ON/BUG_ON changes
+0019      - Test module __init and __exit addition
+0020-0021 - More functional clean ups
+0022-0026 - Changes to keep nodes active
+0027-0034 - Add new mas_{prev,next}_range()
+0035      - Use new mas_{prev,next}_range() in mmap_region()
+
+
+This patch (of 35):
+
+Static analyser of the maple tree code noticed that the split variable is
+being used to dereference into an array prior to checking the variable
+itself.  Fix this issue by changing the order of the statement to check
+the variable first.
+
+Link: https://lkml.kernel.org/r/20230518145544.1722059-1-Liam.Howlett@oracle.com
+Link: https://lkml.kernel.org/r/20230518145544.1722059-2-Liam.Howlett@oracle.com
+Signed-off-by: Liam R. Howlett <Liam.Howlett@oracle.com>
+Reported-by: David Binderman <dcb314@hotmail.com>
+Reviewed-by: Peng Zhang<zhangpeng.00@bytedance.com>
+Cc: Sergey Senozhatsky <senozhatsky@chromium.org>
+Cc: Vernon Yang <vernon2gm@gmail.com>
+Cc: Wei Yang <richard.weiyang@gmail.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ lib/maple_tree.c |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/lib/maple_tree.c
++++ b/lib/maple_tree.c
+@@ -1935,8 +1935,9 @@ static inline int mab_calc_split(struct
+                * causes one node to be deficient.
+                * NOTE: mt_min_slots is 1 based, b_end and split are zero.
+                */
+-              while (((bn->pivot[split] - min) < slot_count - 1) &&
+-                     (split < slot_count - 1) && (b_end - split > slot_min))
++              while ((split < slot_count - 1) &&
++                     ((bn->pivot[split] - min) < slot_count - 1) &&
++                     (b_end - split > slot_min))
+                       split++;
+       }
diff --git a/queue-6.1/maple_tree-simplify-split-calculation.patch b/queue-6.1/maple_tree-simplify-split-calculation.patch
new file mode 100644 (file)
index 0000000..f006062
--- /dev/null
@@ -0,0 +1,112 @@
+From 4f6a6bed0bfef4b966f076f33eb4f5547226056a Mon Sep 17 00:00:00 2001
+From: Wei Yang <richard.weiyang@gmail.com>
+Date: Wed, 13 Nov 2024 03:16:14 +0000
+Subject: maple_tree: simplify split calculation
+
+From: Wei Yang <richard.weiyang@gmail.com>
+
+commit 4f6a6bed0bfef4b966f076f33eb4f5547226056a upstream.
+
+Patch series "simplify split calculation", v3.
+
+
+This patch (of 3):
+
+The current calculation for splitting nodes tries to enforce a minimum
+span on the leaf nodes.  This code is complex and never worked correctly
+to begin with, due to the min value being passed as 0 for all leaves.
+
+The calculation should just split the data as equally as possible
+between the new nodes.  Note that b_end will be one more than the data,
+so the left side is still favoured in the calculation.
+
+The current code may also lead to a deficient node by not leaving enough
+data for the right side of the split. This issue is also addressed with
+the split calculation change.
+
+[Liam.Howlett@Oracle.com: rephrase the change log]
+Link: https://lkml.kernel.org/r/20241113031616.10530-1-richard.weiyang@gmail.com
+Link: https://lkml.kernel.org/r/20241113031616.10530-2-richard.weiyang@gmail.com
+Fixes: 54a611b60590 ("Maple Tree: add new data structure")
+Signed-off-by: Wei Yang <richard.weiyang@gmail.com>
+Reviewed-by: Liam R. Howlett <Liam.Howlett@Oracle.com>
+Cc: Sidhartha Kumar <sidhartha.kumar@oracle.com>
+Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ lib/maple_tree.c |   23 ++++++-----------------
+ 1 file changed, 6 insertions(+), 17 deletions(-)
+
+--- a/lib/maple_tree.c
++++ b/lib/maple_tree.c
+@@ -1890,11 +1890,11 @@ static inline int mab_no_null_split(stru
+  * Return: The first split location.  The middle split is set in @mid_split.
+  */
+ static inline int mab_calc_split(struct ma_state *mas,
+-       struct maple_big_node *bn, unsigned char *mid_split, unsigned long min)
++       struct maple_big_node *bn, unsigned char *mid_split)
+ {
+       unsigned char b_end = bn->b_end;
+       int split = b_end / 2; /* Assume equal split. */
+-      unsigned char slot_min, slot_count = mt_slots[bn->type];
++      unsigned char slot_count = mt_slots[bn->type];
+       /*
+        * To support gap tracking, all NULL entries are kept together and a node cannot
+@@ -1927,18 +1927,7 @@ static inline int mab_calc_split(struct
+               split = b_end / 3;
+               *mid_split = split * 2;
+       } else {
+-              slot_min = mt_min_slots[bn->type];
+-
+               *mid_split = 0;
+-              /*
+-               * Avoid having a range less than the slot count unless it
+-               * causes one node to be deficient.
+-               * NOTE: mt_min_slots is 1 based, b_end and split are zero.
+-               */
+-              while ((split < slot_count - 1) &&
+-                     ((bn->pivot[split] - min) < slot_count - 1) &&
+-                     (b_end - split > slot_min))
+-                      split++;
+       }
+       /* Avoid ending a node on a NULL entry */
+@@ -2664,7 +2653,7 @@ static inline struct maple_enode
+ static inline unsigned char mas_mab_to_node(struct ma_state *mas,
+       struct maple_big_node *b_node, struct maple_enode **left,
+       struct maple_enode **right, struct maple_enode **middle,
+-      unsigned char *mid_split, unsigned long min)
++      unsigned char *mid_split)
+ {
+       unsigned char split = 0;
+       unsigned char slot_count = mt_slots[b_node->type];
+@@ -2677,7 +2666,7 @@ static inline unsigned char mas_mab_to_n
+       if (b_node->b_end < slot_count) {
+               split = b_node->b_end;
+       } else {
+-              split = mab_calc_split(mas, b_node, mid_split, min);
++              split = mab_calc_split(mas, b_node, mid_split);
+               *right = mas_new_ma_node(mas, b_node);
+       }
+@@ -3076,7 +3065,7 @@ static int mas_spanning_rebalance(struct
+               mast->bn->b_end--;
+               mast->bn->type = mte_node_type(mast->orig_l->node);
+               split = mas_mab_to_node(mas, mast->bn, &left, &right, &middle,
+-                                      &mid_split, mast->orig_l->min);
++                                      &mid_split);
+               mast_set_split_parents(mast, left, middle, right, split,
+                                      mid_split);
+               mast_cp_to_nodes(mast, left, middle, right, split, mid_split);
+@@ -3591,7 +3580,7 @@ static int mas_split(struct ma_state *ma
+               if (mas_push_data(mas, height, &mast, false))
+                       break;
+-              split = mab_calc_split(mas, b_node, &mid_split, prev_l_mas.min);
++              split = mab_calc_split(mas, b_node, &mid_split);
+               mast_split_data(&mast, mas, split);
+               /*
+                * Usually correct, mab_mas_cp in the above call overwrites
diff --git a/queue-6.1/mptcp-pm-only-set-fullmesh-for-subflow-endp.patch b/queue-6.1/mptcp-pm-only-set-fullmesh-for-subflow-endp.patch
new file mode 100644 (file)
index 0000000..2a10766
--- /dev/null
@@ -0,0 +1,114 @@
+From stable+bounces-114459-greg=kroah.com@vger.kernel.org Sun Feb  9 18:48:42 2025
+From: "Matthieu Baerts (NGI0)" <matttbe@kernel.org>
+Date: Sun,  9 Feb 2025 18:48:30 +0100
+Subject: mptcp: pm: only set fullmesh for subflow endp
+To: mptcp@lists.linux.dev, stable@vger.kernel.org, gregkh@linuxfoundation.org
+Cc: "Matthieu Baerts (NGI0)" <matttbe@kernel.org>, syzbot+cd16e79c1e45f3fe0377@syzkaller.appspotmail.com, Mat Martineau <martineau@kernel.org>, Jakub Kicinski <kuba@kernel.org>
+Message-ID: <20250209174828.3397229-5-matttbe@kernel.org>
+
+From: "Matthieu Baerts (NGI0)" <matttbe@kernel.org>
+
+commit 1bb0d1348546ad059f55c93def34e67cb2a034a6 upstream.
+
+With the in-kernel path-manager, it is possible to change the 'fullmesh'
+flag. The code in mptcp_pm_nl_fullmesh() expects to change it only on
+'subflow' endpoints, to recreate more or less subflows using the linked
+address.
+
+Unfortunately, the set_flags() hook was a bit more permissive, and
+allowed 'implicit' endpoints to get the 'fullmesh' flag while it is not
+allowed before.
+
+That's what syzbot found, triggering the following warning:
+
+  WARNING: CPU: 0 PID: 6499 at net/mptcp/pm_netlink.c:1496 __mark_subflow_endp_available net/mptcp/pm_netlink.c:1496 [inline]
+  WARNING: CPU: 0 PID: 6499 at net/mptcp/pm_netlink.c:1496 mptcp_pm_nl_fullmesh net/mptcp/pm_netlink.c:1980 [inline]
+  WARNING: CPU: 0 PID: 6499 at net/mptcp/pm_netlink.c:1496 mptcp_nl_set_flags net/mptcp/pm_netlink.c:2003 [inline]
+  WARNING: CPU: 0 PID: 6499 at net/mptcp/pm_netlink.c:1496 mptcp_pm_nl_set_flags+0x974/0xdc0 net/mptcp/pm_netlink.c:2064
+  Modules linked in:
+  CPU: 0 UID: 0 PID: 6499 Comm: syz.1.413 Not tainted 6.13.0-rc5-syzkaller-00172-gd1bf27c4e176 #0
+  Hardware name: Google Compute Engine/Google Compute Engine, BIOS Google 09/13/2024
+  RIP: 0010:__mark_subflow_endp_available net/mptcp/pm_netlink.c:1496 [inline]
+  RIP: 0010:mptcp_pm_nl_fullmesh net/mptcp/pm_netlink.c:1980 [inline]
+  RIP: 0010:mptcp_nl_set_flags net/mptcp/pm_netlink.c:2003 [inline]
+  RIP: 0010:mptcp_pm_nl_set_flags+0x974/0xdc0 net/mptcp/pm_netlink.c:2064
+  Code: 01 00 00 49 89 c5 e8 fb 45 e8 f5 e9 b8 fc ff ff e8 f1 45 e8 f5 4c 89 f7 be 03 00 00 00 e8 44 1d 0b f9 eb a0 e8 dd 45 e8 f5 90 <0f> 0b 90 e9 17 ff ff ff 89 d9 80 e1 07 38 c1 0f 8c c9 fc ff ff 48
+  RSP: 0018:ffffc9000d307240 EFLAGS: 00010293
+  RAX: ffffffff8bb72e03 RBX: 0000000000000000 RCX: ffff88807da88000
+  RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
+  RBP: ffffc9000d307430 R08: ffffffff8bb72cf0 R09: 1ffff1100b842a5e
+  R10: dffffc0000000000 R11: ffffed100b842a5f R12: ffff88801e2e5ac0
+  R13: ffff88805c214800 R14: ffff88805c2152e8 R15: 1ffff1100b842a5d
+  FS:  00005555619f6500(0000) GS:ffff8880b8600000(0000) knlGS:0000000000000000
+  CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+  CR2: 0000000020002840 CR3: 00000000247e6000 CR4: 00000000003526f0
+  DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+  DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+  Call Trace:
+   <TASK>
+   genl_family_rcv_msg_doit net/netlink/genetlink.c:1115 [inline]
+   genl_family_rcv_msg net/netlink/genetlink.c:1195 [inline]
+   genl_rcv_msg+0xb14/0xec0 net/netlink/genetlink.c:1210
+   netlink_rcv_skb+0x1e3/0x430 net/netlink/af_netlink.c:2542
+   genl_rcv+0x28/0x40 net/netlink/genetlink.c:1219
+   netlink_unicast_kernel net/netlink/af_netlink.c:1321 [inline]
+   netlink_unicast+0x7f6/0x990 net/netlink/af_netlink.c:1347
+   netlink_sendmsg+0x8e4/0xcb0 net/netlink/af_netlink.c:1891
+   sock_sendmsg_nosec net/socket.c:711 [inline]
+   __sock_sendmsg+0x221/0x270 net/socket.c:726
+   ____sys_sendmsg+0x52a/0x7e0 net/socket.c:2583
+   ___sys_sendmsg net/socket.c:2637 [inline]
+   __sys_sendmsg+0x269/0x350 net/socket.c:2669
+   do_syscall_x64 arch/x86/entry/common.c:52 [inline]
+   do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83
+   entry_SYSCALL_64_after_hwframe+0x77/0x7f
+  RIP: 0033:0x7f5fe8785d29
+  Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 a8 ff ff ff f7 d8 64 89 01 48
+  RSP: 002b:00007fff571f5558 EFLAGS: 00000246 ORIG_RAX: 000000000000002e
+  RAX: ffffffffffffffda RBX: 00007f5fe8975fa0 RCX: 00007f5fe8785d29
+  RDX: 0000000000000000 RSI: 0000000020000480 RDI: 0000000000000007
+  RBP: 00007f5fe8801b08 R08: 0000000000000000 R09: 0000000000000000
+  R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
+  R13: 00007f5fe8975fa0 R14: 00007f5fe8975fa0 R15: 00000000000011f4
+   </TASK>
+
+Here, syzbot managed to set the 'fullmesh' flag on an 'implicit' and
+used -- according to 'id_avail_bitmap' -- endpoint, causing the PM to
+try decrement the local_addr_used counter which is only incremented for
+the 'subflow' endpoint.
+
+Note that 'no type' endpoints -- not 'subflow', 'signal', 'implicit' --
+are fine, because their ID will not be marked as used in the 'id_avail'
+bitmap, and setting 'fullmesh' can help forcing the creation of subflow
+when receiving an ADD_ADDR.
+
+Fixes: 73c762c1f07d ("mptcp: set fullmesh flag in pm_netlink")
+Cc: stable@vger.kernel.org
+Reported-by: syzbot+cd16e79c1e45f3fe0377@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/6786ac51.050a0220.216c54.00a6.GAE@google.com
+Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/540
+Reviewed-by: Mat Martineau <martineau@kernel.org>
+Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Link: https://patch.msgid.link/20250123-net-mptcp-syzbot-issues-v1-2-af73258a726f@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+[ Conflicts in pm_netlink.c, because the code has been moved around in
+  commit 6a42477fe449 ("mptcp: update set_flags interfaces"), but the
+  same fix can still be applied at the original place. ]
+Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/mptcp/pm_netlink.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/net/mptcp/pm_netlink.c
++++ b/net/mptcp/pm_netlink.c
+@@ -2086,7 +2086,8 @@ static int mptcp_nl_cmd_set_flags(struct
+               return -EINVAL;
+       }
+       if ((addr.flags & MPTCP_PM_ADDR_FLAG_FULLMESH) &&
+-          (entry->flags & MPTCP_PM_ADDR_FLAG_SIGNAL)) {
++          (entry->flags & (MPTCP_PM_ADDR_FLAG_SIGNAL |
++                           MPTCP_PM_ADDR_FLAG_IMPLICIT))) {
+               spin_unlock_bh(&pernet->lock);
+               return -EINVAL;
+       }
diff --git a/queue-6.1/mptcp-prevent-excessive-coalescing-on-receive.patch b/queue-6.1/mptcp-prevent-excessive-coalescing-on-receive.patch
new file mode 100644 (file)
index 0000000..bf923a6
--- /dev/null
@@ -0,0 +1,41 @@
+From stable+bounces-114460-greg=kroah.com@vger.kernel.org Sun Feb  9 18:48:49 2025
+From: "Matthieu Baerts (NGI0)" <matttbe@kernel.org>
+Date: Sun,  9 Feb 2025 18:48:31 +0100
+Subject: mptcp: prevent excessive coalescing on receive
+To: mptcp@lists.linux.dev, stable@vger.kernel.org, gregkh@linuxfoundation.org
+Cc: Paolo Abeni <pabeni@redhat.com>, Mat Martineau <martineau@kernel.org>, "Matthieu Baerts (NGI0)" <matttbe@kernel.org>, Jakub Kicinski <kuba@kernel.org>
+Message-ID: <20250209174828.3397229-6-matttbe@kernel.org>
+
+From: Paolo Abeni <pabeni@redhat.com>
+
+commit 56b824eb49d6258aa0bad09a406ceac3f643cdae upstream.
+
+Currently the skb size after coalescing is only limited by the skb
+layout (the skb must not carry frag_list). A single coalesced skb
+covering several MSS can potentially fill completely the receive
+buffer. In such a case, the snd win will zero until the receive buffer
+will be empty again, affecting tput badly.
+
+Fixes: 8268ed4c9d19 ("mptcp: introduce and use mptcp_try_coalesce()")
+Cc: stable@vger.kernel.org # please delay 2 weeks after 6.13-final release
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Reviewed-by: Mat Martineau <martineau@kernel.org>
+Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Link: https://patch.msgid.link/20241230-net-mptcp-rbuf-fixes-v1-3-8608af434ceb@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/mptcp/protocol.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/net/mptcp/protocol.c
++++ b/net/mptcp/protocol.c
+@@ -149,6 +149,7 @@ static bool mptcp_try_coalesce(struct so
+       int delta;
+       if (MPTCP_SKB_CB(from)->offset ||
++          ((to->len + from->len) > (sk->sk_rcvbuf >> 3)) ||
+           !skb_try_coalesce(to, from, &fragstolen, &delta))
+               return false;
diff --git a/queue-6.1/ocfs2-check-dir-i_size-in-ocfs2_find_entry.patch b/queue-6.1/ocfs2-check-dir-i_size-in-ocfs2_find_entry.patch
new file mode 100644 (file)
index 0000000..5eba226
--- /dev/null
@@ -0,0 +1,217 @@
+From b0fce54b8c0d8e5f2b4c243c803c5996e73baee8 Mon Sep 17 00:00:00 2001
+From: Su Yue <glass.su@suse.com>
+Date: Mon, 6 Jan 2025 22:06:40 +0800
+Subject: ocfs2: check dir i_size in ocfs2_find_entry
+
+From: Su Yue <glass.su@suse.com>
+
+commit b0fce54b8c0d8e5f2b4c243c803c5996e73baee8 upstream.
+
+syz reports an out of bounds read:
+
+==================================================================
+BUG: KASAN: slab-out-of-bounds in ocfs2_match fs/ocfs2/dir.c:334
+[inline]
+BUG: KASAN: slab-out-of-bounds in ocfs2_search_dirblock+0x283/0x6e0
+fs/ocfs2/dir.c:367
+Read of size 1 at addr ffff88804d8b9982 by task syz-executor.2/14802
+
+CPU: 0 UID: 0 PID: 14802 Comm: syz-executor.2 Not tainted 6.13.0-rc4 #2
+Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1
+04/01/2014
+Sched_ext: serialise (enabled+all), task: runnable_at=-10ms
+Call Trace:
+<TASK>
+__dump_stack lib/dump_stack.c:94 [inline]
+dump_stack_lvl+0x229/0x350 lib/dump_stack.c:120
+print_address_description mm/kasan/report.c:378 [inline]
+print_report+0x164/0x530 mm/kasan/report.c:489
+kasan_report+0x147/0x180 mm/kasan/report.c:602
+ocfs2_match fs/ocfs2/dir.c:334 [inline]
+ocfs2_search_dirblock+0x283/0x6e0 fs/ocfs2/dir.c:367
+ocfs2_find_entry_id fs/ocfs2/dir.c:414 [inline]
+ocfs2_find_entry+0x1143/0x2db0 fs/ocfs2/dir.c:1078
+ocfs2_find_files_on_disk+0x18e/0x530 fs/ocfs2/dir.c:1981
+ocfs2_lookup_ino_from_name+0xb6/0x110 fs/ocfs2/dir.c:2003
+ocfs2_lookup+0x30a/0xd40 fs/ocfs2/namei.c:122
+lookup_open fs/namei.c:3627 [inline]
+open_last_lookups fs/namei.c:3748 [inline]
+path_openat+0x145a/0x3870 fs/namei.c:3984
+do_filp_open+0xe9/0x1c0 fs/namei.c:4014
+do_sys_openat2+0x135/0x1d0 fs/open.c:1402
+do_sys_open fs/open.c:1417 [inline]
+__do_sys_openat fs/open.c:1433 [inline]
+__se_sys_openat fs/open.c:1428 [inline]
+__x64_sys_openat+0x15d/0x1c0 fs/open.c:1428
+do_syscall_x64 arch/x86/entry/common.c:52 [inline]
+do_syscall_64+0xf6/0x210 arch/x86/entry/common.c:83
+entry_SYSCALL_64_after_hwframe+0x77/0x7f
+RIP: 0033:0x7f01076903ad
+Code: c3 e8 a7 2b 00 00 0f 1f 80 00 00 00 00 f3 0f 1e fa 48 89 f8 48 89
+f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01
+f0 ff ff 73 01 c3 48 c7 c1 b0 ff ff ff f7 d8 64 89 01 48
+RSP: 002b:00007f01084acfc8 EFLAGS: 00000246 ORIG_RAX: 0000000000000101
+RAX: ffffffffffffffda RBX: 00007f01077cbf80 RCX: 00007f01076903ad
+RDX: 0000000000105042 RSI: 0000000020000080 RDI: ffffffffffffff9c
+RBP: 00007f01077cbf80 R08: 0000000000000000 R09: 0000000000000000
+R10: 00000000000001ff R11: 0000000000000246 R12: 0000000000000000
+R13: 00007f01077cbf80 R14: 00007f010764fc90 R15: 00007f010848d000
+</TASK>
+==================================================================
+
+And a general protection fault in ocfs2_prepare_dir_for_insert:
+
+==================================================================
+loop0: detected capacity change from 0 to 32768
+JBD2: Ignoring recovery information on journal
+ocfs2: Mounting device (7,0) on (node local, slot 0) with ordered data
+mode.
+Oops: general protection fault, probably for non-canonical address
+0xdffffc0000000001: 0000 [#1] PREEMPT SMP KASAN NOPTI
+KASAN: null-ptr-deref in range [0x0000000000000008-0x000000000000000f]
+CPU: 0 UID: 0 PID: 5096 Comm: syz-executor792 Not tainted
+6.11.0-rc4-syzkaller-00002-gb0da640826ba #0
+Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS
+1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
+RIP: 0010:ocfs2_find_dir_space_id fs/ocfs2/dir.c:3406 [inline]
+RIP: 0010:ocfs2_prepare_dir_for_insert+0x3309/0x5c70 fs/ocfs2/dir.c:4280
+Code: 00 00 e8 2a 25 13 fe e9 ba 06 00 00 e8 20 25 13 fe e9 4f 01 00 00
+e8 16 25 13 fe 49 8d 7f 08 49 8d 5f 09 48 89 f8 48 c1 e8 03 <42> 0f b6
+04 20 84 c0 0f 85 bd 23 00 00 48 89 d8 48 c1 e8 03 42 0f
+RSP: 0018:ffffc9000af9f020 EFLAGS: 00010202
+RAX: 0000000000000001 RBX: 0000000000000009 RCX: ffff88801e27a440
+RDX: 0000000000000000 RSI: 0000000000000400 RDI: 0000000000000008
+RBP: ffffc9000af9f830 R08: ffffffff8380395b R09: ffffffff838090a7
+R10: 0000000000000002 R11: ffff88801e27a440 R12: dffffc0000000000
+R13: ffff88803c660878 R14: f700000000000088 R15: 0000000000000000
+FS:  000055555a677380(0000) GS:ffff888020800000(0000)
+knlGS:0000000000000000
+CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 0000560bce569178 CR3: 000000001de5a000 CR4: 0000000000350ef0
+DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+Call Trace:
+<TASK>
+ocfs2_mknod+0xcaf/0x2b40 fs/ocfs2/namei.c:292
+vfs_mknod+0x36d/0x3b0 fs/namei.c:4088
+do_mknodat+0x3ec/0x5b0
+__do_sys_mknodat fs/namei.c:4166 [inline]
+__se_sys_mknodat fs/namei.c:4163 [inline]
+__x64_sys_mknodat+0xa7/0xc0 fs/namei.c:4163
+do_syscall_x64 arch/x86/entry/common.c:52 [inline]
+do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83
+entry_SYSCALL_64_after_hwframe+0x77/0x7f
+RIP: 0033:0x7f2dafda3a99
+Code: 28 00 00 00 75 05 48 83 c4 28 c3 e8 f1 17 00 00 90 48 89
+f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08
+0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b8 ff ff ff f7 d8
+64 89 01 48
+RSP: 002b:00007ffe336a6658 EFLAGS: 00000246 ORIG_RAX:
+0000000000000103
+RAX: ffffffffffffffda RBX: 0000000000000000 RCX:
+00007f2dafda3a99
+RDX: 00000000000021c0 RSI: 0000000020000040 RDI:
+00000000ffffff9c
+RBP: 00007f2dafe1b5f0 R08: 0000000000004480 R09:
+000055555a6784c0
+R10: 0000000000000103 R11: 0000000000000246 R12:
+00007ffe336a6680
+R13: 00007ffe336a68a8 R14: 431bde82d7b634db R15:
+00007f2dafdec03b
+</TASK>
+==================================================================
+
+The two reports are all caused invalid negative i_size of dir inode.  For
+ocfs2, dir_inode can't be negative or zero.
+
+Here add a check in which is called by ocfs2_check_dir_for_entry().  It
+fixes the second report as ocfs2_check_dir_for_entry() must be called
+before ocfs2_prepare_dir_for_insert().  Also set a up limit for dir with
+OCFS2_INLINE_DATA_FL.  The i_size can't be great than blocksize.
+
+Link: https://lkml.kernel.org/r/20250106140640.92260-1-glass.su@suse.com
+Reported-by: Jiacheng Xu <stitch@zju.edu.cn>
+Link: https://lore.kernel.org/ocfs2-devel/17a04f01.1ae74.19436d003fc.Coremail.stitch@zju.edu.cn/T/#u
+Reported-by: syzbot+5a64828fcc4c2ad9b04f@syzkaller.appspotmail.com
+Link: https://lore.kernel.org/all/0000000000005894f3062018caf1@google.com/T/
+Signed-off-by: Su Yue <glass.su@suse.com>
+Reviewed-by: Heming Zhao <heming.zhao@suse.com>
+Reviewed-by: Joseph Qi <joseph.qi@linux.alibaba.com>
+Cc: Mark Fasheh <mark@fasheh.com>
+Cc: Joel Becker <jlbec@evilplan.org>
+Cc: Junxiao Bi <junxiao.bi@oracle.com>
+Cc: Changwei Ge <gechangwei@live.cn>
+Cc: Jun Piao <piaojun@huawei.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ocfs2/dir.c |   25 +++++++++++++++++++++----
+ 1 file changed, 21 insertions(+), 4 deletions(-)
+
+--- a/fs/ocfs2/dir.c
++++ b/fs/ocfs2/dir.c
+@@ -1065,26 +1065,39 @@ int ocfs2_find_entry(const char *name, i
+ {
+       struct buffer_head *bh;
+       struct ocfs2_dir_entry *res_dir = NULL;
++      int ret = 0;
+       if (ocfs2_dir_indexed(dir))
+               return ocfs2_find_entry_dx(name, namelen, dir, lookup);
++      if (unlikely(i_size_read(dir) <= 0)) {
++              ret = -EFSCORRUPTED;
++              mlog_errno(ret);
++              goto out;
++      }
+       /*
+        * The unindexed dir code only uses part of the lookup
+        * structure, so there's no reason to push it down further
+        * than this.
+        */
+-      if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL)
++      if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL) {
++              if (unlikely(i_size_read(dir) > dir->i_sb->s_blocksize)) {
++                      ret = -EFSCORRUPTED;
++                      mlog_errno(ret);
++                      goto out;
++              }
+               bh = ocfs2_find_entry_id(name, namelen, dir, &res_dir);
+-      else
++      } else {
+               bh = ocfs2_find_entry_el(name, namelen, dir, &res_dir);
++      }
+       if (bh == NULL)
+               return -ENOENT;
+       lookup->dl_leaf_bh = bh;
+       lookup->dl_entry = res_dir;
+-      return 0;
++out:
++      return ret;
+ }
+ /*
+@@ -2011,6 +2024,7 @@ int ocfs2_lookup_ino_from_name(struct in
+  *
+  * Return 0 if the name does not exist
+  * Return -EEXIST if the directory contains the name
++ * Return -EFSCORRUPTED if found corruption
+  *
+  * Callers should have i_rwsem + a cluster lock on dir
+  */
+@@ -2024,9 +2038,12 @@ int ocfs2_check_dir_for_entry(struct ino
+       trace_ocfs2_check_dir_for_entry(
+               (unsigned long long)OCFS2_I(dir)->ip_blkno, namelen, name);
+-      if (ocfs2_find_entry(name, namelen, dir, &lookup) == 0) {
++      ret = ocfs2_find_entry(name, namelen, dir, &lookup);
++      if (ret == 0) {
+               ret = -EEXIST;
+               mlog_errno(ret);
++      } else if (ret == -ENOENT) {
++              ret = 0;
+       }
+       ocfs2_free_dir_lookup_result(&lookup);
diff --git a/queue-6.1/pps-fix-a-use-after-free.patch b/queue-6.1/pps-fix-a-use-after-free.patch
new file mode 100644 (file)
index 0000000..f14cd35
--- /dev/null
@@ -0,0 +1,600 @@
+From c79a39dc8d060b9e64e8b0fa9d245d44befeefbe Mon Sep 17 00:00:00 2001
+From: Calvin Owens <calvin@wbinvd.org>
+Date: Mon, 11 Nov 2024 20:13:29 -0800
+Subject: pps: Fix a use-after-free
+
+From: Calvin Owens <calvin@wbinvd.org>
+
+commit c79a39dc8d060b9e64e8b0fa9d245d44befeefbe upstream.
+
+On a board running ntpd and gpsd, I'm seeing a consistent use-after-free
+in sys_exit() from gpsd when rebooting:
+
+    pps pps1: removed
+    ------------[ cut here ]------------
+    kobject: '(null)' (00000000db4bec24): is not initialized, yet kobject_put() is being called.
+    WARNING: CPU: 2 PID: 440 at lib/kobject.c:734 kobject_put+0x120/0x150
+    CPU: 2 UID: 299 PID: 440 Comm: gpsd Not tainted 6.11.0-rc6-00308-gb31c44928842 #1
+    Hardware name: Raspberry Pi 4 Model B Rev 1.1 (DT)
+    pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
+    pc : kobject_put+0x120/0x150
+    lr : kobject_put+0x120/0x150
+    sp : ffffffc0803d3ae0
+    x29: ffffffc0803d3ae0 x28: ffffff8042dc9738 x27: 0000000000000001
+    x26: 0000000000000000 x25: ffffff8042dc9040 x24: ffffff8042dc9440
+    x23: ffffff80402a4620 x22: ffffff8042ef4bd0 x21: ffffff80405cb600
+    x20: 000000000008001b x19: ffffff8040b3b6e0 x18: 0000000000000000
+    x17: 0000000000000000 x16: 0000000000000000 x15: 696e6920746f6e20
+    x14: 7369203a29343263 x13: 205d303434542020 x12: 0000000000000000
+    x11: 0000000000000000 x10: 0000000000000000 x9 : 0000000000000000
+    x8 : 0000000000000000 x7 : 0000000000000000 x6 : 0000000000000000
+    x5 : 0000000000000000 x4 : 0000000000000000 x3 : 0000000000000000
+    x2 : 0000000000000000 x1 : 0000000000000000 x0 : 0000000000000000
+    Call trace:
+     kobject_put+0x120/0x150
+     cdev_put+0x20/0x3c
+     __fput+0x2c4/0x2d8
+     ____fput+0x1c/0x38
+     task_work_run+0x70/0xfc
+     do_exit+0x2a0/0x924
+     do_group_exit+0x34/0x90
+     get_signal+0x7fc/0x8c0
+     do_signal+0x128/0x13b4
+     do_notify_resume+0xdc/0x160
+     el0_svc+0xd4/0xf8
+     el0t_64_sync_handler+0x140/0x14c
+     el0t_64_sync+0x190/0x194
+    ---[ end trace 0000000000000000 ]---
+
+...followed by more symptoms of corruption, with similar stacks:
+
+    refcount_t: underflow; use-after-free.
+    kernel BUG at lib/list_debug.c:62!
+    Kernel panic - not syncing: Oops - BUG: Fatal exception
+
+This happens because pps_device_destruct() frees the pps_device with the
+embedded cdev immediately after calling cdev_del(), but, as the comment
+above cdev_del() notes, fops for previously opened cdevs are still
+callable even after cdev_del() returns. I think this bug has always
+been there: I can't explain why it suddenly started happening every time
+I reboot this particular board.
+
+In commit d953e0e837e6 ("pps: Fix a use-after free bug when
+unregistering a source."), George Spelvin suggested removing the
+embedded cdev. That seems like the simplest way to fix this, so I've
+implemented his suggestion, using __register_chrdev() with pps_idr
+becoming the source of truth for which minor corresponds to which
+device.
+
+But now that pps_idr defines userspace visibility instead of cdev_add(),
+we need to be sure the pps->dev refcount can't reach zero while
+userspace can still find it again. So, the idr_remove() call moves to
+pps_unregister_cdev(), and pps_idr now holds a reference to pps->dev.
+
+    pps_core: source serial1 got cdev (251:1)
+    <...>
+    pps pps1: removed
+    pps_core: unregistering pps1
+    pps_core: deallocating pps1
+
+Fixes: d953e0e837e6 ("pps: Fix a use-after free bug when unregistering a source.")
+Cc: stable@vger.kernel.org
+Signed-off-by: Calvin Owens <calvin@wbinvd.org>
+Reviewed-by: Michal Schmidt <mschmidt@redhat.com>
+Link: https://lore.kernel.org/r/a17975fd5ae99385791929e563f72564edbcf28f.1731383727.git.calvin@wbinvd.org
+Signed-off-by: Calvin Owens <calvin@wbinvd.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pps/clients/pps-gpio.c    |    4 -
+ drivers/pps/clients/pps-ktimer.c  |    4 -
+ drivers/pps/clients/pps-ldisc.c   |    6 -
+ drivers/pps/clients/pps_parport.c |    4 -
+ drivers/pps/kapi.c                |   10 +-
+ drivers/pps/kc.c                  |   10 +-
+ drivers/pps/pps.c                 |  127 +++++++++++++++++++-------------------
+ drivers/ptp/ptp_ocp.c             |    2 
+ include/linux/pps_kernel.h        |    3 
+ 9 files changed, 87 insertions(+), 83 deletions(-)
+
+--- a/drivers/pps/clients/pps-gpio.c
++++ b/drivers/pps/clients/pps-gpio.c
+@@ -214,8 +214,8 @@ static int pps_gpio_probe(struct platfor
+               return -EINVAL;
+       }
+-      dev_info(data->pps->dev, "Registered IRQ %d as PPS source\n",
+-               data->irq);
++      dev_dbg(&data->pps->dev, "Registered IRQ %d as PPS source\n",
++              data->irq);
+       return 0;
+ }
+--- a/drivers/pps/clients/pps-ktimer.c
++++ b/drivers/pps/clients/pps-ktimer.c
+@@ -56,7 +56,7 @@ static struct pps_source_info pps_ktimer
+ static void __exit pps_ktimer_exit(void)
+ {
+-      dev_info(pps->dev, "ktimer PPS source unregistered\n");
++      dev_dbg(&pps->dev, "ktimer PPS source unregistered\n");
+       del_timer_sync(&ktimer);
+       pps_unregister_source(pps);
+@@ -74,7 +74,7 @@ static int __init pps_ktimer_init(void)
+       timer_setup(&ktimer, pps_ktimer_event, 0);
+       mod_timer(&ktimer, jiffies + HZ);
+-      dev_info(pps->dev, "ktimer PPS source registered\n");
++      dev_dbg(&pps->dev, "ktimer PPS source registered\n");
+       return 0;
+ }
+--- a/drivers/pps/clients/pps-ldisc.c
++++ b/drivers/pps/clients/pps-ldisc.c
+@@ -32,7 +32,7 @@ static void pps_tty_dcd_change(struct tt
+       pps_event(pps, &ts, active ? PPS_CAPTUREASSERT :
+                       PPS_CAPTURECLEAR, NULL);
+-      dev_dbg(pps->dev, "PPS %s at %lu\n",
++      dev_dbg(&pps->dev, "PPS %s at %lu\n",
+                       active ? "assert" : "clear", jiffies);
+ }
+@@ -69,7 +69,7 @@ static int pps_tty_open(struct tty_struc
+               goto err_unregister;
+       }
+-      dev_info(pps->dev, "source \"%s\" added\n", info.path);
++      dev_dbg(&pps->dev, "source \"%s\" added\n", info.path);
+       return 0;
+@@ -89,7 +89,7 @@ static void pps_tty_close(struct tty_str
+       if (WARN_ON(!pps))
+               return;
+-      dev_info(pps->dev, "removed\n");
++      dev_info(&pps->dev, "removed\n");
+       pps_unregister_source(pps);
+ }
+--- a/drivers/pps/clients/pps_parport.c
++++ b/drivers/pps/clients/pps_parport.c
+@@ -81,7 +81,7 @@ static void parport_irq(void *handle)
+       /* check the signal (no signal means the pulse is lost this time) */
+       if (!signal_is_set(port)) {
+               local_irq_restore(flags);
+-              dev_err(dev->pps->dev, "lost the signal\n");
++              dev_err(&dev->pps->dev, "lost the signal\n");
+               goto out_assert;
+       }
+@@ -98,7 +98,7 @@ static void parport_irq(void *handle)
+       /* timeout */
+       dev->cw_err++;
+       if (dev->cw_err >= CLEAR_WAIT_MAX_ERRORS) {
+-              dev_err(dev->pps->dev, "disabled clear edge capture after %d"
++              dev_err(&dev->pps->dev, "disabled clear edge capture after %d"
+                               " timeouts\n", dev->cw_err);
+               dev->cw = 0;
+               dev->cw_err = 0;
+--- a/drivers/pps/kapi.c
++++ b/drivers/pps/kapi.c
+@@ -41,7 +41,7 @@ static void pps_add_offset(struct pps_kt
+ static void pps_echo_client_default(struct pps_device *pps, int event,
+               void *data)
+ {
+-      dev_info(pps->dev, "echo %s %s\n",
++      dev_info(&pps->dev, "echo %s %s\n",
+               event & PPS_CAPTUREASSERT ? "assert" : "",
+               event & PPS_CAPTURECLEAR ? "clear" : "");
+ }
+@@ -112,7 +112,7 @@ struct pps_device *pps_register_source(s
+               goto kfree_pps;
+       }
+-      dev_info(pps->dev, "new PPS source %s\n", info->name);
++      dev_dbg(&pps->dev, "new PPS source %s\n", info->name);
+       return pps;
+@@ -166,7 +166,7 @@ void pps_event(struct pps_device *pps, s
+       /* check event type */
+       BUG_ON((event & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR)) == 0);
+-      dev_dbg(pps->dev, "PPS event at %lld.%09ld\n",
++      dev_dbg(&pps->dev, "PPS event at %lld.%09ld\n",
+                       (s64)ts->ts_real.tv_sec, ts->ts_real.tv_nsec);
+       timespec_to_pps_ktime(&ts_real, ts->ts_real);
+@@ -188,7 +188,7 @@ void pps_event(struct pps_device *pps, s
+               /* Save the time stamp */
+               pps->assert_tu = ts_real;
+               pps->assert_sequence++;
+-              dev_dbg(pps->dev, "capture assert seq #%u\n",
++              dev_dbg(&pps->dev, "capture assert seq #%u\n",
+                       pps->assert_sequence);
+               captured = ~0;
+@@ -202,7 +202,7 @@ void pps_event(struct pps_device *pps, s
+               /* Save the time stamp */
+               pps->clear_tu = ts_real;
+               pps->clear_sequence++;
+-              dev_dbg(pps->dev, "capture clear seq #%u\n",
++              dev_dbg(&pps->dev, "capture clear seq #%u\n",
+                       pps->clear_sequence);
+               captured = ~0;
+--- a/drivers/pps/kc.c
++++ b/drivers/pps/kc.c
+@@ -43,11 +43,11 @@ int pps_kc_bind(struct pps_device *pps,
+                       pps_kc_hardpps_mode = 0;
+                       pps_kc_hardpps_dev = NULL;
+                       spin_unlock_irq(&pps_kc_hardpps_lock);
+-                      dev_info(pps->dev, "unbound kernel"
++                      dev_info(&pps->dev, "unbound kernel"
+                                       " consumer\n");
+               } else {
+                       spin_unlock_irq(&pps_kc_hardpps_lock);
+-                      dev_err(pps->dev, "selected kernel consumer"
++                      dev_err(&pps->dev, "selected kernel consumer"
+                                       " is not bound\n");
+                       return -EINVAL;
+               }
+@@ -57,11 +57,11 @@ int pps_kc_bind(struct pps_device *pps,
+                       pps_kc_hardpps_mode = bind_args->edge;
+                       pps_kc_hardpps_dev = pps;
+                       spin_unlock_irq(&pps_kc_hardpps_lock);
+-                      dev_info(pps->dev, "bound kernel consumer: "
++                      dev_info(&pps->dev, "bound kernel consumer: "
+                               "edge=0x%x\n", bind_args->edge);
+               } else {
+                       spin_unlock_irq(&pps_kc_hardpps_lock);
+-                      dev_err(pps->dev, "another kernel consumer"
++                      dev_err(&pps->dev, "another kernel consumer"
+                                       " is already bound\n");
+                       return -EINVAL;
+               }
+@@ -83,7 +83,7 @@ void pps_kc_remove(struct pps_device *pp
+               pps_kc_hardpps_mode = 0;
+               pps_kc_hardpps_dev = NULL;
+               spin_unlock_irq(&pps_kc_hardpps_lock);
+-              dev_info(pps->dev, "unbound kernel consumer"
++              dev_info(&pps->dev, "unbound kernel consumer"
+                               " on device removal\n");
+       } else
+               spin_unlock_irq(&pps_kc_hardpps_lock);
+--- a/drivers/pps/pps.c
++++ b/drivers/pps/pps.c
+@@ -25,7 +25,7 @@
+  * Local variables
+  */
+-static dev_t pps_devt;
++static int pps_major;
+ static struct class *pps_class;
+ static DEFINE_MUTEX(pps_idr_lock);
+@@ -62,7 +62,7 @@ static int pps_cdev_pps_fetch(struct pps
+       else {
+               unsigned long ticks;
+-              dev_dbg(pps->dev, "timeout %lld.%09d\n",
++              dev_dbg(&pps->dev, "timeout %lld.%09d\n",
+                               (long long) fdata->timeout.sec,
+                               fdata->timeout.nsec);
+               ticks = fdata->timeout.sec * HZ;
+@@ -80,7 +80,7 @@ static int pps_cdev_pps_fetch(struct pps
+       /* Check for pending signals */
+       if (err == -ERESTARTSYS) {
+-              dev_dbg(pps->dev, "pending signal caught\n");
++              dev_dbg(&pps->dev, "pending signal caught\n");
+               return -EINTR;
+       }
+@@ -98,7 +98,7 @@ static long pps_cdev_ioctl(struct file *
+       switch (cmd) {
+       case PPS_GETPARAMS:
+-              dev_dbg(pps->dev, "PPS_GETPARAMS\n");
++              dev_dbg(&pps->dev, "PPS_GETPARAMS\n");
+               spin_lock_irq(&pps->lock);
+@@ -114,7 +114,7 @@ static long pps_cdev_ioctl(struct file *
+               break;
+       case PPS_SETPARAMS:
+-              dev_dbg(pps->dev, "PPS_SETPARAMS\n");
++              dev_dbg(&pps->dev, "PPS_SETPARAMS\n");
+               /* Check the capabilities */
+               if (!capable(CAP_SYS_TIME))
+@@ -124,14 +124,14 @@ static long pps_cdev_ioctl(struct file *
+               if (err)
+                       return -EFAULT;
+               if (!(params.mode & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR))) {
+-                      dev_dbg(pps->dev, "capture mode unspecified (%x)\n",
++                      dev_dbg(&pps->dev, "capture mode unspecified (%x)\n",
+                                                               params.mode);
+                       return -EINVAL;
+               }
+               /* Check for supported capabilities */
+               if ((params.mode & ~pps->info.mode) != 0) {
+-                      dev_dbg(pps->dev, "unsupported capabilities (%x)\n",
++                      dev_dbg(&pps->dev, "unsupported capabilities (%x)\n",
+                                                               params.mode);
+                       return -EINVAL;
+               }
+@@ -144,7 +144,7 @@ static long pps_cdev_ioctl(struct file *
+               /* Restore the read only parameters */
+               if ((params.mode & (PPS_TSFMT_TSPEC | PPS_TSFMT_NTPFP)) == 0) {
+                       /* section 3.3 of RFC 2783 interpreted */
+-                      dev_dbg(pps->dev, "time format unspecified (%x)\n",
++                      dev_dbg(&pps->dev, "time format unspecified (%x)\n",
+                                                               params.mode);
+                       pps->params.mode |= PPS_TSFMT_TSPEC;
+               }
+@@ -165,7 +165,7 @@ static long pps_cdev_ioctl(struct file *
+               break;
+       case PPS_GETCAP:
+-              dev_dbg(pps->dev, "PPS_GETCAP\n");
++              dev_dbg(&pps->dev, "PPS_GETCAP\n");
+               err = put_user(pps->info.mode, iuarg);
+               if (err)
+@@ -176,7 +176,7 @@ static long pps_cdev_ioctl(struct file *
+       case PPS_FETCH: {
+               struct pps_fdata fdata;
+-              dev_dbg(pps->dev, "PPS_FETCH\n");
++              dev_dbg(&pps->dev, "PPS_FETCH\n");
+               err = copy_from_user(&fdata, uarg, sizeof(struct pps_fdata));
+               if (err)
+@@ -206,7 +206,7 @@ static long pps_cdev_ioctl(struct file *
+       case PPS_KC_BIND: {
+               struct pps_bind_args bind_args;
+-              dev_dbg(pps->dev, "PPS_KC_BIND\n");
++              dev_dbg(&pps->dev, "PPS_KC_BIND\n");
+               /* Check the capabilities */
+               if (!capable(CAP_SYS_TIME))
+@@ -218,7 +218,7 @@ static long pps_cdev_ioctl(struct file *
+               /* Check for supported capabilities */
+               if ((bind_args.edge & ~pps->info.mode) != 0) {
+-                      dev_err(pps->dev, "unsupported capabilities (%x)\n",
++                      dev_err(&pps->dev, "unsupported capabilities (%x)\n",
+                                       bind_args.edge);
+                       return -EINVAL;
+               }
+@@ -227,7 +227,7 @@ static long pps_cdev_ioctl(struct file *
+               if (bind_args.tsformat != PPS_TSFMT_TSPEC ||
+                               (bind_args.edge & ~PPS_CAPTUREBOTH) != 0 ||
+                               bind_args.consumer != PPS_KC_HARDPPS) {
+-                      dev_err(pps->dev, "invalid kernel consumer bind"
++                      dev_err(&pps->dev, "invalid kernel consumer bind"
+                                       " parameters (%x)\n", bind_args.edge);
+                       return -EINVAL;
+               }
+@@ -259,7 +259,7 @@ static long pps_cdev_compat_ioctl(struct
+               struct pps_fdata fdata;
+               int err;
+-              dev_dbg(pps->dev, "PPS_FETCH\n");
++              dev_dbg(&pps->dev, "PPS_FETCH\n");
+               err = copy_from_user(&compat, uarg, sizeof(struct pps_fdata_compat));
+               if (err)
+@@ -296,20 +296,36 @@ static long pps_cdev_compat_ioctl(struct
+ #define pps_cdev_compat_ioctl NULL
+ #endif
++static struct pps_device *pps_idr_get(unsigned long id)
++{
++      struct pps_device *pps;
++
++      mutex_lock(&pps_idr_lock);
++      pps = idr_find(&pps_idr, id);
++      if (pps)
++              get_device(&pps->dev);
++
++      mutex_unlock(&pps_idr_lock);
++      return pps;
++}
++
+ static int pps_cdev_open(struct inode *inode, struct file *file)
+ {
+-      struct pps_device *pps = container_of(inode->i_cdev,
+-                                              struct pps_device, cdev);
++      struct pps_device *pps = pps_idr_get(iminor(inode));
++
++      if (!pps)
++              return -ENODEV;
++
+       file->private_data = pps;
+-      kobject_get(&pps->dev->kobj);
+       return 0;
+ }
+ static int pps_cdev_release(struct inode *inode, struct file *file)
+ {
+-      struct pps_device *pps = container_of(inode->i_cdev,
+-                                              struct pps_device, cdev);
+-      kobject_put(&pps->dev->kobj);
++      struct pps_device *pps = file->private_data;
++
++      WARN_ON(pps->id != iminor(inode));
++      put_device(&pps->dev);
+       return 0;
+ }
+@@ -332,22 +348,13 @@ static void pps_device_destruct(struct d
+ {
+       struct pps_device *pps = dev_get_drvdata(dev);
+-      cdev_del(&pps->cdev);
+-
+-      /* Now we can release the ID for re-use */
+       pr_debug("deallocating pps%d\n", pps->id);
+-      mutex_lock(&pps_idr_lock);
+-      idr_remove(&pps_idr, pps->id);
+-      mutex_unlock(&pps_idr_lock);
+-
+-      kfree(dev);
+       kfree(pps);
+ }
+ int pps_register_cdev(struct pps_device *pps)
+ {
+       int err;
+-      dev_t devt;
+       mutex_lock(&pps_idr_lock);
+       /*
+@@ -364,40 +371,29 @@ int pps_register_cdev(struct pps_device
+               goto out_unlock;
+       }
+       pps->id = err;
+-      mutex_unlock(&pps_idr_lock);
+-
+-      devt = MKDEV(MAJOR(pps_devt), pps->id);
+-
+-      cdev_init(&pps->cdev, &pps_cdev_fops);
+-      pps->cdev.owner = pps->info.owner;
+-      err = cdev_add(&pps->cdev, devt, 1);
+-      if (err) {
+-              pr_err("%s: failed to add char device %d:%d\n",
+-                              pps->info.name, MAJOR(pps_devt), pps->id);
++      pps->dev.class = pps_class;
++      pps->dev.parent = pps->info.dev;
++      pps->dev.devt = MKDEV(pps_major, pps->id);
++      dev_set_drvdata(&pps->dev, pps);
++      dev_set_name(&pps->dev, "pps%d", pps->id);
++      err = device_register(&pps->dev);
++      if (err)
+               goto free_idr;
+-      }
+-      pps->dev = device_create(pps_class, pps->info.dev, devt, pps,
+-                                                      "pps%d", pps->id);
+-      if (IS_ERR(pps->dev)) {
+-              err = PTR_ERR(pps->dev);
+-              goto del_cdev;
+-      }
+       /* Override the release function with our own */
+-      pps->dev->release = pps_device_destruct;
++      pps->dev.release = pps_device_destruct;
+-      pr_debug("source %s got cdev (%d:%d)\n", pps->info.name,
+-                      MAJOR(pps_devt), pps->id);
++      pr_debug("source %s got cdev (%d:%d)\n", pps->info.name, pps_major,
++               pps->id);
++      get_device(&pps->dev);
++      mutex_unlock(&pps_idr_lock);
+       return 0;
+-del_cdev:
+-      cdev_del(&pps->cdev);
+-
+ free_idr:
+-      mutex_lock(&pps_idr_lock);
+       idr_remove(&pps_idr, pps->id);
++      put_device(&pps->dev);
+ out_unlock:
+       mutex_unlock(&pps_idr_lock);
+       return err;
+@@ -407,7 +403,13 @@ void pps_unregister_cdev(struct pps_devi
+ {
+       pr_debug("unregistering pps%d\n", pps->id);
+       pps->lookup_cookie = NULL;
+-      device_destroy(pps_class, pps->dev->devt);
++      device_destroy(pps_class, pps->dev.devt);
++
++      /* Now we can release the ID for re-use */
++      mutex_lock(&pps_idr_lock);
++      idr_remove(&pps_idr, pps->id);
++      put_device(&pps->dev);
++      mutex_unlock(&pps_idr_lock);
+ }
+ /*
+@@ -427,6 +429,11 @@ void pps_unregister_cdev(struct pps_devi
+  * so that it will not be used again, even if the pps device cannot
+  * be removed from the idr due to pending references holding the minor
+  * number in use.
++ *
++ * Since pps_idr holds a reference to the device, the returned
++ * pps_device is guaranteed to be valid until pps_unregister_cdev() is
++ * called on it. But after calling pps_unregister_cdev(), it may be
++ * freed at any time.
+  */
+ struct pps_device *pps_lookup_dev(void const *cookie)
+ {
+@@ -449,13 +456,11 @@ EXPORT_SYMBOL(pps_lookup_dev);
+ static void __exit pps_exit(void)
+ {
+       class_destroy(pps_class);
+-      unregister_chrdev_region(pps_devt, PPS_MAX_SOURCES);
++      __unregister_chrdev(pps_major, 0, PPS_MAX_SOURCES, "pps");
+ }
+ static int __init pps_init(void)
+ {
+-      int err;
+-
+       pps_class = class_create(THIS_MODULE, "pps");
+       if (IS_ERR(pps_class)) {
+               pr_err("failed to allocate class\n");
+@@ -463,8 +468,9 @@ static int __init pps_init(void)
+       }
+       pps_class->dev_groups = pps_groups;
+-      err = alloc_chrdev_region(&pps_devt, 0, PPS_MAX_SOURCES, "pps");
+-      if (err < 0) {
++      pps_major = __register_chrdev(0, 0, PPS_MAX_SOURCES, "pps",
++                                    &pps_cdev_fops);
++      if (pps_major < 0) {
+               pr_err("failed to allocate char device region\n");
+               goto remove_class;
+       }
+@@ -477,8 +483,7 @@ static int __init pps_init(void)
+ remove_class:
+       class_destroy(pps_class);
+-
+-      return err;
++      return pps_major;
+ }
+ subsys_initcall(pps_init);
+--- a/drivers/ptp/ptp_ocp.c
++++ b/drivers/ptp/ptp_ocp.c
+@@ -3589,7 +3589,7 @@ ptp_ocp_complete(struct ptp_ocp *bp)
+       pps = pps_lookup_dev(bp->ptp);
+       if (pps)
+-              ptp_ocp_symlink(bp, pps->dev, "pps");
++              ptp_ocp_symlink(bp, &pps->dev, "pps");
+       ptp_ocp_debugfs_add_device(bp);
+--- a/include/linux/pps_kernel.h
++++ b/include/linux/pps_kernel.h
+@@ -56,8 +56,7 @@ struct pps_device {
+       unsigned int id;                        /* PPS source unique ID */
+       void const *lookup_cookie;              /* For pps_lookup_dev() only */
+-      struct cdev cdev;
+-      struct device *dev;
++      struct device dev;
+       struct fasync_struct *async_queue;      /* fasync method */
+       spinlock_t lock;
+ };
diff --git a/queue-6.1/revert-btrfs-avoid-monopolizing-a-core-when-activating-a-swap-file.patch b/queue-6.1/revert-btrfs-avoid-monopolizing-a-core-when-activating-a-swap-file.patch
new file mode 100644 (file)
index 0000000..646fce4
--- /dev/null
@@ -0,0 +1,36 @@
+From stable+bounces-114131-greg=kroah.com@vger.kernel.org Thu Feb  6 17:21:32 2025
+From: Koichiro Den <koichiro.den@canonical.com>
+Date: Fri,  7 Feb 2025 01:20:54 +0900
+Subject: Revert "btrfs: avoid monopolizing a core when activating a swap file"
+To: gregkh@linuxfoundation.org, stable@vger.kernel.org
+Cc: wqu@suse.com, fdmanana@suse.com, dsterba@suse.com
+Message-ID: <20250206162055.1387169-1-koichiro.den@canonical.com>
+
+From: Koichiro Den <koichiro.den@canonical.com>
+
+This reverts commit bb8e287f596b62fac18ed84cc03a9f1752f6b3b8.
+
+The backport for linux-6.1.y, commit bb8e287f596b ("btrfs: avoid
+monopolizing a core when activating a swap file"), inserted
+cond_resched() in the wrong location.
+
+Revert it now; a subsequent commit will re-backport the original patch.
+
+Fixes: bb8e287f596b ("btrfs: avoid monopolizing a core when activating a swap file") # linux-6.1.y
+Signed-off-by: Koichiro Den <koichiro.den@canonical.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/btrfs/inode.c |    2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -7387,8 +7387,6 @@ noinline int can_nocow_extent(struct ino
+                       ret = -EAGAIN;
+                       goto out;
+               }
+-
+-              cond_resched();
+       }
+       if (orig_start)
index e321951ab04db67412aff2193543714e4327f829..bf9c434b34a54ec84ef85cab8d94bf9a47f090a4 100644 (file)
@@ -279,7 +279,6 @@ lockdep-fix-upper-limit-for-lockdep_-_bits-configs.patch
 x86-amd_nb-restrict-init-function-to-amd-based-syste.patch
 drm-virtio-new-fence-for-every-plane-update.patch
 printk-fix-signed-integer-overflow-when-defining-log.patch
-drm-sti-hdmi-use-eld_mutex-to-protect-access-to-conn.patch
 drm-amd-display-fix-mode-cutoff-in-dsc-passthrough-t.patch
 drm-bridge-it6505-change-definition-max_hdcp_down_st.patch
 drm-bridge-it6505-fix-hdcp-bstatus-check.patch
@@ -452,3 +451,14 @@ io_uring-rw-commit-provided-buffer-state-on-async.patch
 mips-ftrace-declare-ftrace_get_parent_ra_addr-as-static.patch
 net-ncsi-use-dev_set_mac_address-for-get-mc-mac-address-handling.patch
 gpio-xilinx-remove-excess-kernel-doc.patch
+ocfs2-check-dir-i_size-in-ocfs2_find_entry.patch
+ext4-filesystems-without-casefold-feature-cannot-be-mounted-with-siphash.patch
+cachefiles-fix-null-pointer-dereference-in-object-file.patch
+mptcp-pm-only-set-fullmesh-for-subflow-endp.patch
+mptcp-prevent-excessive-coalescing-on-receive.patch
+tty-xilinx_uartps-split-sysrq-handling.patch
+maple_tree-fix-static-analyser-cppcheck-issue.patch
+maple_tree-simplify-split-calculation.patch
+pps-fix-a-use-after-free.patch
+revert-btrfs-avoid-monopolizing-a-core-when-activating-a-swap-file.patch
+btrfs-avoid-monopolizing-a-core-when-activating-a-swap-file.patch
diff --git a/queue-6.1/tty-xilinx_uartps-split-sysrq-handling.patch b/queue-6.1/tty-xilinx_uartps-split-sysrq-handling.patch
new file mode 100644 (file)
index 0000000..2349dae
--- /dev/null
@@ -0,0 +1,77 @@
+From b06f388994500297bb91be60ffaf6825ecfd2afe Mon Sep 17 00:00:00 2001
+From: Sean Anderson <sean.anderson@linux.dev>
+Date: Fri, 10 Jan 2025 16:38:22 -0500
+Subject: tty: xilinx_uartps: split sysrq handling
+
+From: Sean Anderson <sean.anderson@linux.dev>
+
+commit b06f388994500297bb91be60ffaf6825ecfd2afe upstream.
+
+lockdep detects the following circular locking dependency:
+
+CPU 0                      CPU 1
+========================== ============================
+cdns_uart_isr()            printk()
+  uart_port_lock(port)       console_lock()
+                            cdns_uart_console_write()
+                               if (!port->sysrq)
+                                 uart_port_lock(port)
+  uart_handle_break()
+    port->sysrq = ...
+  uart_handle_sysrq_char()
+    printk()
+      console_lock()
+
+The fixed commit attempts to avoid this situation by only taking the
+port lock in cdns_uart_console_write if port->sysrq unset. However, if
+(as shown above) cdns_uart_console_write runs before port->sysrq is set,
+then it will try to take the port lock anyway. This may result in a
+deadlock.
+
+Fix this by splitting sysrq handling into two parts. We use the prepare
+helper under the port lock and defer handling until we release the lock.
+
+Fixes: 74ea66d4ca06 ("tty: xuartps: Improve sysrq handling")
+Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
+Cc: stable@vger.kernel.org # c980248179d: serial: xilinx_uartps: Use port lock wrappers
+Acked-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20250110213822.2107462-1-sean.anderson@linux.dev
+Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/tty/serial/xilinx_uartps.c |   10 ++++------
+ 1 file changed, 4 insertions(+), 6 deletions(-)
+
+--- a/drivers/tty/serial/xilinx_uartps.c
++++ b/drivers/tty/serial/xilinx_uartps.c
+@@ -268,7 +268,7 @@ static void cdns_uart_handle_rx(void *de
+                               continue;
+               }
+-              if (uart_handle_sysrq_char(port, data))
++              if (uart_prepare_sysrq_char(port, data))
+                       continue;
+               if (is_rxbs_support) {
+@@ -371,7 +371,7 @@ static irqreturn_t cdns_uart_isr(int irq
+           !(readl(port->membase + CDNS_UART_CR) & CDNS_UART_CR_RX_DIS))
+               cdns_uart_handle_rx(dev_id, isrstatus);
+-      spin_unlock(&port->lock);
++      uart_unlock_and_check_sysrq(port);
+       return IRQ_HANDLED;
+ }
+@@ -1231,10 +1231,8 @@ static void cdns_uart_console_write(stru
+       unsigned int imr, ctrl;
+       int locked = 1;
+-      if (port->sysrq)
+-              locked = 0;
+-      else if (oops_in_progress)
+-              locked = spin_trylock_irqsave(&port->lock, flags);
++      if (oops_in_progress)
++              locked = uart_port_trylock_irqsave(port, &flags);
+       else
+               spin_lock_irqsave(&port->lock, flags);