]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 9 Jul 2026 14:43:13 +0000 (16:43 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 9 Jul 2026 14:43:13 +0000 (16:43 +0200)
added patches:
apparmor-fix-use-after-free-in-rawdata-dedup-loop.patch
apparmor-mediate-the-implicit-connect-of-tcp-fast-open-sendmsg.patch
f2fs-adjust-zone-capacity-when-considering-valid-block-count.patch
f2fs-bound-i_inline_xattr_size-for-non-inline-xattr-inodes.patch
f2fs-fix-listxattr-handling-of-corrupted-xattr-entries.patch
f2fs-fix-potential-deadlock-in-f2fs_balance_fs.patch
f2fs-fix-to-round-down-start-offset-of-fallocate-for-pin-file.patch
f2fs-validate-orphan-inode-entry-count.patch
fbdev-fbcon-fix-out-of-bounds-read-in-err_out-of-fbcon_do_set_font.patch
hdlc_ppp-sync-per-proto-timers-before-freeing-hdlc-state.patch
i2c-core-fix-adapter-debugfs-creation.patch
i2c-core-fix-adapter-registration-race.patch
i2c-core-fix-hang-on-adapter-registration-failure.patch
i2c-core-fix-irq-domain-leak-on-adapter-registration-failure.patch
i2c-core-fix-null-deref-on-adapter-registration-failure.patch
net-ip_gre-require-cap_net_admin-in-the-device-netns-for-changelink.patch
net-skmsg-preserve-sg.copy-across-sg-transforms.patch
nfsv4-flexfiles-reject-zero-filehandle-version-count.patch
skmsg-convert-struct-sk_msg_sg-copy-to-a-bitmap.patch

20 files changed:
queue-5.10/apparmor-fix-use-after-free-in-rawdata-dedup-loop.patch [new file with mode: 0644]
queue-5.10/apparmor-mediate-the-implicit-connect-of-tcp-fast-open-sendmsg.patch [new file with mode: 0644]
queue-5.10/f2fs-adjust-zone-capacity-when-considering-valid-block-count.patch [new file with mode: 0644]
queue-5.10/f2fs-bound-i_inline_xattr_size-for-non-inline-xattr-inodes.patch [new file with mode: 0644]
queue-5.10/f2fs-fix-listxattr-handling-of-corrupted-xattr-entries.patch [new file with mode: 0644]
queue-5.10/f2fs-fix-potential-deadlock-in-f2fs_balance_fs.patch [new file with mode: 0644]
queue-5.10/f2fs-fix-to-round-down-start-offset-of-fallocate-for-pin-file.patch [new file with mode: 0644]
queue-5.10/f2fs-validate-orphan-inode-entry-count.patch [new file with mode: 0644]
queue-5.10/fbdev-fbcon-fix-out-of-bounds-read-in-err_out-of-fbcon_do_set_font.patch [new file with mode: 0644]
queue-5.10/hdlc_ppp-sync-per-proto-timers-before-freeing-hdlc-state.patch [new file with mode: 0644]
queue-5.10/i2c-core-fix-adapter-debugfs-creation.patch [new file with mode: 0644]
queue-5.10/i2c-core-fix-adapter-registration-race.patch [new file with mode: 0644]
queue-5.10/i2c-core-fix-hang-on-adapter-registration-failure.patch [new file with mode: 0644]
queue-5.10/i2c-core-fix-irq-domain-leak-on-adapter-registration-failure.patch [new file with mode: 0644]
queue-5.10/i2c-core-fix-null-deref-on-adapter-registration-failure.patch [new file with mode: 0644]
queue-5.10/net-ip_gre-require-cap_net_admin-in-the-device-netns-for-changelink.patch [new file with mode: 0644]
queue-5.10/net-skmsg-preserve-sg.copy-across-sg-transforms.patch [new file with mode: 0644]
queue-5.10/nfsv4-flexfiles-reject-zero-filehandle-version-count.patch [new file with mode: 0644]
queue-5.10/series
queue-5.10/skmsg-convert-struct-sk_msg_sg-copy-to-a-bitmap.patch [new file with mode: 0644]

diff --git a/queue-5.10/apparmor-fix-use-after-free-in-rawdata-dedup-loop.patch b/queue-5.10/apparmor-fix-use-after-free-in-rawdata-dedup-loop.patch
new file mode 100644 (file)
index 0000000..f89bbe9
--- /dev/null
@@ -0,0 +1,111 @@
+From stable+bounces-270557-greg=kroah.com@vger.kernel.org Thu Jul  2 17:30:47 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu,  2 Jul 2026 11:26:28 -0400
+Subject: apparmor: fix use-after-free in rawdata dedup loop
+To: stable@vger.kernel.org
+Cc: Ruslan Valiyev <linuxoid@gmail.com>, Colin Ian King <colin.i.king@gmail.com>, John Johansen <john.johansen@canonical.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260702152628.3530333-1-sashal@kernel.org>
+
+From: Ruslan Valiyev <linuxoid@gmail.com>
+
+[ Upstream commit 6f060496d03e4dc560a40f73770bd08335cb7a27 ]
+
+aa_replace_profiles() walks ns->rawdata_list to dedup the incoming
+policy blob against entries already attached to existing profiles.
+Per the kernel-doc on struct aa_loaddata, list membership does not
+hold a reference: profiles hold pcount, and when the last pcount
+drops, do_ploaddata_rmfs() is queued on a workqueue that takes
+ns->lock and removes the entry. Between dropping the last pcount
+and the workqueue running, an entry remains on the list with
+pcount == 0.
+
+aa_get_profile_loaddata() is an unconditional kref_get() on
+pcount, so when the dedup loop hits such an entry, refcount
+hardening reports
+
+  refcount_t: addition on 0; use-after-free.
+
+inside aa_replace_profiles(), and the poisoned counter then
+trips "saturated" and "underflow" warnings on the subsequent
+uses of the same loaddata.
+
+Before commit a0b7091c4de4 ("apparmor: fix race on rawdata
+dereference") the dedup path used a get_unless_zero-style helper
+on a single counter, so the existing "if (tmp)" guard was
+meaningful. The split-refcount refactor introduced
+aa_get_profile_loaddata(), which has plain kref_get() semantics,
+and the guard quietly became a no-op.
+
+Introduce aa_get_profile_loaddata_not0(), matching the existing
+_not0 convention used by aa_get_profile_not0(), and use it for
+the rawdata_list dedup lookup so dying entries are skipped.
+
+Reproduced on x86_64 with v7.1-rc5 in QEMU+KVM running Ubuntu
+24.04 + stress-ng 0.17.06:
+
+  stress-ng --apparmor 1 --klog-check --timeout 60s
+
+Without this patch the three refcount_t warnings fire within a
+few seconds. With it the same 60 s run is clean. Coverage is a
+smoke-test only; a longer soak with CONFIG_KASAN, CONFIG_KCSAN
+and CONFIG_PROVE_LOCKING would be welcome from anyone with the
+cycles.
+
+Fixes: a0b7091c4de4 ("apparmor: fix race on rawdata dereference")
+Reported-by: Colin Ian King <colin.i.king@gmail.com>
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=221513
+Cc: stable@vger.kernel.org
+Signed-off-by: Ruslan Valiyev <linuxoid@gmail.com>
+Signed-off-by: John Johansen <john.johansen@canonical.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ security/apparmor/include/policy_unpack.h |   19 +++++++++++++++++++
+ security/apparmor/policy.c                |    8 ++++++--
+ 2 files changed, 25 insertions(+), 2 deletions(-)
+
+--- a/security/apparmor/include/policy_unpack.h
++++ b/security/apparmor/include/policy_unpack.h
+@@ -122,6 +122,25 @@ aa_get_profile_loaddata(struct aa_loadda
+       return data;
+ }
++/**
++ * aa_get_profile_loaddata_not0 - get a profile reference count if not zero
++ * @data: reference to get a count on
++ *
++ * Like aa_get_profile_loaddata(), but safe to call on an entry that may
++ * be on a list (e.g. ns->rawdata_list) where the last pcount has already
++ * dropped and the deferred cleanup has not yet run.
++ *
++ * Returns: pointer to reference, or %NULL if @data is NULL or its
++ *          profile refcount has already reached zero.
++ */
++static inline struct aa_loaddata *
++aa_get_profile_loaddata_not0(struct aa_loaddata *data)
++{
++      if (data && kref_get_unless_zero(&data->pcount))
++              return data;
++      return NULL;
++}
++
+ void __aa_loaddata_update(struct aa_loaddata *data, long revision);
+ bool aa_rawdata_eq(struct aa_loaddata *l, struct aa_loaddata *r);
+ void aa_loaddata_kref(struct kref *kref);
+--- a/security/apparmor/policy.c
++++ b/security/apparmor/policy.c
+@@ -976,8 +976,12 @@ ssize_t aa_replace_profiles(struct aa_ns
+               if (aa_rawdata_eq(rawdata_ent, udata)) {
+                       struct aa_loaddata *tmp;
+-                      tmp = aa_get_profile_loaddata(rawdata_ent);
+-                      /* check we didn't fail the race */
++                      /*
++                       * Entries remain on rawdata_list with
++                       * pcount == 0 until do_ploaddata_rmfs()
++                       * runs; only take a live profile ref.
++                       */
++                      tmp = aa_get_profile_loaddata_not0(rawdata_ent);
+                       if (tmp) {
+                               aa_put_profile_loaddata(udata);
+                               udata = tmp;
diff --git a/queue-5.10/apparmor-mediate-the-implicit-connect-of-tcp-fast-open-sendmsg.patch b/queue-5.10/apparmor-mediate-the-implicit-connect-of-tcp-fast-open-sendmsg.patch
new file mode 100644 (file)
index 0000000..863148c
--- /dev/null
@@ -0,0 +1,62 @@
+From stable+bounces-271597-greg=kroah.com@vger.kernel.org Fri Jul  3 03:29:49 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu,  2 Jul 2026 21:29:42 -0400
+Subject: apparmor: mediate the implicit connect of TCP fast open sendmsg
+To: stable@vger.kernel.org
+Cc: Bryam Vargas <hexlabsecurity@proton.me>, John Johansen <john.johansen@canonical.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260703012942.3803836-1-sashal@kernel.org>
+
+From: Bryam Vargas <hexlabsecurity@proton.me>
+
+[ Upstream commit 4d587cd8a72155089a627130bbd4716ec0856e21 ]
+
+sendmsg()/sendto() with MSG_FASTOPEN is a combination of connect(2) and
+write(2): it opens the connection in the SYN. apparmor_socket_sendmsg()
+only checks AA_MAY_SEND, so a profile that grants send but denies connect
+lets a confined task open an outbound TCP/MPTCP connection that connect(2)
+would have refused, bypassing connect mediation.
+
+Mediate the implicit connect when MSG_FASTOPEN is set and a destination
+is supplied. Add it to apparmor_socket_sendmsg() (not the shared
+aa_sock_msg_perm() helper, which recvmsg also uses) and call aa_sk_perm()
+directly, mirroring the selinux and tomoyo fixes. sk_is_tcp() does not
+cover MPTCP fast open, so the SOCK_STREAM/IPPROTO_MPTCP arm is explicit.
+
+Fixes: cf60af03ca4e ("net-tcp: Fast Open client - sendmsg(MSG_FASTOPEN)")
+Cc: stable@vger.kernel.org
+Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me>
+Signed-off-by: John Johansen <john.johansen@canonical.com>
+[ inlined absent sk_is_tcp()/sk_is_inet() helpers into the equivalent family/type/protocol checks ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ security/apparmor/lsm.c |   18 +++++++++++++++++-
+ 1 file changed, 17 insertions(+), 1 deletion(-)
+
+--- a/security/apparmor/lsm.c
++++ b/security/apparmor/lsm.c
+@@ -951,7 +951,23 @@ static int aa_sock_msg_perm(const char *
+ static int apparmor_socket_sendmsg(struct socket *sock,
+                                  struct msghdr *msg, int size)
+ {
+-      return aa_sock_msg_perm(OP_SENDMSG, AA_MAY_SEND, sock, msg, size);
++      int error = aa_sock_msg_perm(OP_SENDMSG, AA_MAY_SEND, sock, msg, size);
++
++      if (error)
++              return error;
++
++      /* TCP fast open carries connect() semantics in sendmsg(); mediate
++       * the implicit connect so it cannot bypass the connect permission.
++       */
++      if ((msg->msg_flags & MSG_FASTOPEN) && msg->msg_name &&
++          (sock->sk->sk_family == AF_INET ||
++           sock->sk->sk_family == AF_INET6) &&
++          sock->sk->sk_type == SOCK_STREAM &&
++          (sock->sk->sk_protocol == IPPROTO_TCP ||
++           sock->sk->sk_protocol == IPPROTO_MPTCP))
++              error = aa_sk_perm(OP_CONNECT, AA_MAY_CONNECT, sock->sk);
++
++      return error;
+ }
+ /**
diff --git a/queue-5.10/f2fs-adjust-zone-capacity-when-considering-valid-block-count.patch b/queue-5.10/f2fs-adjust-zone-capacity-when-considering-valid-block-count.patch
new file mode 100644 (file)
index 0000000..55b8c80
--- /dev/null
@@ -0,0 +1,142 @@
+From stable+bounces-271779-greg=kroah.com@vger.kernel.org Fri Jul  3 15:39:29 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri,  3 Jul 2026 09:31:00 -0400
+Subject: f2fs: adjust zone capacity when considering valid block count
+To: stable@vger.kernel.org
+Cc: Jaegeuk Kim <jaegeuk@kernel.org>, Chao Yu <chao@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260703133101.4123681-1-sashal@kernel.org>
+
+From: Jaegeuk Kim <jaegeuk@kernel.org>
+
+[ Upstream commit 074b5ea2900ea8e40f8e7a3fd37e0a55ad3d5874 ]
+
+This patch fixes counting unusable blocks set by zone capacity when
+checking the valid block count in a section.
+
+Reviewed-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Stable-dep-of: 4275b59673eb ("f2fs: fix to round down start offset of fallocate for pin file")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/debug.c   |    2 +-
+ fs/f2fs/file.c    |    6 +++---
+ fs/f2fs/gc.c      |    4 ++--
+ fs/f2fs/segment.c |    7 +++----
+ fs/f2fs/segment.h |    8 ++++----
+ 5 files changed, 13 insertions(+), 14 deletions(-)
+
+--- a/fs/f2fs/debug.c
++++ b/fs/f2fs/debug.c
+@@ -39,7 +39,7 @@ void f2fs_update_sit_info(struct f2fs_sb
+       bimodal = 0;
+       total_vblocks = 0;
+-      blks_per_sec = BLKS_PER_SEC(sbi);
++      blks_per_sec = CAP_BLKS_PER_SEC(sbi);
+       hblks_per_sec = blks_per_sec / 2;
+       for (segno = 0; segno < MAIN_SEGS(sbi); segno += sbi->segs_per_sec) {
+               vblocks = get_valid_blocks(sbi, segno, true);
+--- a/fs/f2fs/file.c
++++ b/fs/f2fs/file.c
+@@ -1681,7 +1681,7 @@ static int expand_inode_data(struct inod
+               return 0;
+       if (f2fs_is_pinned_file(inode)) {
+-              block_t sec_blks = BLKS_PER_SEC(sbi);
++              block_t sec_blks = CAP_BLKS_PER_SEC(sbi);
+               block_t sec_len = roundup(map.m_len, sec_blks);
+               map.m_len = sec_blks;
+@@ -2595,7 +2595,7 @@ do_more:
+                       ret = -EAGAIN;
+               goto out;
+       }
+-      range->start += BLKS_PER_SEC(sbi);
++      range->start += CAP_BLKS_PER_SEC(sbi);
+       if (range->start <= end)
+               goto do_more;
+ out:
+@@ -2717,7 +2717,7 @@ static int f2fs_defragment_range(struct
+               goto out;
+       }
+-      sec_num = DIV_ROUND_UP(total, BLKS_PER_SEC(sbi));
++      sec_num = DIV_ROUND_UP(total, CAP_BLKS_PER_SEC(sbi));
+       /*
+        * make sure there are enough free section for LFS allocation, this can
+--- a/fs/f2fs/gc.c
++++ b/fs/f2fs/gc.c
+@@ -441,7 +441,7 @@ static void atgc_lookup_victim(struct f2
+       unsigned long long age, u, accu;
+       unsigned long long max_mtime = sit_i->dirty_max_mtime;
+       unsigned long long min_mtime = sit_i->dirty_min_mtime;
+-      unsigned int sec_blocks = BLKS_PER_SEC(sbi);
++      unsigned int sec_blocks = CAP_BLKS_PER_SEC(sbi);
+       unsigned int vblocks;
+       unsigned int dirty_threshold = max(am->max_candidate_count,
+                                       am->candidate_ratio *
+@@ -1421,7 +1421,7 @@ next_step:
+                */
+               if ((gc_type == BG_GC && has_not_enough_free_secs(sbi, 0, 0)) ||
+                       (!force_migrate && get_valid_blocks(sbi, segno, true) ==
+-                                                      BLKS_PER_SEC(sbi)))
++                                                      CAP_BLKS_PER_SEC(sbi)))
+                       return submitted;
+               if (check_valid_map(sbi, segno, off) == 0)
+--- a/fs/f2fs/segment.c
++++ b/fs/f2fs/segment.c
+@@ -820,7 +820,7 @@ static void __locate_dirty_segment(struc
+                               get_valid_blocks(sbi, segno, true);
+                       f2fs_bug_on(sbi, unlikely(!valid_blocks ||
+-                                      valid_blocks == BLKS_PER_SEC(sbi)));
++                                      valid_blocks == CAP_BLKS_PER_SEC(sbi)));
+                       if (!IS_CURSEC(sbi, secno))
+                               set_bit(secno, dirty_i->dirty_secmap);
+@@ -856,7 +856,7 @@ static void __remove_dirty_segment(struc
+                       unsigned int secno = GET_SEC_FROM_SEG(sbi, segno);
+                       if (!valid_blocks ||
+-                                      valid_blocks == BLKS_PER_SEC(sbi)) {
++                                      valid_blocks == CAP_BLKS_PER_SEC(sbi)) {
+                               clear_bit(secno, dirty_i->dirty_secmap);
+                               return;
+                       }
+@@ -4577,7 +4577,6 @@ static void init_dirty_segmap(struct f2f
+       struct free_segmap_info *free_i = FREE_I(sbi);
+       unsigned int segno = 0, offset = 0, secno;
+       block_t valid_blocks, usable_blks_in_seg;
+-      block_t blks_per_sec = BLKS_PER_SEC(sbi);
+       while (1) {
+               /* find dirty segment based on free segmap */
+@@ -4606,7 +4605,7 @@ static void init_dirty_segmap(struct f2f
+               valid_blocks = get_valid_blocks(sbi, segno, true);
+               secno = GET_SEC_FROM_SEG(sbi, segno);
+-              if (!valid_blocks || valid_blocks == blks_per_sec)
++              if (!valid_blocks || valid_blocks == CAP_BLKS_PER_SEC(sbi))
+                       continue;
+               if (IS_CURSEC(sbi, secno))
+                       continue;
+--- a/fs/f2fs/segment.h
++++ b/fs/f2fs/segment.h
+@@ -608,10 +608,10 @@ static inline bool has_not_enough_free_s
+                                       get_pages(sbi, F2FS_DIRTY_DENTS) +
+                                       get_pages(sbi, F2FS_DIRTY_IMETA);
+       unsigned int total_dent_blocks = get_pages(sbi, F2FS_DIRTY_DENTS);
+-      unsigned int node_secs = total_node_blocks / BLKS_PER_SEC(sbi);
+-      unsigned int dent_secs = total_dent_blocks / BLKS_PER_SEC(sbi);
+-      unsigned int node_blocks = total_node_blocks % BLKS_PER_SEC(sbi);
+-      unsigned int dent_blocks = total_dent_blocks % BLKS_PER_SEC(sbi);
++      unsigned int node_secs = total_node_blocks / CAP_BLKS_PER_SEC(sbi);
++      unsigned int dent_secs = total_dent_blocks / CAP_BLKS_PER_SEC(sbi);
++      unsigned int node_blocks = total_node_blocks % CAP_BLKS_PER_SEC(sbi);
++      unsigned int dent_blocks = total_dent_blocks % CAP_BLKS_PER_SEC(sbi);
+       unsigned int free, need_lower, need_upper;
+       if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING)))
diff --git a/queue-5.10/f2fs-bound-i_inline_xattr_size-for-non-inline-xattr-inodes.patch b/queue-5.10/f2fs-bound-i_inline_xattr_size-for-non-inline-xattr-inodes.patch
new file mode 100644 (file)
index 0000000..aa1cecd
--- /dev/null
@@ -0,0 +1,85 @@
+From stable+bounces-271857-greg=kroah.com@vger.kernel.org Fri Jul  3 20:50:25 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri,  3 Jul 2026 14:50:18 -0400
+Subject: f2fs: bound i_inline_xattr_size for non-inline-xattr inodes
+To: stable@vger.kernel.org
+Cc: Bryam Vargas <hexlabsecurity@proton.me>, Chao Yu <chao@kernel.org>, Jaegeuk Kim <jaegeuk@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260703185018.285454-1-sashal@kernel.org>
+
+From: Bryam Vargas <hexlabsecurity@proton.me>
+
+[ Upstream commit 378acf3cf19b6af6cba55e8dd1154c4e1504bae8 ]
+
+When the flexible_inline_xattr feature is enabled, do_read_inode() loads
+the on-disk i_inline_xattr_size unconditionally:
+
+       if (f2fs_sb_has_flexible_inline_xattr(sbi))
+               fi->i_inline_xattr_size = le16_to_cpu(ri->i_inline_xattr_size);
+
+but sanity_check_inode() only range-checks it when the inode also has the
+FI_INLINE_XATTR flag set.  An inode that carries an inline dentry or inline
+data but not FI_INLINE_XATTR -- the normal layout for an inline
+directory -- therefore keeps a fully attacker-controlled
+i_inline_xattr_size from a crafted image.
+
+get_inline_xattr_addrs() returns that value with no flag gating, so it
+feeds the inode geometry:
+
+       MAX_INLINE_DATA()  = 4 * (CUR_ADDRS_PER_INODE - i_inline_xattr_size - 1)
+       NR_INLINE_DENTRY() = MAX_INLINE_DATA() * BITS_PER_BYTE / (...)
+       addrs_per_page()   = CUR_ADDRS_PER_INODE - i_inline_xattr_size
+
+A large i_inline_xattr_size drives MAX_INLINE_DATA() and NR_INLINE_DENTRY()
+negative, so make_dentry_ptr_inline() sets d->max (int) to a negative
+value.  The inline directory walk then compares an unsigned long bit_pos
+against that negative d->max, which is promoted to a huge unsigned bound,
+and reads far past the inline area:
+
+       while (bit_pos < d->max)                /* fs/f2fs/dir.c */
+               ... test_bit_le(bit_pos, d->bitmap) / d->dentry[bit_pos] ...
+
+Mounting a crafted image and reading such a directory triggers an
+out-of-bounds read in f2fs_fill_dentries(); the same underflow also
+corrupts ADDRS_PER_INODE for regular files.
+
+Validate i_inline_xattr_size against MAX_INLINE_XATTR_SIZE whenever the
+flexible_inline_xattr feature is enabled -- i.e. whenever the value is
+loaded from disk and consumed -- and keep the lower MIN_INLINE_XATTR_SIZE
+bound gated on inodes that actually carry an inline xattr, so legitimate
+inodes with i_inline_xattr_size == 0 are still accepted.
+
+Cc: stable@vger.kernel.org
+Fixes: 6afc662e68b5 ("f2fs: support flexible inline xattr size")
+Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me>
+Reviewed-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/inode.c |   13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+--- a/fs/f2fs/inode.c
++++ b/fs/f2fs/inode.c
+@@ -254,14 +254,15 @@ static bool sanity_check_inode(struct in
+               return false;
+       }
+-      if (f2fs_has_extra_attr(inode) &&
+-              f2fs_sb_has_flexible_inline_xattr(sbi) &&
+-              f2fs_has_inline_xattr(inode) &&
+-              (!fi->i_inline_xattr_size ||
+-              fi->i_inline_xattr_size > MAX_INLINE_XATTR_SIZE)) {
++      if (f2fs_sb_has_flexible_inline_xattr(sbi) &&
++              (fi->i_inline_xattr_size > MAX_INLINE_XATTR_SIZE ||
++              (f2fs_has_inline_xattr(inode) &&
++              fi->i_inline_xattr_size <
++                      sizeof(struct f2fs_xattr_header) / sizeof(__le32)))) {
+               set_sbi_flag(sbi, SBI_NEED_FSCK);
+-              f2fs_warn(sbi, "%s: inode (ino=%lx) has corrupted i_inline_xattr_size: %d, max: %zu",
++              f2fs_warn(sbi, "%s: inode (ino=%lx) has corrupted i_inline_xattr_size: %d, min: %zu, max: %zu",
+                         __func__, inode->i_ino, fi->i_inline_xattr_size,
++                        sizeof(struct f2fs_xattr_header) / sizeof(__le32),
+                         MAX_INLINE_XATTR_SIZE);
+               return false;
+       }
diff --git a/queue-5.10/f2fs-fix-listxattr-handling-of-corrupted-xattr-entries.patch b/queue-5.10/f2fs-fix-listxattr-handling-of-corrupted-xattr-entries.patch
new file mode 100644 (file)
index 0000000..58b2503
--- /dev/null
@@ -0,0 +1,47 @@
+From stable+bounces-271947-greg=kroah.com@vger.kernel.org Sat Jul  4 13:54:59 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat,  4 Jul 2026 07:54:49 -0400
+Subject: f2fs: fix listxattr handling of corrupted xattr entries
+To: stable@vger.kernel.org
+Cc: Keshav Verma <iganschel@gmail.com>, stable@kernel.org, Chao Yu <chao@kernel.org>, Jaegeuk Kim <jaegeuk@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260704115449.629037-1-sashal@kernel.org>
+
+From: Keshav Verma <iganschel@gmail.com>
+
+[ Upstream commit 5ef5bc304f23c3fe255d4936472378dcb74d0e94 ]
+
+Validate the xattr entry before reading its fields in f2fs_listxattr().
+Return -EFSCORRUPTED when the entry is outside the valid xattr storage
+area instead of returning a successful partial result.
+
+Fixes: 688078e7f36c ("f2fs: fix to avoid memory leakage in f2fs_listxattr")
+Cc: stable@kernel.org
+Reviewed-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Keshav Verma <iganschel@gmail.com>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/xattr.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/fs/f2fs/xattr.c
++++ b/fs/f2fs/xattr.c
+@@ -575,8 +575,7 @@ ssize_t f2fs_listxattr(struct dentry *de
+       last_base_addr = (void *)base_addr + XATTR_SIZE(inode);
+       list_for_each_xattr(entry, base_addr) {
+-              const struct xattr_handler *handler =
+-                      f2fs_xattr_handler(entry->e_name_index);
++              const struct xattr_handler *handler;
+               const char *prefix;
+               size_t prefix_len;
+               size_t size;
+@@ -590,6 +589,7 @@ ssize_t f2fs_listxattr(struct dentry *de
+                       goto cleanup;
+               }
++              handler = f2fs_xattr_handler(entry->e_name_index);
+               if (!handler || (handler->list && !handler->list(dentry)))
+                       continue;
diff --git a/queue-5.10/f2fs-fix-potential-deadlock-in-f2fs_balance_fs.patch b/queue-5.10/f2fs-fix-potential-deadlock-in-f2fs_balance_fs.patch
new file mode 100644 (file)
index 0000000..72502f6
--- /dev/null
@@ -0,0 +1,252 @@
+From stable+bounces-271944-greg=kroah.com@vger.kernel.org Sat Jul  4 13:49:23 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat,  4 Jul 2026 07:49:15 -0400
+Subject: f2fs: fix potential deadlock in f2fs_balance_fs()
+To: stable@vger.kernel.org
+Cc: Ruipeng Qi <ruipengqi3@gmail.com>, Chao Yu <chao@kernel.org>, Jaegeuk Kim <jaegeuk@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260704114915.620065-1-sashal@kernel.org>
+
+From: Ruipeng Qi <ruipengqi3@gmail.com>
+
+[ Upstream commit dd3114870771562036fdcf5abe813956f36d224d ]
+
+When the f2fs filesystem space is nearly exhausted, we encounter deadlock
+issues as below:
+
+INFO: task A:1890 blocked for more than 120 seconds.
+      Tainted: G           O       6.12.41-g3fe07ddf05ab #1
+"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
+task:A    state:D stack:0     pid:1890  tgid:1626  ppid:1153   flags:0x00000204
+Call trace:
+ __switch_to+0xf4/0x158
+ __schedule+0x27c/0x908
+ schedule+0x3c/0x118
+ io_schedule+0x44/0x68
+ folio_wait_bit_common+0x174/0x370
+ folio_wait_bit+0x20/0x38
+ folio_wait_writeback+0x54/0xc8
+ truncate_inode_partial_folio+0x70/0x1e0
+ truncate_inode_pages_range+0x1b0/0x450
+ truncate_pagecache+0x54/0x88
+ f2fs_file_write_iter+0x3e8/0xb80
+ do_iter_readv_writev+0xf0/0x1e0
+ vfs_writev+0x138/0x2c8
+ do_writev+0x88/0x130
+ __arm64_sys_writev+0x28/0x40
+ invoke_syscall+0x50/0x120
+ el0_svc_common.constprop.0+0xc8/0xf0
+ do_el0_svc+0x24/0x38
+ el0_svc+0x30/0xf8
+ el0t_64_sync_handler+0x120/0x130
+ el0t_64_sync+0x190/0x198
+
+INFO: task kworker/u8:11:2680853 blocked for more than 120 seconds.
+      Tainted: G           O       6.12.41-g3fe07ddf05ab #1
+"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
+task:kworker/u8:11   state:D stack:0     pid:2680853 tgid:2680853 ppid:2      flags:0x00000208
+Workqueue: writeback wb_workfn (flush-254:0)
+Call trace:
+ __switch_to+0xf4/0x158
+ __schedule+0x27c/0x908
+ schedule+0x3c/0x118
+ io_schedule+0x44/0x68
+ folio_wait_bit_common+0x174/0x370
+ __filemap_get_folio+0x214/0x348
+ pagecache_get_page+0x20/0x70
+ f2fs_get_read_data_page+0x150/0x3e8
+ f2fs_get_lock_data_page+0x2c/0x160
+ move_data_page+0x50/0x478
+ do_garbage_collect+0xd38/0x1528
+ f2fs_gc+0x240/0x7e0
+ f2fs_balance_fs+0x1a0/0x208
+ f2fs_write_single_data_page+0x6e4/0x730
+ f2fs_write_cache_pages+0x378/0x9b0
+ f2fs_write_data_pages+0x2e4/0x388
+ do_writepages+0x8c/0x2c8
+ __writeback_single_inode+0x4c/0x498
+ writeback_sb_inodes+0x234/0x4a8
+ __writeback_inodes_wb+0x58/0x118
+ wb_writeback+0x2f8/0x3c0
+ wb_workfn+0x2c4/0x508
+ process_one_work+0x180/0x408
+ worker_thread+0x258/0x368
+ kthread+0x118/0x128
+ ret_from_fork+0x10/0x200
+
+INFO: task kworker/u8:8:2641297 blocked for more than 120 seconds.
+      Tainted: G           O       6.12.41-g3fe07ddf05ab #1
+"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
+task:kworker/u8:8    state:D stack:0     pid:2641297 tgid:2641297 ppid:2      flags:0x00000208
+Workqueue: writeback wb_workfn (flush-254:0)
+Call trace:
+ __switch_to+0xf4/0x158
+ __schedule+0x27c/0x908
+ rt_mutex_schedule+0x30/0x60
+ __rt_mutex_slowlock_locked.constprop.0+0x460/0x8a8
+ rwbase_write_lock+0x24c/0x378
+ down_write+0x1c/0x30
+ f2fs_balance_fs+0x184/0x208
+ f2fs_write_inode+0xf4/0x328
+ __writeback_single_inode+0x370/0x498
+ writeback_sb_inodes+0x234/0x4a8
+ __writeback_inodes_wb+0x58/0x118
+ wb_writeback+0x2f8/0x3c0
+ wb_workfn+0x2c4/0x508
+ process_one_work+0x180/0x408
+ worker_thread+0x258/0x368
+ kthread+0x118/0x128
+ ret_from_fork+0x10/0x20
+
+INFO: task B:1902 blocked for more than 120 seconds.
+      Tainted: G           O       6.12.41-g3fe07ddf05ab #1
+"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
+task:B     state:D stack:0     pid:1902  tgid:1626  ppid:1153   flags:0x0000020c
+Call trace:
+ __switch_to+0xf4/0x158
+ __schedule+0x27c/0x908
+ rt_mutex_schedule+0x30/0x60
+ __rt_mutex_slowlock_locked.constprop.0+0x460/0x8a8
+ rwbase_write_lock+0x24c/0x378
+ down_write+0x1c/0x30
+ f2fs_balance_fs+0x184/0x208
+ f2fs_map_blocks+0x94c/0x1110
+ f2fs_file_write_iter+0x228/0xb80
+ do_iter_readv_writev+0xf0/0x1e0
+ vfs_writev+0x138/0x2c8
+ do_writev+0x88/0x130
+ __arm64_sys_writev+0x28/0x40
+ invoke_syscall+0x50/0x120
+ el0_svc_common.constprop.0+0xc8/0xf0
+ do_el0_svc+0x24/0x38
+ el0_svc+0x30/0xf8
+ el0t_64_sync_handler+0x120/0x130
+ el0t_64_sync+0x190/0x198
+
+INFO: task sync:2769849 blocked for more than 120 seconds.
+      Tainted: G           O       6.12.41-g3fe07ddf05ab #1
+"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
+task:sync            state:D stack:0     pid:2769849 tgid:2769849 ppid:736    flags:0x0000020c
+Call trace:
+ __switch_to+0xf4/0x158
+ __schedule+0x27c/0x908
+ schedule+0x3c/0x118
+ wb_wait_for_completion+0xb0/0xe8
+ sync_inodes_sb+0xc8/0x2b0
+ sync_inodes_one_sb+0x24/0x38
+ iterate_supers+0xa8/0x138
+ ksys_sync+0x54/0xc8
+ __arm64_sys_sync+0x18/0x30
+ invoke_syscall+0x50/0x120
+ el0_svc_common.constprop.0+0xc8/0xf0
+ do_el0_svc+0x24/0x38
+ el0_svc+0x30/0xf8
+ el0t_64_sync_handler+0x120/0x130
+ el0t_64_sync+0x190/0x198
+
+The root cause is a potential deadlock between the following tasks:
+
+kworker/u8:11                          Thread A
+- f2fs_write_single_data_page
+ - f2fs_do_write_data_page
+  - folio_start_writeback(X)
+  - f2fs_outplace_write_data
+   - bio_add_folio(X)
+ - folio_unlock(X)
+                                       - truncate_inode_pages_range
+                                        - __filemap_get_folio(X, FGP_LOCK)
+                                        - truncate_inode_partial_folio(X)
+                                         - folio_wait_writeback(X)
+ - f2fs_balance_fs
+  - f2fs_gc
+   - do_garbage_collect
+    - move_data_page
+     - f2fs_get_lock_data_page
+      - __filemap_get_folio(X, FGP_LOCK)
+
+Both threads try to access folio X. Thread A holds the lock but waits
+for writeback, while kworker waits for the lock. This causes a deadlock.
+
+Other threads also enter D state, waiting for locks such as gc_lock and
+writepages.
+
+OPU/IPU DATA folio are all affected by this issue. To avoid such
+potential deadlocks, always commit these cached folios before
+triggering f2fs_gc() in f2fs_balance_fs().
+
+Suggested-by: Chao Yu <chao@kernel.org>
+Reviewed-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Ruipeng Qi <ruipengqi3@gmail.com>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Stable-dep-of: 8b4468ec023d ("f2fs: fix potential deadlock in gc_merge path of f2fs_balance_fs()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/data.c    |   29 +++++++++++++++++++++++++++++
+ fs/f2fs/f2fs.h    |    1 +
+ fs/f2fs/segment.c |    7 +++++++
+ 3 files changed, 37 insertions(+)
+
+--- a/fs/f2fs/data.c
++++ b/fs/f2fs/data.c
+@@ -906,6 +906,35 @@ void f2fs_submit_merged_ipu_write(struct
+       }
+ }
++void f2fs_submit_all_merged_ipu_writes(struct f2fs_sb_info *sbi)
++{
++      struct bio_entry *be, *tmp;
++      struct f2fs_bio_info *io;
++      enum temp_type temp;
++
++      for (temp = HOT; temp < NR_TEMP_TYPE; temp++) {
++              LIST_HEAD(list);
++
++              io = sbi->write_io[DATA] + temp;
++
++              /* A lockless list_empty() check is safe here: any bios from
++               * other kworkers that we miss will be submitted by those
++               * kworkers accordingly.
++               */
++              if (list_empty(&io->bio_list))
++                      continue;
++
++              down_write(&io->bio_list_lock);
++              list_splice_init(&io->bio_list, &list);
++              up_write(&io->bio_list_lock);
++
++              list_for_each_entry_safe(be, tmp, &list, list) {
++                      __submit_bio(sbi, be->bio, DATA);
++                      del_bio_entry(be);
++              }
++      }
++}
++
+ int f2fs_merge_page_bio(struct f2fs_io_info *fio)
+ {
+       struct bio *bio = *fio->bio;
+--- a/fs/f2fs/f2fs.h
++++ b/fs/f2fs/f2fs.h
+@@ -3475,6 +3475,7 @@ void f2fs_submit_merged_write_cond(struc
+                               nid_t ino, enum page_type type);
+ void f2fs_submit_merged_ipu_write(struct f2fs_sb_info *sbi,
+                                       struct bio **bio, struct page *page);
++void f2fs_submit_all_merged_ipu_writes(struct f2fs_sb_info *sbi);
+ void f2fs_flush_merged_writes(struct f2fs_sb_info *sbi);
+ int f2fs_submit_page_bio(struct f2fs_io_info *fio);
+ int f2fs_merge_page_bio(struct f2fs_io_info *fio);
+--- a/fs/f2fs/segment.c
++++ b/fs/f2fs/segment.c
+@@ -513,6 +513,13 @@ void f2fs_balance_fs(struct f2fs_sb_info
+        * dir/node pages without enough free segments.
+        */
+       if (has_not_enough_free_secs(sbi, 0, 0)) {
++              /*
++               * Submit all cached OPU/IPU DATA bios before triggering
++               * foreground GC to avoid potential deadlocks.
++               */
++              f2fs_submit_merged_write(sbi, DATA);
++              f2fs_submit_all_merged_ipu_writes(sbi);
++
+               down_write(&sbi->gc_lock);
+               f2fs_gc(sbi, false, false, false, NULL_SEGNO);
+       }
diff --git a/queue-5.10/f2fs-fix-to-round-down-start-offset-of-fallocate-for-pin-file.patch b/queue-5.10/f2fs-fix-to-round-down-start-offset-of-fallocate-for-pin-file.patch
new file mode 100644 (file)
index 0000000..cb9d602
--- /dev/null
@@ -0,0 +1,75 @@
+From stable+bounces-271780-greg=kroah.com@vger.kernel.org Fri Jul  3 15:39:31 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri,  3 Jul 2026 09:31:01 -0400
+Subject: f2fs: fix to round down start offset of fallocate for pin file
+To: stable@vger.kernel.org
+Cc: Sunmin Jeong <s_min.jeong@samsung.com>, Yunji Kang <yunji0.kang@samsung.com>, Yeongjin Gil <youngjin.gil@samsung.com>, Sungjong Seo <sj1557.seo@samsung.com>, Chao Yu <chao@kernel.org>, Jaegeuk Kim <jaegeuk@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260703133101.4123681-2-sashal@kernel.org>
+
+From: Sunmin Jeong <s_min.jeong@samsung.com>
+
+[ Upstream commit 4275b59673eb60b02eec3997816c83f1f4b909c4 ]
+
+Currently, the length of fallocate for pin file is section-aligned to
+keep allocated sections from being selected as victims of GC. However,
+for the case that the start offset of fallocate is not aligned in
+section, the allocated sections can't be fully utilized. It's because a
+new section is allocated by f2fs_allocate_pinning_section() after using
+blks_per_sec blocks regardless of the start offset. As a result, several
+unexpected dirty segments may be created, including blocks assigned to
+the pinned file.
+
+To address this issue, let's round down the start offset of fallocate
+to the length of section.
+
+The reproducing scenario is as below
+
+chunk=$(((2<<20)+4096)) # 2MB + 4KB
+touch test
+f2fs_io pinfile set test
+f2fs_io fallocate 0 0 $chunk test
+f2fs_io fallocate 0 $chunk $chunk test
+f2fs_io fallocate 0 $((chunk*2)) $chunk test
+f2fs_io fiemap 0 $((chunk*3)) test
+
+Fiemap: offset = 0 len = 12288
+    logical addr.    physical addr.   length           flags
+0   0000000000000000 000000068c600000 0000000000400000 00001088
+1   0000000000400000 000000003d400000 0000000000001000 00001088
+2   0000000000401000 00000003eb200000 0000000000200000 00001088
+3   0000000000601000 00000005e4200000 0000000000001000 00001088
+4   0000000000602000 0000000605400000 0000000000200000 00001089
+
+Cc: stable@vger.kernel.org
+Fixes: f5a53edcf01e ("f2fs: support aligned pinned file")
+Reviewed-by: Yunji Kang <yunji0.kang@samsung.com>
+Reviewed-by: Yeongjin Gil <youngjin.gil@samsung.com>
+Reviewed-by: Sungjong Seo <sj1557.seo@samsung.com>
+Signed-off-by: Sunmin Jeong <s_min.jeong@samsung.com>
+Reviewed-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/file.c |    9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+--- a/fs/f2fs/file.c
++++ b/fs/f2fs/file.c
+@@ -1682,8 +1682,15 @@ static int expand_inode_data(struct inod
+       if (f2fs_is_pinned_file(inode)) {
+               block_t sec_blks = CAP_BLKS_PER_SEC(sbi);
+-              block_t sec_len = roundup(map.m_len, sec_blks);
++              block_t sec_len;
++              if (map.m_lblk % sec_blks) {
++                      map.m_lblk = rounddown(map.m_lblk, sec_blks);
++                      map.m_len = pg_end - map.m_lblk;
++                      if (off_end)
++                              map.m_len++;
++              }
++              sec_len = roundup(map.m_len, sec_blks);
+               map.m_len = sec_blks;
+ next_alloc:
+               if (has_not_enough_free_secs(sbi, 0,
diff --git a/queue-5.10/f2fs-validate-orphan-inode-entry-count.patch b/queue-5.10/f2fs-validate-orphan-inode-entry-count.patch
new file mode 100644 (file)
index 0000000..d0dae49
--- /dev/null
@@ -0,0 +1,68 @@
+From stable+bounces-271844-greg=kroah.com@vger.kernel.org Fri Jul  3 20:25:13 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri,  3 Jul 2026 14:14:20 -0400
+Subject: f2fs: validate orphan inode entry count
+To: stable@vger.kernel.org
+Cc: Wenjie Qi <qwjhust@gmail.com>, stable@kernel.org, Wenjie Qi <qiwenjie@xiaomi.com>, Chao Yu <chao@kernel.org>, Jaegeuk Kim <jaegeuk@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260703181420.250032-1-sashal@kernel.org>
+
+From: Wenjie Qi <qwjhust@gmail.com>
+
+[ Upstream commit 846c499a65816d13f1186e3090e825e8bb8bcb8b ]
+
+f2fs_recover_orphan_inodes() trusts the orphan block entry_count when
+replaying orphan inodes from the checkpoint pack. A corrupted entry_count
+larger than F2FS_ORPHANS_PER_BLOCK makes the recovery loop read past the
+ino[] array and interpret footer or following data as inode numbers.
+
+On a crafted image, mounting an unpatched kernel can drive orphan recovery
+into f2fs_bug_on() and panic the kernel. Validate entry_count before
+consuming entries so corrupted checkpoint data fails the mount with
+-EFSCORRUPTED and requests fsck instead.
+
+Set ERROR_INCONSISTENT_ORPHAN as well, so the corruption reason can be
+recorded in the superblock s_errors[] field. This gives fsck a persistent
+hint even though mount-time orphan recovery failure may leave no chance to
+persist SBI_NEED_FSCK through a checkpoint.
+
+Cc: stable@kernel.org
+Fixes: 127e670abfa7 ("f2fs: add checkpoint operations")
+Signed-off-by: Wenjie Qi <qiwenjie@xiaomi.com>
+Reviewed-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+[ Folio API ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/checkpoint.c |   13 ++++++++++++-
+ 1 file changed, 12 insertions(+), 1 deletion(-)
+
+--- a/fs/f2fs/checkpoint.c
++++ b/fs/f2fs/checkpoint.c
+@@ -723,6 +723,7 @@ int f2fs_recover_orphan_inodes(struct f2
+       for (i = 0; i < orphan_blocks; i++) {
+               struct page *page;
+               struct f2fs_orphan_block *orphan_blk;
++              unsigned int entry_count;
+               page = f2fs_get_meta_page(sbi, start_blk + i);
+               if (IS_ERR(page)) {
+@@ -731,7 +732,17 @@ int f2fs_recover_orphan_inodes(struct f2
+               }
+               orphan_blk = (struct f2fs_orphan_block *)page_address(page);
+-              for (j = 0; j < le32_to_cpu(orphan_blk->entry_count); j++) {
++              entry_count = le32_to_cpu(orphan_blk->entry_count);
++              if (entry_count > F2FS_ORPHANS_PER_BLOCK) {
++                      f2fs_err(sbi, "invalid orphan inode entry count %u",
++                               entry_count);
++                      set_sbi_flag(sbi, SBI_NEED_FSCK);
++                      err = -EFSCORRUPTED;
++                      f2fs_put_page(page, 1);
++                      goto out;
++              }
++
++              for (j = 0; j < entry_count; j++) {
+                       nid_t ino = le32_to_cpu(orphan_blk->ino[j]);
+                       err = recover_orphan_inode(sbi, ino);
+                       if (err) {
diff --git a/queue-5.10/fbdev-fbcon-fix-out-of-bounds-read-in-err_out-of-fbcon_do_set_font.patch b/queue-5.10/fbdev-fbcon-fix-out-of-bounds-read-in-err_out-of-fbcon_do_set_font.patch
new file mode 100644 (file)
index 0000000..550b045
--- /dev/null
@@ -0,0 +1,70 @@
+From stable+bounces-272074-greg=kroah.com@vger.kernel.org Sun Jul  5 16:25:07 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun,  5 Jul 2026 10:24:59 -0400
+Subject: fbdev: fbcon: fix out-of-bounds read in err_out of fbcon_do_set_font()
+To: stable@vger.kernel.org
+Cc: Mingyu Wang <25181214217@stu.xidian.edu.cn>, Thomas Zimmermann <tzimmermann@suse.de>, Helge Deller <deller@gmx.de>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260705142459.1798975-1-sashal@kernel.org>
+
+From: Mingyu Wang <25181214217@stu.xidian.edu.cn>
+
+[ Upstream commit 8fdc8c2057eea08d40ce2c8eed41ff9e451c65c2 ]
+
+When fbcon_do_set_font() fails (e.g., due to a memory allocation failure
+inside vc_resize() under heavy memory pressure), it jumps to the `err_out`
+label to roll back the console state. However, the current rollback logic
+forgets to restore the `hi_font` state, leading to a severe state machine
+corruption.
+
+Earlier in the function, `set_vc_hi_font()` might be called to change
+`vc->vc_hi_font_mask` and mutate the screen buffer. If `vc_resize()`
+subsequently fails, the `err_out` path restores `vc_font.charcount`
+but entirely skips rolling back the `vc_hi_font_mask` and the screen
+buffer.
+
+This mismatch leaves the terminal in a desynchronized state. Because
+`vc_hi_font_mask` remains set, the VT subsystem will still accept
+character indices greater than 255 from userspace and write them to the
+screen buffer. Subsequent rendering calls (e.g., `fbcon_putcs()`) will
+then use these inflated indices to access the reverted, 256-character
+font array, leading to a deterministic out-of-bounds read and potential
+kernel memory disclosure.
+
+Fix this by adding the missing rollback logic for the `hi_font` mask
+and screen buffer in the error path.
+
+Fixes: a5a923038d70 ("fbdev: fbcon: Properly revert changes when vc_resize() failed")
+Cc: stable@vger.kernel.org
+Signed-off-by: Mingyu Wang <25181214217@stu.xidian.edu.cn>
+Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de>
+Signed-off-by: Helge Deller <deller@gmx.de>
+[ Adjust context ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/video/fbdev/core/fbcon.c |    7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/drivers/video/fbdev/core/fbcon.c
++++ b/drivers/video/fbdev/core/fbcon.c
+@@ -2426,6 +2426,7 @@ static int fbcon_do_set_font(struct vc_d
+       struct fbcon_display *p = &fb_display[vc->vc_num];
+       int resize, ret, old_userfont, old_width, old_height, old_charcount;
+       u8 *old_data = vc->vc_font.data;
++      unsigned short old_hi_font_mask = vc->vc_hi_font_mask;
+       resize = (w != vc->vc_font.width) || (h != vc->vc_font.height);
+       vc->vc_font.data = (void *)(p->fontdata = data);
+@@ -2479,6 +2480,12 @@ err_out:
+       vc->vc_font.height = old_height;
+       vc->vc_font.charcount = old_charcount;
++      /* Restore the hi_font state and screen buffer */
++      if (old_hi_font_mask && !vc->vc_hi_font_mask)
++              set_vc_hi_font(vc, true);
++      else if (!old_hi_font_mask && vc->vc_hi_font_mask)
++              set_vc_hi_font(vc, false);
++
+       return ret;
+ }
diff --git a/queue-5.10/hdlc_ppp-sync-per-proto-timers-before-freeing-hdlc-state.patch b/queue-5.10/hdlc_ppp-sync-per-proto-timers-before-freeing-hdlc-state.patch
new file mode 100644 (file)
index 0000000..24ce564
--- /dev/null
@@ -0,0 +1,114 @@
+From stable+bounces-272117-greg=kroah.com@vger.kernel.org Mon Jul  6 04:28:31 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun,  5 Jul 2026 22:28:22 -0400
+Subject: hdlc_ppp: sync per-proto timers before freeing hdlc state
+To: stable@vger.kernel.org
+Cc: Fan Wu <fanwu01@zju.edu.cn>, Jakub Kicinski <kuba@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260706022823.2081953-1-sashal@kernel.org>
+
+From: Fan Wu <fanwu01@zju.edu.cn>
+
+[ Upstream commit c78a4e41ab5ead6193ad8a2dd92e8906bae659fa ]
+
+Each PPP control protocol (LCP/IPCP/IPV6CP) embedded in struct ppp
+registers a timer via timer_setup(). That struct ppp is the
+hdlc->state allocation, which detach_hdlc_protocol() frees with kfree()
+in both teardown paths: unregister_hdlc_device() and the re-attach inside
+attach_hdlc_protocol().
+
+The ppp proto never registered a .detach callback, so
+detach_hdlc_protocol() performs no timer synchronization before the
+kfree(). The only cancel, timer_delete(&proto->timer) in ppp_cp_event(),
+is partial (it does not wait for a running callback) and only runs on the
+->CLOSED transition; ppp_stop()/ppp_close() do not sync either. A
+ppp_timer callback already executing (blocked on ppp->lock) survives the
+kfree and then dereferences proto->state / ppp->lock in freed memory,
+leading to a use-after-free.
+
+Fix this by adding a .detach helper that calls timer_shutdown_sync() on
+every per-proto timer. detach_hdlc_protocol() invokes proto->detach(dev)
+before kfree(hdlc->state), so timer_shutdown_sync()
+now runs on both free paths.
+timer_shutdown_sync() is used instead of timer_delete_sync() because the
+keepalive path re-arms the timer through add_timer()/mod_timer() and
+shutdown blocks any re-activation during teardown.
+
+Initialize the per-protocol timers in ppp_ioctl() when the protocol is
+attached, and remove the now-redundant timer_setup() from ppp_start(), so
+that the timers are initialized exactly once at attach time and
+ppp_timer_release() never operates on uninitialized timer_list
+structures. attach_hdlc_protocol() uses kmalloc() (not kzalloc), so
+struct ppp's protos[i].timer is uninitialized garbage until the first
+timer_setup(); without this init-at-attach, attaching the PPP protocol
+without ever bringing the device up would leave timer_shutdown_sync()
+operating on uninitialized memory in .detach. Moving the init out of
+ppp_start() (which only runs on NETDEV_UP) into the attach path makes the
+initialization unconditional and avoids initializing the same timer_list
+twice.
+
+This bug was found by static analysis.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Cc: stable@vger.kernel.org
+Signed-off-by: Fan Wu <fanwu01@zju.edu.cn>
+Link: https://patch.msgid.link/20260617020518.116319-1-fanwu01@zju.edu.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+[ replaced timer_shutdown_sync() with del_timer_sync() since timer_shutdown_sync() is not available in 5.10 ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/wan/hdlc_ppp.c |   15 +++++++++++++--
+ 1 file changed, 13 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wan/hdlc_ppp.c
++++ b/drivers/net/wan/hdlc_ppp.c
+@@ -624,7 +624,6 @@ static void ppp_start(struct net_device
+       for (i = 0; i < IDX_COUNT; i++) {
+               struct proto *proto = &ppp->protos[i];
+               proto->dev = dev;
+-              timer_setup(&proto->timer, ppp_timer, 0);
+               proto->state = CLOSED;
+       }
+       ppp->protos[IDX_LCP].pid = PID_LCP;
+@@ -644,6 +643,15 @@ static void ppp_close(struct net_device
+       ppp_tx_flush();
+ }
++static void ppp_timer_release(struct net_device *dev)
++{
++      struct ppp *ppp = get_ppp(dev);
++      int i;
++
++      for (i = 0; i < IDX_COUNT; i++)
++              del_timer_sync(&ppp->protos[i].timer);
++}
++
+ static struct hdlc_proto proto = {
+       .start          = ppp_start,
+       .stop           = ppp_stop,
+@@ -652,6 +660,7 @@ static struct hdlc_proto proto = {
+       .ioctl          = ppp_ioctl,
+       .netif_rx       = ppp_rx,
+       .module         = THIS_MODULE,
++      .detach         = ppp_timer_release,
+ };
+ static const struct header_ops ppp_header_ops = {
+@@ -662,7 +671,7 @@ static int ppp_ioctl(struct net_device *
+ {
+       hdlc_device *hdlc = dev_to_hdlc(dev);
+       struct ppp *ppp;
+-      int result;
++      int i, result;
+       switch (ifr->ifr_settings.type) {
+       case IF_GET_PROTO:
+@@ -689,6 +698,8 @@ static int ppp_ioctl(struct net_device *
+                       return result;
+               ppp = get_ppp(dev);
++              for (i = 0; i < IDX_COUNT; i++)
++                      timer_setup(&ppp->protos[i].timer, ppp_timer, 0);
+               spin_lock_init(&ppp->lock);
+               ppp->req_timeout = 2;
+               ppp->cr_retries = 10;
diff --git a/queue-5.10/i2c-core-fix-adapter-debugfs-creation.patch b/queue-5.10/i2c-core-fix-adapter-debugfs-creation.patch
new file mode 100644 (file)
index 0000000..7317793
--- /dev/null
@@ -0,0 +1,80 @@
+From stable+bounces-272090-greg=kroah.com@vger.kernel.org Sun Jul  5 21:06:23 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun,  5 Jul 2026 15:06:11 -0400
+Subject: i2c: core: fix adapter debugfs creation
+To: stable@vger.kernel.org
+Cc: Johan Hovold <johan@kernel.org>, Wolfram Sang <wsa+renesas@sang-engineering.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260705190612.1987801-4-sashal@kernel.org>
+
+From: Johan Hovold <johan@kernel.org>
+
+[ Upstream commit 07d5fb537928aad4369aaff0cbae73ba38a719af ]
+
+Clients can be registered from bus notifier callbacks so the debugfs
+directory needs to be created before registering the adapter as clients
+use that directory as their debugfs parent.
+
+Move debugfs creation before adapter registration to avoid having
+clients create their debugfs directories in the debugfs root (which is
+also more likely to fail due to name collisions).
+
+Note that failure to allocate the adapter name must now be handled
+explicitly as debugfs_create_dir() cannot handle a NULL name (unlike
+device_add() which returns an error).
+
+Fixes: 73febd775bdb ("i2c: create debugfs entry per adapter")
+Cc: stable@vger.kernel.org     # 6.8
+Cc: Wolfram Sang <wsa+renesas@sang-engineering.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
+Stable-dep-of: ba14d7cf2fe7 ("i2c: core: fix adapter registration race")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/i2c/i2c-core-base.c |   19 ++++++++++++-------
+ 1 file changed, 12 insertions(+), 7 deletions(-)
+
+--- a/drivers/i2c/i2c-core-base.c
++++ b/drivers/i2c/i2c-core-base.c
+@@ -1456,10 +1456,19 @@ static int i2c_register_adapter(struct i
+               goto out_list;
+       }
+-      dev_set_name(&adap->dev, "i2c-%d", adap->nr);
++      res = dev_set_name(&adap->dev, "i2c-%d", adap->nr);
++      if (res)
++              goto err_remove_irq_domain;
++
+       adap->dev.bus = &i2c_bus_type;
+       adap->dev.type = &i2c_adapter_type;
+-      res = device_register(&adap->dev);
++      device_initialize(&adap->dev);
++
++      pm_runtime_no_callbacks(&adap->dev);
++      pm_suspend_ignore_children(&adap->dev, true);
++      pm_runtime_enable(&adap->dev);
++
++      res = device_add(&adap->dev);
+       if (res) {
+               pr_err("adapter '%s': can't register device (%d)\n", adap->name, res);
+               goto err_put_adap;
+@@ -1469,10 +1478,6 @@ static int i2c_register_adapter(struct i
+       if (res)
+               goto out_reg;
+-      pm_runtime_no_callbacks(&adap->dev);
+-      pm_suspend_ignore_children(&adap->dev, true);
+-      pm_runtime_enable(&adap->dev);
+-
+       res = i2c_init_recovery(adap);
+       if (res == -EPROBE_DEFER)
+               goto out_reg;
+@@ -1509,7 +1514,7 @@ err_put_adap:
+       init_completion(&adap->dev_released);
+       put_device(&adap->dev);
+       wait_for_completion(&adap->dev_released);
+-
++err_remove_irq_domain:
+       i2c_host_notify_irq_teardown(adap);
+ out_list:
+       mutex_lock(&core_lock);
diff --git a/queue-5.10/i2c-core-fix-adapter-registration-race.patch b/queue-5.10/i2c-core-fix-adapter-registration-race.patch
new file mode 100644 (file)
index 0000000..0e4f146
--- /dev/null
@@ -0,0 +1,65 @@
+From stable+bounces-272091-greg=kroah.com@vger.kernel.org Sun Jul  5 21:06:23 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun,  5 Jul 2026 15:06:12 -0400
+Subject: i2c: core: fix adapter registration race
+To: stable@vger.kernel.org
+Cc: Johan Hovold <johan@kernel.org>, Wolfram Sang <wsa+renesas@sang-engineering.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260705190612.1987801-5-sashal@kernel.org>
+
+From: Johan Hovold <johan@kernel.org>
+
+[ Upstream commit ba14d7cf2fe7284610a29854bdff22b2537d3ce6 ]
+
+Adapters can be looked up based on their id using i2c_get_adapter()
+which takes a reference to the embedded struct device.
+
+Make sure that the adapter (including its struct device) has been
+initialised before adding it to the IDR to avoid accessing uninitialised
+data which could, for example, lead to NULL-pointer dereferences or
+use-after-free.
+
+Note that the i2c-dev chardev, which is registered from a bus notifier,
+currently uses i2c_get_adapter() so the adapter needs to be added to the
+IDR before registration.
+
+Fixes: 6e13e6418418 ("i2c: Add i2c_add_numbered_adapter()")
+Cc: stable@vger.kernel.org     # 2.6.22
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/i2c/i2c-core-base.c |    8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+--- a/drivers/i2c/i2c-core-base.c
++++ b/drivers/i2c/i2c-core-base.c
+@@ -1468,6 +1468,10 @@ static int i2c_register_adapter(struct i
+       pm_suspend_ignore_children(&adap->dev, true);
+       pm_runtime_enable(&adap->dev);
++      mutex_lock(&core_lock);
++      idr_replace(&i2c_adapter_idr, adap, adap->nr);
++      mutex_unlock(&core_lock);
++
+       res = device_add(&adap->dev);
+       if (res) {
+               pr_err("adapter '%s': can't register device (%d)\n", adap->name, res);
+@@ -1535,7 +1539,7 @@ static int __i2c_add_numbered_adapter(st
+       int id;
+       mutex_lock(&core_lock);
+-      id = idr_alloc(&i2c_adapter_idr, adap, adap->nr, adap->nr + 1, GFP_KERNEL);
++      id = idr_alloc(&i2c_adapter_idr, NULL, adap->nr, adap->nr + 1, GFP_KERNEL);
+       mutex_unlock(&core_lock);
+       if (WARN(id < 0, "couldn't get idr"))
+               return id == -ENOSPC ? -EBUSY : id;
+@@ -1571,7 +1575,7 @@ int i2c_add_adapter(struct i2c_adapter *
+       }
+       mutex_lock(&core_lock);
+-      id = idr_alloc(&i2c_adapter_idr, adapter,
++      id = idr_alloc(&i2c_adapter_idr, NULL,
+                      __i2c_first_dynamic_bus_num, 0, GFP_KERNEL);
+       mutex_unlock(&core_lock);
+       if (WARN(id < 0, "couldn't get idr"))
diff --git a/queue-5.10/i2c-core-fix-hang-on-adapter-registration-failure.patch b/queue-5.10/i2c-core-fix-hang-on-adapter-registration-failure.patch
new file mode 100644 (file)
index 0000000..de5cd36
--- /dev/null
@@ -0,0 +1,114 @@
+From stable+bounces-272088-greg=kroah.com@vger.kernel.org Sun Jul  5 21:06:23 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun,  5 Jul 2026 15:06:09 -0400
+Subject: i2c: core: fix hang on adapter registration failure
+To: stable@vger.kernel.org
+Cc: Johan Hovold <johan@kernel.org>, Phil Reid <preid@electromag.com.au>, Wolfram Sang <wsa+renesas@sang-engineering.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260705190612.1987801-2-sashal@kernel.org>
+
+From: Johan Hovold <johan@kernel.org>
+
+[ Upstream commit 3c7e164344e5bcf6f274bbf59a3274f5caad9bc1 ]
+
+Clients may be registered from bus notifier callbacks when the adapter
+is registered. On a subsequent error during registration, the adapter
+references taken by such clients prevent the wait for the references to
+be released from ever completing.
+
+Fix this by refactoring client deregistration and deregistering also on
+late adapter registration failures.
+
+Fixes: f8756c67b3de ("i2c: core: call of_i2c_setup_smbus_alert in i2c_register_adapter")
+Cc: stable@vger.kernel.org     # 4.15
+Cc: Phil Reid <preid@electromag.com.au>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
+Stable-dep-of: ba14d7cf2fe7 ("i2c: core: fix adapter registration race")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/i2c/i2c-core-base.c |   49 ++++++++++++++++++++++++++------------------
+ 1 file changed, 29 insertions(+), 20 deletions(-)
+
+--- a/drivers/i2c/i2c-core-base.c
++++ b/drivers/i2c/i2c-core-base.c
+@@ -61,6 +61,7 @@
+ static DEFINE_MUTEX(core_lock);
+ static DEFINE_IDR(i2c_adapter_idr);
++static void i2c_deregister_clients(struct i2c_adapter *adap);
+ static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver);
+ static DEFINE_STATIC_KEY_FALSE(i2c_trace_msg_key);
+@@ -1502,6 +1503,7 @@ static int i2c_register_adapter(struct i
+       return 0;
+ out_reg:
++      i2c_deregister_clients(adap);
+       init_completion(&adap->dev_released);
+       device_unregister(&adap->dev);
+       wait_for_completion(&adap->dev_released);
+@@ -1644,29 +1646,10 @@ static int __process_removed_adapter(str
+       return 0;
+ }
+-/**
+- * i2c_del_adapter - unregister I2C adapter
+- * @adap: the adapter being unregistered
+- * Context: can sleep
+- *
+- * This unregisters an I2C adapter which was previously registered
+- * by @i2c_add_adapter or @i2c_add_numbered_adapter.
+- */
+-void i2c_del_adapter(struct i2c_adapter *adap)
++static void i2c_deregister_clients(struct i2c_adapter *adap)
+ {
+-      struct i2c_adapter *found;
+       struct i2c_client *client, *next;
+-      /* First make sure that this adapter was ever added */
+-      mutex_lock(&core_lock);
+-      found = idr_find(&i2c_adapter_idr, adap->nr);
+-      mutex_unlock(&core_lock);
+-      if (found != adap) {
+-              pr_debug("attempting to delete unregistered adapter [%s]\n", adap->name);
+-              return;
+-      }
+-
+-      i2c_acpi_remove_space_handler(adap);
+       /* Tell drivers about this removal */
+       mutex_lock(&core_lock);
+       bus_for_each_drv(&i2c_bus_type, NULL, adap,
+@@ -1692,6 +1675,32 @@ void i2c_del_adapter(struct i2c_adapter
+        * them up properly, so we give them a chance to do that first. */
+       device_for_each_child(&adap->dev, NULL, __unregister_client);
+       device_for_each_child(&adap->dev, NULL, __unregister_dummy);
++}
++
++/**
++ * i2c_del_adapter - unregister I2C adapter
++ * @adap: the adapter being unregistered
++ * Context: can sleep
++ *
++ * This unregisters an I2C adapter which was previously registered
++ * by @i2c_add_adapter or @i2c_add_numbered_adapter.
++ */
++void i2c_del_adapter(struct i2c_adapter *adap)
++{
++      struct i2c_adapter *found;
++
++      /* First make sure that this adapter was ever added */
++      mutex_lock(&core_lock);
++      found = idr_find(&i2c_adapter_idr, adap->nr);
++      mutex_unlock(&core_lock);
++      if (found != adap) {
++              pr_debug("attempting to delete unregistered adapter [%s]\n", adap->name);
++              return;
++      }
++
++      i2c_acpi_remove_space_handler(adap);
++
++      i2c_deregister_clients(adap);
+ #ifdef CONFIG_I2C_COMPAT
+       class_compat_remove_link(i2c_adapter_compat_class, &adap->dev,
diff --git a/queue-5.10/i2c-core-fix-irq-domain-leak-on-adapter-registration-failure.patch b/queue-5.10/i2c-core-fix-irq-domain-leak-on-adapter-registration-failure.patch
new file mode 100644 (file)
index 0000000..dec1cd1
--- /dev/null
@@ -0,0 +1,50 @@
+From stable+bounces-272087-greg=kroah.com@vger.kernel.org Sun Jul  5 21:06:19 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun,  5 Jul 2026 15:06:08 -0400
+Subject: i2c: core: fix irq domain leak on adapter registration failure
+To: stable@vger.kernel.org
+Cc: Johan Hovold <johan@kernel.org>, Benjamin Tissoires <bentiss@kernel.org>, Wolfram Sang <wsa+renesas@sang-engineering.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260705190612.1987801-1-sashal@kernel.org>
+
+From: Johan Hovold <johan@kernel.org>
+
+[ Upstream commit 8ce19524e4cc2462685f596a6402fbd8fb984ab2 ]
+
+Make sure to tear down the host notify irq domain on adapter
+registration failure to avoid leaking it.
+
+This issue was flagged by Sashiko when reviewing another adapter
+registration fix.
+
+Fixes: 4d5538f5882a ("i2c: use an IRQ to report Host Notify events, not alert")
+Cc: stable@vger.kernel.org     # 4.10
+Cc: Benjamin Tissoires <bentiss@kernel.org>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
+Stable-dep-of: ba14d7cf2fe7 ("i2c: core: fix adapter registration race")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/i2c/i2c-core-base.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/i2c/i2c-core-base.c
++++ b/drivers/i2c/i2c-core-base.c
+@@ -1461,7 +1461,7 @@ static int i2c_register_adapter(struct i
+       res = device_register(&adap->dev);
+       if (res) {
+               pr_err("adapter '%s': can't register device (%d)\n", adap->name, res);
+-              goto out_list;
++              goto err_remove_irq_domain;
+       }
+       res = of_i2c_setup_smbus_alert(adap);
+@@ -1505,6 +1505,8 @@ out_reg:
+       init_completion(&adap->dev_released);
+       device_unregister(&adap->dev);
+       wait_for_completion(&adap->dev_released);
++err_remove_irq_domain:
++      i2c_host_notify_irq_teardown(adap);
+ out_list:
+       mutex_lock(&core_lock);
+       idr_remove(&i2c_adapter_idr, adap->nr);
diff --git a/queue-5.10/i2c-core-fix-null-deref-on-adapter-registration-failure.patch b/queue-5.10/i2c-core-fix-null-deref-on-adapter-registration-failure.patch
new file mode 100644 (file)
index 0000000..9e9e2dd
--- /dev/null
@@ -0,0 +1,57 @@
+From stable+bounces-272089-greg=kroah.com@vger.kernel.org Sun Jul  5 21:06:28 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun,  5 Jul 2026 15:06:10 -0400
+Subject: i2c: core: fix NULL-deref on adapter registration failure
+To: stable@vger.kernel.org
+Cc: Johan Hovold <johan@kernel.org>, Joe Hattori <joe@pf.is.s.u-tokyo.ac.jp>, Wolfram Sang <wsa+renesas@sang-engineering.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260705190612.1987801-3-sashal@kernel.org>
+
+From: Johan Hovold <johan@kernel.org>
+
+[ Upstream commit 2295d2bb101faa663fbc45fadbb3fec45f107441 ]
+
+If adapter registration ever fails the release callback would trigger a
+NULL-pointer dereference as the completion struct has not been
+initialised.
+
+Note that before the offending commit this would instead have resulted
+in a minor memory leak of the adapter name.
+
+Fixes: 3f8c4f5e9a57 ("i2c: core: fix reference leak in i2c_register_adapter()")
+Cc: stable@vger.kernel.org
+Cc: Joe Hattori <joe@pf.is.s.u-tokyo.ac.jp>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
+Stable-dep-of: ba14d7cf2fe7 ("i2c: core: fix adapter registration race")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/i2c/i2c-core-base.c |    8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+--- a/drivers/i2c/i2c-core-base.c
++++ b/drivers/i2c/i2c-core-base.c
+@@ -1462,7 +1462,7 @@ static int i2c_register_adapter(struct i
+       res = device_register(&adap->dev);
+       if (res) {
+               pr_err("adapter '%s': can't register device (%d)\n", adap->name, res);
+-              goto err_remove_irq_domain;
++              goto err_put_adap;
+       }
+       res = of_i2c_setup_smbus_alert(adap);
+@@ -1504,10 +1504,12 @@ static int i2c_register_adapter(struct i
+ out_reg:
+       i2c_deregister_clients(adap);
++      device_del(&adap->dev);
++err_put_adap:
+       init_completion(&adap->dev_released);
+-      device_unregister(&adap->dev);
++      put_device(&adap->dev);
+       wait_for_completion(&adap->dev_released);
+-err_remove_irq_domain:
++
+       i2c_host_notify_irq_teardown(adap);
+ out_list:
+       mutex_lock(&core_lock);
diff --git a/queue-5.10/net-ip_gre-require-cap_net_admin-in-the-device-netns-for-changelink.patch b/queue-5.10/net-ip_gre-require-cap_net_admin-in-the-device-netns-for-changelink.patch
new file mode 100644 (file)
index 0000000..42449fe
--- /dev/null
@@ -0,0 +1,99 @@
+From stable+bounces-270565-greg=kroah.com@vger.kernel.org Thu Jul  2 17:42:18 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu,  2 Jul 2026 11:36:22 -0400
+Subject: net: ip_gre: require CAP_NET_ADMIN in the device netns for changelink
+To: stable@vger.kernel.org
+Cc: Maoyi Xie <maoyixie.tju@gmail.com>, Xiao Liang <shaw.leon@gmail.com>, Kuniyuki Iwashima <kuniyu@google.com>, Jakub Kicinski <kuba@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260702153622.3533221-1-sashal@kernel.org>
+
+From: Maoyi Xie <maoyixie.tju@gmail.com>
+
+[ Upstream commit 8165f7ff57d9667d2bb477ef6af83ede7fed4ad7 ]
+
+A tunnel changelink() operates on at most two netns, dev_net(dev) and
+the tunnel link netns t->net. They differ once the device is created in
+or moved to a netns other than the one the request runs in. The rtnl
+changelink path checks CAP_NET_ADMIN only against dev_net(dev), so a
+caller privileged there but not in t->net can rewrite a tunnel that
+lives in t->net.
+
+Add rtnl_dev_link_net_capable() next to rtnl_get_net_ns_capable() in
+net/core/rtnetlink.c. It requires CAP_NET_ADMIN in the link netns and is
+skipped when the link netns is dev_net(dev), where the rtnl path already
+checked it. The other patches in this series use the same helper.
+
+Gate ipgre_changelink() and erspan_changelink() with it, at the top of
+the op before any attribute is parsed, because the parsers update live
+tunnel fields first. ipgre_netlink_parms() sets t->collect_md before
+ip_tunnel_changelink() runs.
+
+Commit 8b484efd5cb4 ("ip6: vti: Use ip6_tnl.net in
+vti6_siocdevprivate().") added the same check on the ioctl path. This
+adds it on RTM_NEWLINK.
+
+Reported-by: Xiao Liang <shaw.leon@gmail.com>
+Closes: https://lore.kernel.org/netdev/CABAhCOSzP1vaThGV35_VnsRCb=87_CPjPVsTHbq905k8A+BuUg@mail.gmail.com/
+Fixes: b57708add314 ("gre: add x-netns support")
+Cc: stable@vger.kernel.org
+Signed-off-by: Maoyi Xie <maoyixie.tju@gmail.com>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
+Link: https://patch.msgid.link/20260612085941.3158249-2-maoyixie.tju@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/net/rtnetlink.h |    2 ++
+ net/core/rtnetlink.c    |    8 ++++++++
+ net/ipv4/ip_gre.c       |    6 ++++++
+ 3 files changed, 16 insertions(+)
+
+--- a/include/net/rtnetlink.h
++++ b/include/net/rtnetlink.h
+@@ -183,6 +183,8 @@ int rtnl_configure_link(struct net_devic
+ int rtnl_nla_parse_ifinfomsg(struct nlattr **tb, const struct nlattr *nla_peer,
+                            struct netlink_ext_ack *exterr);
+ struct net *rtnl_get_net_ns_capable(struct sock *sk, int netnsid);
++bool rtnl_dev_link_net_capable(const struct net_device *dev,
++                             const struct net *link_net);
+ #define MODULE_ALIAS_RTNL_LINK(kind) MODULE_ALIAS("rtnl-link-" kind)
+--- a/net/core/rtnetlink.c
++++ b/net/core/rtnetlink.c
+@@ -2024,6 +2024,14 @@ struct net *rtnl_get_net_ns_capable(stru
+ }
+ EXPORT_SYMBOL_GPL(rtnl_get_net_ns_capable);
++bool rtnl_dev_link_net_capable(const struct net_device *dev,
++                             const struct net *link_net)
++{
++      return net_eq(link_net, dev_net(dev)) ||
++             ns_capable(link_net->user_ns, CAP_NET_ADMIN);
++}
++EXPORT_SYMBOL_GPL(rtnl_dev_link_net_capable);
++
+ static int rtnl_valid_dump_ifinfo_req(const struct nlmsghdr *nlh,
+                                     bool strict_check, struct nlattr **tb,
+                                     struct netlink_ext_ack *extack)
+--- a/net/ipv4/ip_gre.c
++++ b/net/ipv4/ip_gre.c
+@@ -1407,6 +1407,9 @@ static int ipgre_changelink(struct net_d
+       struct ip_tunnel_parm p;
+       int err;
++      if (!rtnl_dev_link_net_capable(dev, t->net))
++              return -EPERM;
++
+       err = ipgre_newlink_encap_setup(dev, data);
+       if (err)
+               return err;
+@@ -1436,6 +1439,9 @@ static int erspan_changelink(struct net_
+       struct ip_tunnel_parm p;
+       int err;
++      if (!rtnl_dev_link_net_capable(dev, t->net))
++              return -EPERM;
++
+       err = ipgre_newlink_encap_setup(dev, data);
+       if (err)
+               return err;
diff --git a/queue-5.10/net-skmsg-preserve-sg.copy-across-sg-transforms.patch b/queue-5.10/net-skmsg-preserve-sg.copy-across-sg-transforms.patch
new file mode 100644 (file)
index 0000000..9a7f7e9
--- /dev/null
@@ -0,0 +1,292 @@
+From stable+bounces-270555-greg=kroah.com@vger.kernel.org Thu Jul  2 17:30:39 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu,  2 Jul 2026 11:26:23 -0400
+Subject: net: skmsg: preserve sg.copy across SG transforms
+To: stable@vger.kernel.org
+Cc: Yiming Qian <yimingqian591@gmail.com>, Keenan Dong <keenanat2000@gmail.com>, Jakub Kicinski <kuba@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260702152623.3530248-2-sashal@kernel.org>
+
+From: Yiming Qian <yimingqian591@gmail.com>
+
+[ Upstream commit 406e8a651a7b854c41fecd5117bb282b3a6c2c6b ]
+
+The sk_msg sg.copy bitmap is part of the scatterlist entry ownership
+state. A set bit tells sk_msg_compute_data_pointers() not to expose the
+entry through writable BPF ctx->data. This protects entries backed by
+pages that are not private to the sk_msg, such as splice-backed file
+page-cache pages.
+
+Several sk_msg transform paths move, copy, split, or compact
+msg->sg.data[] entries without moving the matching sg.copy bit. This can
+make an externally backed entry arrive at a new slot with a clear copy
+bit. A later SK_MSG verdict can then expose sg_virt(sge) as writable
+ctx->data and BPF stores can modify the original page cache.
+
+Keep sg.copy synchronized with sg.data[] whenever entries are
+transferred, shifted, split, or copied into a new sk_msg. Clear the bit
+when an entry is replaced by a newly allocated private page or freed.
+This covers the BPF pull/push/pop helpers, sk_msg_shift_left/right(),
+sk_msg_xfer(), and tls_split_open_record(), including the partial tail
+entry created during TLS open-record splitting.
+
+Fixes: d3b18ad31f93 ("tls: add bpf support to sk_msg handling")
+Cc: stable@vger.kernel.org
+Reported-by: Yiming Qian <yimingqian591@gmail.com>
+Reported-by: Keenan Dong <keenanat2000@gmail.com>
+Signed-off-by: Yiming Qian <yimingqian591@gmail.com>
+Link: https://patch.msgid.link/20260610062137.49075-1-yimingqian591@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/skmsg.h |   15 +++++++++++----
+ net/core/filter.c     |   27 +++++++++++++++++++++++++++
+ net/core/skmsg.c      |    2 ++
+ net/tls/tls_sw.c      |    4 ++++
+ 4 files changed, 44 insertions(+), 4 deletions(-)
+
+--- a/include/linux/skmsg.h
++++ b/include/linux/skmsg.h
+@@ -4,6 +4,7 @@
+ #ifndef _LINUX_SKMSG_H
+ #define _LINUX_SKMSG_H
++#include <linux/bitops.h>
+ #include <linux/bpf.h>
+ #include <linux/filter.h>
+ #include <linux/scatterlist.h>
+@@ -187,11 +188,14 @@ static inline void sk_msg_xfer(struct sk
+                              int which, u32 size)
+ {
+       dst->sg.data[which] = src->sg.data[which];
++      __assign_bit(which, dst->sg.copy, test_bit(which, src->sg.copy));
+       dst->sg.data[which].length  = size;
+       dst->sg.size               += size;
+       src->sg.size               -= size;
+       src->sg.data[which].length -= size;
+       src->sg.data[which].offset += size;
++      if (!src->sg.data[which].length)
++              __clear_bit(which, src->sg.copy);
+ }
+ static inline void sk_msg_xfer_full(struct sk_msg *dst, struct sk_msg *src)
+@@ -261,16 +265,19 @@ static inline void sk_msg_page_add(struc
+ static inline void sk_msg_sg_copy(struct sk_msg *msg, u32 i, bool copy_state)
+ {
+       do {
+-              if (copy_state)
+-                      __set_bit(i, msg->sg.copy);
+-              else
+-                      __clear_bit(i, msg->sg.copy);
++              __assign_bit(i, msg->sg.copy, copy_state);
+               sk_msg_iter_var_next(i);
+               if (i == msg->sg.end)
+                       break;
+       } while (1);
+ }
++static inline void sk_msg_sg_copy_assign(struct sk_msg *dst, u32 dst_i,
++                                       const struct sk_msg *src, u32 src_i)
++{
++      __assign_bit(dst_i, dst->sg.copy, test_bit(src_i, src->sg.copy));
++}
++
+ static inline void sk_msg_sg_copy_set(struct sk_msg *msg, u32 start)
+ {
+       sk_msg_sg_copy(msg, start, true);
+--- a/net/core/filter.c
++++ b/net/core/filter.c
+@@ -2718,11 +2718,13 @@ BPF_CALL_4(bpf_msg_pull_data, struct sk_
+               poffset += len;
+               sge->length = 0;
+               put_page(sg_page(sge));
++              __clear_bit(i, msg->sg.copy);
+               sk_msg_iter_var_next(i);
+       } while (i != last_sge);
+       sg_set_page(&msg->sg.data[first_sge], page, copy, 0);
++      __clear_bit(first_sge, msg->sg.copy);
+       /* To repair sg ring we need to shift entries. If we only
+        * had a single entry though we can just replace it and
+@@ -2748,9 +2750,11 @@ BPF_CALL_4(bpf_msg_pull_data, struct sk_
+                       break;
+               msg->sg.data[i] = msg->sg.data[move_from];
++              sk_msg_sg_copy_assign(msg, i, msg, move_from);
+               msg->sg.data[move_from].length = 0;
+               msg->sg.data[move_from].page_link = 0;
+               msg->sg.data[move_from].offset = 0;
++              __clear_bit(move_from, msg->sg.copy);
+               sk_msg_iter_var_next(i);
+       } while (1);
+@@ -2779,6 +2783,7 @@ BPF_CALL_4(bpf_msg_push_data, struct sk_
+ {
+       struct scatterlist sge, nsge, nnsge, rsge = {0}, *psge;
+       u32 new, i = 0, l = 0, space, copy = 0, offset = 0;
++      bool sge_copy, nsge_copy, nnsge_copy, rsge_copy = false;
+       u8 *raw, *to, *from;
+       struct page *page;
+@@ -2851,6 +2856,7 @@ BPF_CALL_4(bpf_msg_push_data, struct sk_
+                       sk_msg_iter_var_prev(i);
+               psge = sk_msg_elem(msg, i);
+               rsge = sk_msg_elem_cpy(msg, i);
++              rsge_copy = test_bit(i, msg->sg.copy);
+               psge->length = start - offset;
+               rsge.length -= psge->length;
+@@ -2875,24 +2881,32 @@ BPF_CALL_4(bpf_msg_push_data, struct sk_
+       /* Shift one or two slots as needed */
+       sge = sk_msg_elem_cpy(msg, new);
++      sge_copy = test_bit(new, msg->sg.copy);
+       sg_unmark_end(&sge);
+       nsge = sk_msg_elem_cpy(msg, i);
++      nsge_copy = test_bit(i, msg->sg.copy);
+       if (rsge.length) {
+               sk_msg_iter_var_next(i);
+               nnsge = sk_msg_elem_cpy(msg, i);
++              nnsge_copy = test_bit(i, msg->sg.copy);
+               sk_msg_iter_next(msg, end);
+       }
+       while (i != msg->sg.end) {
+               msg->sg.data[i] = sge;
++              __assign_bit(i, msg->sg.copy, sge_copy);
+               sge = nsge;
++              sge_copy = nsge_copy;
+               sk_msg_iter_var_next(i);
+               if (rsge.length) {
+                       nsge = nnsge;
++                      nsge_copy = nnsge_copy;
+                       nnsge = sk_msg_elem_cpy(msg, i);
++                      nnsge_copy = test_bit(i, msg->sg.copy);
+               } else {
+                       nsge = sk_msg_elem_cpy(msg, i);
++                      nsge_copy = test_bit(i, msg->sg.copy);
+               }
+       }
+@@ -2906,6 +2920,7 @@ place_new:
+               get_page(sg_page(&rsge));
+               sk_msg_iter_var_next(new);
+               msg->sg.data[new] = rsge;
++              __assign_bit(new, msg->sg.copy, rsge_copy);
+       }
+       sk_msg_reset_curr(msg);
+@@ -2933,25 +2948,33 @@ static void sk_msg_shift_left(struct sk_
+               prev = i;
+               sk_msg_iter_var_next(i);
+               msg->sg.data[prev] = msg->sg.data[i];
++              sk_msg_sg_copy_assign(msg, prev, msg, i);
+       } while (i != msg->sg.end);
+       sk_msg_iter_prev(msg, end);
++      __clear_bit(msg->sg.end, msg->sg.copy);
+ }
+ static void sk_msg_shift_right(struct sk_msg *msg, int i)
+ {
+       struct scatterlist tmp, sge;
++      bool tmp_copy, sge_copy;
+       sk_msg_iter_next(msg, end);
+       sge = sk_msg_elem_cpy(msg, i);
++      sge_copy = test_bit(i, msg->sg.copy);
+       sk_msg_iter_var_next(i);
+       tmp = sk_msg_elem_cpy(msg, i);
++      tmp_copy = test_bit(i, msg->sg.copy);
+       while (i != msg->sg.end) {
+               msg->sg.data[i] = sge;
++              __assign_bit(i, msg->sg.copy, sge_copy);
+               sk_msg_iter_var_next(i);
+               sge = tmp;
++              sge_copy = tmp_copy;
+               tmp = sk_msg_elem_cpy(msg, i);
++              tmp_copy = test_bit(i, msg->sg.copy);
+       }
+ }
+@@ -3011,6 +3034,8 @@ BPF_CALL_4(bpf_msg_pop_data, struct sk_m
+               struct scatterlist *nsge, *sge = sk_msg_elem(msg, i);
+               int a = start - offset;
+               int b = sge->length - pop - a;
++              u32 sge_i = i;
++              bool sge_copy = test_bit(i, msg->sg.copy);
+               sk_msg_iter_var_next(i);
+@@ -3023,6 +3048,7 @@ BPF_CALL_4(bpf_msg_pop_data, struct sk_m
+                               sg_set_page(nsge,
+                                           sg_page(sge),
+                                           b, sge->offset + pop + a);
++                              __assign_bit(i, msg->sg.copy, sge_copy);
+                       } else {
+                               struct page *page, *orig;
+                               u8 *to, *from;
+@@ -3039,6 +3065,7 @@ BPF_CALL_4(bpf_msg_pop_data, struct sk_m
+                               memcpy(to, from, a);
+                               memcpy(to + a, from + a + pop, b);
+                               sg_set_page(sge, page, a + b, 0);
++                              __clear_bit(sge_i, msg->sg.copy);
+                               put_page(orig);
+                       }
+                       pop = 0;
+--- a/net/core/skmsg.c
++++ b/net/core/skmsg.c
+@@ -65,6 +65,7 @@ int sk_msg_alloc(struct sock *sk, struct
+                       sge = &msg->sg.data[msg->sg.end];
+                       sg_unmark_end(sge);
+                       sg_set_page(sge, pfrag->page, use, orig_offset);
++                      __clear_bit(msg->sg.end, msg->sg.copy);
+                       get_page(pfrag->page);
+                       sk_msg_iter_next(msg, end);
+               }
+@@ -185,6 +186,7 @@ static int sk_msg_free_elem(struct sock
+                       sk_mem_uncharge(sk, len);
+               put_page(sg_page(sge));
+       }
++      __clear_bit(i, msg->sg.copy);
+       memset(sge, 0, sizeof(*sge));
+       return len;
+ }
+--- a/net/tls/tls_sw.c
++++ b/net/tls/tls_sw.c
+@@ -564,6 +564,7 @@ static int tls_split_open_record(struct
+       struct scatterlist *sge, *osge, *nsge;
+       u32 orig_size = msg_opl->sg.size;
+       struct scatterlist tmp = { };
++      u32 tmp_i = 0;
+       struct sk_msg *msg_npl;
+       struct tls_rec *new;
+       int ret;
+@@ -585,6 +586,7 @@ static int tls_split_open_record(struct
+               if (sge->length > apply) {
+                       u32 len = sge->length - apply;
++                      tmp_i = i;
+                       get_page(sg_page(sge));
+                       sg_set_page(&tmp, sg_page(sge), len,
+                                   sge->offset + apply);
+@@ -616,6 +618,7 @@ static int tls_split_open_record(struct
+       nsge = sk_msg_elem(msg_npl, j);
+       if (tmp.length) {
+               memcpy(nsge, &tmp, sizeof(*nsge));
++              sk_msg_sg_copy_assign(msg_npl, j, msg_opl, tmp_i);
+               sk_msg_iter_var_next(j);
+               nsge = sk_msg_elem(msg_npl, j);
+       }
+@@ -623,6 +626,7 @@ static int tls_split_open_record(struct
+       osge = sk_msg_elem(msg_opl, i);
+       while (osge->length) {
+               memcpy(nsge, osge, sizeof(*nsge));
++              sk_msg_sg_copy_assign(msg_npl, j, msg_opl, i);
+               sg_unmark_end(nsge);
+               sk_msg_iter_var_next(i);
+               sk_msg_iter_var_next(j);
diff --git a/queue-5.10/nfsv4-flexfiles-reject-zero-filehandle-version-count.patch b/queue-5.10/nfsv4-flexfiles-reject-zero-filehandle-version-count.patch
new file mode 100644 (file)
index 0000000..9ab6c9e
--- /dev/null
@@ -0,0 +1,58 @@
+From stable+bounces-272073-greg=kroah.com@vger.kernel.org Sun Jul  5 16:20:51 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun,  5 Jul 2026 10:20:39 -0400
+Subject: NFSv4/flexfiles: reject zero filehandle version count
+To: stable@vger.kernel.org
+Cc: Michael Bommarito <michael.bommarito@gmail.com>, Anna Schumaker <anna.schumaker@hammerspace.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260705142039.1791851-1-sashal@kernel.org>
+
+From: Michael Bommarito <michael.bommarito@gmail.com>
+
+[ Upstream commit 2c6bb3c40bc24f6aa8dfbe6fe98c3ad6389203f2 ]
+
+ff_layout_alloc_lseg() decodes the filehandle-version array count
+from the flexfiles layout body. The value is used as the count for
+kzalloc_objs(), and the current code only rejects NULL.
+
+A zero count yields ZERO_SIZE_PTR, which can be stored in
+dss_info->fh_versions even though later flexfiles paths assume that at
+least one filehandle version exists.
+
+Reject fh_count == 0 before the allocation, matching the existing zero
+version_count validation in the flexfiles GETDEVICEINFO parser.
+
+A QEMU/KASAN run with a malformed flexfiles layout hit:
+
+  KASAN: null-ptr-deref in range [0x0000000000000010-0x0000000000000017]
+  RIP: 0010:ff_layout_encode_ff_layoutupdate.isra.0+0x15f/0x750
+  ff_layout_encode_layoutreturn+0x683/0x970
+  nfs4_xdr_enc_layoutreturn+0x278/0x3a0
+  Kernel panic - not syncing: Fatal exception
+
+The patched kernel rejects the malformed layout without KASAN/oops/panic,
+and a valid fh_count=1 regression still opens, reads, and unmounts cleanly.
+
+Cc: stable@vger.kernel.org
+Fixes: d67ae825a59d ("pnfs/flexfiles: Add the FlexFile Layout Driver")
+Assisted-by: Claude:claude-opus-4-7
+Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
+Signed-off-by: Anna Schumaker <anna.schumaker@hammerspace.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfs/flexfilelayout/flexfilelayout.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/fs/nfs/flexfilelayout/flexfilelayout.c
++++ b/fs/nfs/flexfilelayout/flexfilelayout.c
+@@ -454,6 +454,10 @@ ff_layout_alloc_lseg(struct pnfs_layout_
+               if (!p)
+                       goto out_err_free;
+               fh_count = be32_to_cpup(p);
++              if (fh_count == 0) {
++                      rc = -EINVAL;
++                      goto out_err_free;
++              }
+               fls->mirror_array[i]->fh_versions =
+                       kcalloc(fh_count, sizeof(struct nfs_fh),
index 7fcf346a6caeb444ceac34dc54ac602656d4a284..05695438659fe367585c7eb314acdf090591fcad 100644 (file)
@@ -10,3 +10,22 @@ kvm-replace-guest-triggerable-bug_on-in-ioeventfd-da.patch
 perf-trace-beauty-fcntl-fix-build-with-older-kernel-headers.patch
 bus-mhi-host-add-alignment-check-for-event-ring-read-pointer.patch
 netfilter-nf_log-validate-mac-header-was-set-before-dumping-it.patch
+skmsg-convert-struct-sk_msg_sg-copy-to-a-bitmap.patch
+net-skmsg-preserve-sg.copy-across-sg-transforms.patch
+apparmor-fix-use-after-free-in-rawdata-dedup-loop.patch
+net-ip_gre-require-cap_net_admin-in-the-device-netns-for-changelink.patch
+apparmor-mediate-the-implicit-connect-of-tcp-fast-open-sendmsg.patch
+f2fs-adjust-zone-capacity-when-considering-valid-block-count.patch
+f2fs-fix-to-round-down-start-offset-of-fallocate-for-pin-file.patch
+f2fs-validate-orphan-inode-entry-count.patch
+f2fs-bound-i_inline_xattr_size-for-non-inline-xattr-inodes.patch
+f2fs-fix-potential-deadlock-in-f2fs_balance_fs.patch
+f2fs-fix-listxattr-handling-of-corrupted-xattr-entries.patch
+nfsv4-flexfiles-reject-zero-filehandle-version-count.patch
+fbdev-fbcon-fix-out-of-bounds-read-in-err_out-of-fbcon_do_set_font.patch
+i2c-core-fix-irq-domain-leak-on-adapter-registration-failure.patch
+i2c-core-fix-hang-on-adapter-registration-failure.patch
+i2c-core-fix-null-deref-on-adapter-registration-failure.patch
+i2c-core-fix-adapter-debugfs-creation.patch
+i2c-core-fix-adapter-registration-race.patch
+hdlc_ppp-sync-per-proto-timers-before-freeing-hdlc-state.patch
diff --git a/queue-5.10/skmsg-convert-struct-sk_msg_sg-copy-to-a-bitmap.patch b/queue-5.10/skmsg-convert-struct-sk_msg_sg-copy-to-a-bitmap.patch
new file mode 100644 (file)
index 0000000..e31e727
--- /dev/null
@@ -0,0 +1,96 @@
+From stable+bounces-270554-greg=kroah.com@vger.kernel.org Thu Jul  2 17:30:36 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu,  2 Jul 2026 11:26:22 -0400
+Subject: skmsg: convert struct sk_msg_sg::copy to a bitmap
+To: stable@vger.kernel.org
+Cc: Eric Dumazet <edumazet@google.com>, "David S. Miller" <davem@davemloft.net>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260702152623.3530248-1-sashal@kernel.org>
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 5a8fb33e530512ee67a11b30f3451a4f030f4b01 ]
+
+We have plans for increasing MAX_SKB_FRAGS, but sk_msg_sg::copy
+is currently an unsigned long, limiting MAX_SKB_FRAGS to 30 on 32bit arches.
+
+Convert it to a bitmap, as Jakub suggested.
+
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: 406e8a651a7b ("net: skmsg: preserve sg.copy across SG transforms")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/skmsg.h |   11 +++++------
+ net/core/filter.c     |    4 ++--
+ 2 files changed, 7 insertions(+), 8 deletions(-)
+
+--- a/include/linux/skmsg.h
++++ b/include/linux/skmsg.h
+@@ -29,7 +29,7 @@ struct sk_msg_sg {
+       u32                             end;
+       u32                             size;
+       u32                             copybreak;
+-      unsigned long                   copy;
++      DECLARE_BITMAP(copy, MAX_MSG_FRAGS + 2);
+       /* The extra two elements:
+        * 1) used for chaining the front and sections when the list becomes
+        *    partitioned (e.g. end < start). The crypto APIs require the
+@@ -38,7 +38,6 @@ struct sk_msg_sg {
+        */
+       struct scatterlist              data[MAX_MSG_FRAGS + 2];
+ };
+-static_assert(BITS_PER_LONG >= NR_MSG_FRAG_IDS);
+ /* UAPI in filter.c depends on struct sk_msg_sg being first element. */
+ struct sk_msg {
+@@ -235,7 +234,7 @@ static inline void sk_msg_compute_data_p
+ {
+       struct scatterlist *sge = sk_msg_elem(msg, msg->sg.start);
+-      if (test_bit(msg->sg.start, &msg->sg.copy)) {
++      if (test_bit(msg->sg.start, msg->sg.copy)) {
+               msg->data = NULL;
+               msg->data_end = NULL;
+       } else {
+@@ -254,7 +253,7 @@ static inline void sk_msg_page_add(struc
+       sg_set_page(sge, page, len, offset);
+       sg_unmark_end(sge);
+-      __set_bit(msg->sg.end, &msg->sg.copy);
++      __set_bit(msg->sg.end, msg->sg.copy);
+       msg->sg.size += len;
+       sk_msg_iter_next(msg, end);
+ }
+@@ -263,9 +262,9 @@ static inline void sk_msg_sg_copy(struct
+ {
+       do {
+               if (copy_state)
+-                      __set_bit(i, &msg->sg.copy);
++                      __set_bit(i, msg->sg.copy);
+               else
+-                      __clear_bit(i, &msg->sg.copy);
++                      __clear_bit(i, msg->sg.copy);
+               sk_msg_iter_var_next(i);
+               if (i == msg->sg.end)
+                       break;
+--- a/net/core/filter.c
++++ b/net/core/filter.c
+@@ -2677,7 +2677,7 @@ BPF_CALL_4(bpf_msg_pull_data, struct sk_
+        * account for the headroom.
+        */
+       bytes_sg_total = start - offset + bytes;
+-      if (!test_bit(i, &msg->sg.copy) && bytes_sg_total <= len)
++      if (!test_bit(i, msg->sg.copy) && bytes_sg_total <= len)
+               goto out;
+       /* At this point we need to linearize multiple scatterlist
+@@ -2900,7 +2900,7 @@ place_new:
+       /* Place newly allocated data buffer */
+       sk_mem_charge(msg->sk, len);
+       msg->sg.size += len;
+-      __clear_bit(new, &msg->sg.copy);
++      __clear_bit(new, msg->sg.copy);
+       sg_set_page(&msg->sg.data[new], page, len + copy, 0);
+       if (rsge.length) {
+               get_page(sg_page(&rsge));