]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
7.1-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 2 Jul 2026 13:14:48 +0000 (15:14 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 2 Jul 2026 13:14:48 +0000 (15:14 +0200)
added patches:
block-avoid-mounting-the-bdev-pseudo-filesystem-in-userspace.patch
bpf-use-kvfree-for-replaced-sysctl-write-buffer.patch
crypto-nx-fix-nx_crypto_ctx_exit-argument.patch
exfat-fix-potential-use-after-free-in-exfat_find_dir_entry.patch
f2fs-atomic-fix-uaf-issue-on-f2fs_inode_info.atomic_inode.patch
f2fs-bound-i_inline_xattr_size-for-non-inline-xattr-inodes.patch
f2fs-fix-incorrect-fi_no_extent-handling-in-__destroy_extent_node.patch
f2fs-fix-missing-read-bio-submission-on-large-folio-error.patch
f2fs-fix-to-do-sanity-check-on-f2fs_get_node_folio_ra.patch
f2fs-fix-to-round-down-start-offset-of-fallocate-for-pin-file.patch
f2fs-keep-atomic-write-retry-from-zeroing-original-data.patch
f2fs-pass-correct-iostat-type-for-single-node-writes.patch
f2fs-read-cow-data-with-the-original-inode-during-atomic-write.patch
f2fs-reject-setattr-size-changes-on-large-folio-files.patch
f2fs-validate-acl-entry-sizes-in-f2fs_acl_from_disk.patch
f2fs-validate-compress-cache-inode-only-when-enabled.patch
f2fs-validate-orphan-inode-entry-count.patch
kvm-replace-guest-triggerable-bug_on-in-ioeventfd-datamatch-with-get_unaligned.patch
kvm-x86-mmu-ensure-hugepage-is-in-by-slot-before-checking-max-mapping-level.patch
mips-dec-prevent-initial-console-buffer-from-landing-in-xkphys.patch
revert-f2fs-remove-non-uptodate-folio-from-the-page-cache-in-move_data_block.patch

22 files changed:
queue-7.1/block-avoid-mounting-the-bdev-pseudo-filesystem-in-userspace.patch [new file with mode: 0644]
queue-7.1/bpf-use-kvfree-for-replaced-sysctl-write-buffer.patch [new file with mode: 0644]
queue-7.1/crypto-nx-fix-nx_crypto_ctx_exit-argument.patch [new file with mode: 0644]
queue-7.1/exfat-fix-potential-use-after-free-in-exfat_find_dir_entry.patch [new file with mode: 0644]
queue-7.1/f2fs-atomic-fix-uaf-issue-on-f2fs_inode_info.atomic_inode.patch [new file with mode: 0644]
queue-7.1/f2fs-bound-i_inline_xattr_size-for-non-inline-xattr-inodes.patch [new file with mode: 0644]
queue-7.1/f2fs-fix-incorrect-fi_no_extent-handling-in-__destroy_extent_node.patch [new file with mode: 0644]
queue-7.1/f2fs-fix-missing-read-bio-submission-on-large-folio-error.patch [new file with mode: 0644]
queue-7.1/f2fs-fix-to-do-sanity-check-on-f2fs_get_node_folio_ra.patch [new file with mode: 0644]
queue-7.1/f2fs-fix-to-round-down-start-offset-of-fallocate-for-pin-file.patch [new file with mode: 0644]
queue-7.1/f2fs-keep-atomic-write-retry-from-zeroing-original-data.patch [new file with mode: 0644]
queue-7.1/f2fs-pass-correct-iostat-type-for-single-node-writes.patch [new file with mode: 0644]
queue-7.1/f2fs-read-cow-data-with-the-original-inode-during-atomic-write.patch [new file with mode: 0644]
queue-7.1/f2fs-reject-setattr-size-changes-on-large-folio-files.patch [new file with mode: 0644]
queue-7.1/f2fs-validate-acl-entry-sizes-in-f2fs_acl_from_disk.patch [new file with mode: 0644]
queue-7.1/f2fs-validate-compress-cache-inode-only-when-enabled.patch [new file with mode: 0644]
queue-7.1/f2fs-validate-orphan-inode-entry-count.patch [new file with mode: 0644]
queue-7.1/kvm-replace-guest-triggerable-bug_on-in-ioeventfd-datamatch-with-get_unaligned.patch [new file with mode: 0644]
queue-7.1/kvm-x86-mmu-ensure-hugepage-is-in-by-slot-before-checking-max-mapping-level.patch [new file with mode: 0644]
queue-7.1/mips-dec-prevent-initial-console-buffer-from-landing-in-xkphys.patch [new file with mode: 0644]
queue-7.1/revert-f2fs-remove-non-uptodate-folio-from-the-page-cache-in-move_data_block.patch [new file with mode: 0644]
queue-7.1/series

diff --git a/queue-7.1/block-avoid-mounting-the-bdev-pseudo-filesystem-in-userspace.patch b/queue-7.1/block-avoid-mounting-the-bdev-pseudo-filesystem-in-userspace.patch
new file mode 100644 (file)
index 0000000..556f492
--- /dev/null
@@ -0,0 +1,76 @@
+From f73aa66dffcb8e61e78f01b56163ec16a15d06d2 Mon Sep 17 00:00:00 2001
+From: Denis Arefev <arefev@swemel.ru>
+Date: Thu, 21 May 2026 10:28:56 +0300
+Subject: block: Avoid mounting the bdev pseudo-filesystem in userspace
+
+From: Denis Arefev <arefev@swemel.ru>
+
+commit f73aa66dffcb8e61e78f01b56163ec16a15d06d2 upstream.
+
+The bdev pseudo-filesystem is an internal kernel filesystem with which
+userspace should not interfere. Unregister it so that userspace cannot
+even attempt to mount it.
+
+This fixes a bug [1] that occurs when attempting to access files,
+because the system call move_mount() uses pointers declared in the
+inode_operations structure, which for the bdev pseudo-filesystem
+are always equal to 0. `inode->i_op = &empty_iops;`
+
+[1]
+
+ BUG: kernel NULL pointer dereference, address: 0000000000000000
+ #PF: supervisor instruction fetch in kernel mode
+ #PF: error_code(0x0010) - not-present page
+ PGD 23380067 P4D 23380067 PUD 23381067 PMD 0
+ Oops: 0010 [#1] PREEMPT SMP KASAN NOPTI
+ CPU: 2 PID: 17125 Comm: syz-executor.0 Not tainted 6.1.155-syzkaller-00350-g84221fde2681 #0
+ Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-1 04/01/2014
+ RIP: 0010:0x0
+
+ Call Trace:
+ <TASK>
+ lookup_open.isra.0+0x700/0x1180 fs/namei.c:3460
+ open_last_lookups fs/namei.c:3550 [inline]
+ path_openat+0x953/0x2700 fs/namei.c:3780
+ do_filp_open+0x1c5/0x410 fs/namei.c:3810
+ do_sys_openat2+0x171/0x4d0 fs/open.c:1318
+ do_sys_open fs/open.c:1334 [inline]
+ __do_sys_openat fs/open.c:1350 [inline]
+ __se_sys_openat fs/open.c:1345 [inline]
+ __x64_sys_openat+0x13c/0x1f0 fs/open.c:1345
+ do_syscall_x64 arch/x86/entry/common.c:51 [inline]
+ do_syscall_64+0x35/0x80 arch/x86/entry/common.c:81
+ entry_SYSCALL_64_after_hwframe+0x6e/0xd8
+
+Found by Linux Verification Center (linuxtesting.org) with Syzkaller.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Link: https://lore.kernel.org/all/20131010004732.GJ13318@ZenIV.linux.org.uk/T/#
+Cc: stable@vger.kernel.org
+Signed-off-by: Denis Arefev <arefev@swemel.ru>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Link: https://patch.msgid.link/20260521072857.5078-1-arefev@swemel.ru
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ block/bdev.c |    5 -----
+ 1 file changed, 5 deletions(-)
+
+--- a/block/bdev.c
++++ b/block/bdev.c
+@@ -446,15 +446,10 @@ EXPORT_SYMBOL_GPL(blockdev_superblock);
+ void __init bdev_cache_init(void)
+ {
+-      int err;
+-
+       bdev_cachep = kmem_cache_create("bdev_cache", sizeof(struct bdev_inode),
+                       0, (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|
+                               SLAB_ACCOUNT|SLAB_PANIC),
+                       init_once);
+-      err = register_filesystem(&bd_type);
+-      if (err)
+-              panic("Cannot register bdev pseudo-fs");
+       blockdev_mnt = kern_mount(&bd_type);
+       if (IS_ERR(blockdev_mnt))
+               panic("Cannot create bdev pseudo-fs");
diff --git a/queue-7.1/bpf-use-kvfree-for-replaced-sysctl-write-buffer.patch b/queue-7.1/bpf-use-kvfree-for-replaced-sysctl-write-buffer.patch
new file mode 100644 (file)
index 0000000..4ab8538
--- /dev/null
@@ -0,0 +1,89 @@
+From 4c21b5927d4364bfe7365f2700da5fea0ed0d004 Mon Sep 17 00:00:00 2001
+From: Dawei Feng <dawei.feng@seu.edu.cn>
+Date: Wed, 3 Jun 2026 18:53:16 +0800
+Subject: bpf: use kvfree() for replaced sysctl write buffer
+
+From: Dawei Feng <dawei.feng@seu.edu.cn>
+
+commit 4c21b5927d4364bfe7365f2700da5fea0ed0d004 upstream.
+
+proc_sys_call_handler() allocates its temporary sysctl buffer with
+kvzalloc() and passes it to __cgroup_bpf_run_filter_sysctl(). Since
+kvzalloc() may fall back to vmalloc() for large allocations, freeing
+that buffer with kfree() is wrong and can corrupt memory.
+
+Use kvfree() to safely handle both kmalloc and kvzalloc()/vmalloc
+allocations.
+
+The bug was first flagged by an experimental analysis tool we are
+developing for kernel memory-management bugs while analyzing
+v6.13-rc1. The tool is still under development and is not yet publicly
+available. Manual inspection confirms that the bug is still
+present in v7.1-rc5.
+
+Reproduced the bug based on v7.1-rc4 in a QEMU x86_64 guest booted with
+KASAN and CONFIG_FAILSLAB enabled. To exercise the replacement path, the
+test tree also included the accompanying fix for the stale ret == 1
+check in __cgroup_bpf_run_filter_sysctl(). The reproducer confines
+failslab injections to the proc_sys_call_handler() range, uses
+stacktrace-depth=32, and injects fail-nth=1 while writing 8191 bytes to
+/proc/sys/kernel/domainname from a task in the target cgroup. Under
+that setup, fail-nth=1 triggered the fault:
+
+  BUG: unable to handle page fault for address: ffffeb0200024d48
+  #PF: supervisor read access in kernel mode
+  #PF: error_code(0x0000) - not-present page
+  PGD 0 P4D 0
+  Oops: Oops: 0000  SMP KASAN NOPTI
+  CPU: 2 UID: 0 PID: 209 Comm: repro_proc_sys_ Not tainted 7.1.0-rc4-00686-g97625979a5d4  PREEMPT(lazy)
+  Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.15.0-1 04/01/2014
+  RIP: 0010:kfree+0x6e/0x510
+  ...
+  Call Trace:
+   <TASK>
+   ? __cgroup_bpf_run_filter_sysctl+0x626/0xc30
+   __cgroup_bpf_run_filter_sysctl+0x74d/0xc30
+   ? __pfx___cgroup_bpf_run_filter_sysctl+0x10/0x10
+   ? srso_return_thunk+0x5/0x5f
+   ? __kvmalloc_node_noprof+0x345/0x870
+   ? proc_sys_call_handler+0x250/0x480
+   ? srso_return_thunk+0x5/0x5f
+   proc_sys_call_handler+0x3a2/0x480
+   ? __pfx_proc_sys_call_handler+0x10/0x10
+   ? srso_return_thunk+0x5/0x5f
+   ? selinux_file_permission+0x39f/0x500
+   ? srso_return_thunk+0x5/0x5f
+   ? lock_is_held_type+0x9e/0x120
+   vfs_write+0x98e/0x1000
+   ...
+   </TASK>
+
+With this fix applied on top of the same test setup, rerunning the
+reproducer with fail-nth=1 yields no corresponding Oops reports.
+
+Fixes: 4508943794ef ("proc: use kvzalloc for our kernel buffer")
+Cc: stable@vger.kernel.org
+
+Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
+Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev>
+Acked-by: Yonghong Song <yonghong.song@linux.dev>
+Signed-off-by: Zilin Guan <zilin@seu.edu.cn>
+Signed-off-by: Dawei Feng <dawei.feng@seu.edu.cn>
+Link: https://lore.kernel.org/r/20260603105317.944304-3-dawei.feng@seu.edu.cn
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/bpf/cgroup.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/kernel/bpf/cgroup.c
++++ b/kernel/bpf/cgroup.c
+@@ -1936,7 +1936,7 @@ int __cgroup_bpf_run_filter_sysctl(struc
+       kfree(ctx.cur_val);
+       if (ret == 1 && ctx.new_updated) {
+-              kfree(*buf);
++              kvfree(*buf);
+               *buf = ctx.new_val;
+               *pcount = ctx.new_len;
+       } else {
diff --git a/queue-7.1/crypto-nx-fix-nx_crypto_ctx_exit-argument.patch b/queue-7.1/crypto-nx-fix-nx_crypto_ctx_exit-argument.patch
new file mode 100644 (file)
index 0000000..fe77e0c
--- /dev/null
@@ -0,0 +1,90 @@
+From 4e67f504ee9ded15e256b64f4fde150e917381d7 Mon Sep 17 00:00:00 2001
+From: Sam James <sam@gentoo.org>
+Date: Mon, 25 May 2026 08:56:19 +0100
+Subject: crypto: nx - fix nx_crypto_ctx_exit argument
+
+From: Sam James <sam@gentoo.org>
+
+commit 4e67f504ee9ded15e256b64f4fde150e917381d7 upstream.
+
+nx_crypto_ctx_shash_exit calls nx_crypto_ctx_exit with crypto_shash_ctx(...)
+but crypto_shash_ctx gives a nx_crypto_ctx *, not a crypto_tfm *.
+
+Fix the type in nx_crypto_ctx_exit and drop the bogus crypto_tfm_ctx
+call.
+
+This fixes the following oops:
+
+  BUG: Unable to handle kernel data access at 0xc0403effffffffc8
+  Faulting instruction address: 0xc000000000396cb4
+  Oops: Kernel access of bad area, sig: 11 [#15]
+  Call Trace:
+   nx_crypto_ctx_shash_exit+0x24/0x60
+   crypto_shash_exit_tfm+0x28/0x40
+   crypto_destroy_tfm+0x98/0x140
+   crypto_exit_ahash_using_shash+0x20/0x40
+   crypto_destroy_tfm+0x98/0x140
+   hash_release+0x1c/0x30
+   alg_sock_destruct+0x38/0x60
+   __sk_destruct+0x48/0x2b0
+   af_alg_release+0x58/0xb0
+   __sock_release+0x68/0x150
+   sock_close+0x20/0x40
+   __fput+0x110/0x3a0
+   sys_close+0x48/0xa0
+   system_call_exception+0x140/0x2d0
+   system_call_common+0xf4/0x258
+
+.. which came from hardlink(1) opportunistically using AF_ALG.
+
+The same problem exists with nx_crypto_ctx_skcipher_exit getting a context
+it wasn't expecting, but apparently nobody hit that for years.
+
+Cc: Eric Biggers <ebiggers@kernel.org>
+Cc: stable@vger.kernel.org
+Fixes: bfd9efddf990 ("crypto: nx - convert AES-ECB to skcipher API")
+Fixes: 9420e628e7d8 ("crypto: nx - Use API partial block handling")
+Acked-by: Breno Leitao <leitao@debian.org>
+Reviewed-by: Eric Biggers <ebiggers@kernel.org>
+Reported-by: Calvin Buckley <calvin@cmpct.info>
+Tested-by: Calvin Buckley <calvin@cmpct.info>
+Suggested-by: Brad Spengler <brad.spengler@opensrcsec.com>
+Signed-off-by: Sam James <sam@gentoo.org>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/crypto/nx/nx.c |    6 ++----
+ drivers/crypto/nx/nx.h |    2 +-
+ 2 files changed, 3 insertions(+), 5 deletions(-)
+
+--- a/drivers/crypto/nx/nx.c
++++ b/drivers/crypto/nx/nx.c
+@@ -714,15 +714,13 @@ int nx_crypto_ctx_aes_xcbc_init(struct c
+ /**
+  * nx_crypto_ctx_exit - destroy a crypto api context
+  *
+- * @tfm: the crypto transform pointer for the context
++ * @nx_ctx: the crypto api context
+  *
+  * As crypto API contexts are destroyed, this exit hook is called to free the
+  * memory associated with it.
+  */
+-void nx_crypto_ctx_exit(struct crypto_tfm *tfm)
++void nx_crypto_ctx_exit(struct nx_crypto_ctx *nx_ctx)
+ {
+-      struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(tfm);
+-
+       kfree_sensitive(nx_ctx->kmem);
+       nx_ctx->csbcpb = NULL;
+       nx_ctx->csbcpb_aead = NULL;
+--- a/drivers/crypto/nx/nx.h
++++ b/drivers/crypto/nx/nx.h
+@@ -153,7 +153,7 @@ int nx_crypto_ctx_aes_ctr_init(struct cr
+ int nx_crypto_ctx_aes_cbc_init(struct crypto_skcipher *tfm);
+ int nx_crypto_ctx_aes_ecb_init(struct crypto_skcipher *tfm);
+ int nx_crypto_ctx_sha_init(struct crypto_shash *tfm);
+-void nx_crypto_ctx_exit(struct crypto_tfm *tfm);
++void nx_crypto_ctx_exit(struct nx_crypto_ctx *nx_ctx);
+ void nx_crypto_ctx_skcipher_exit(struct crypto_skcipher *tfm);
+ void nx_crypto_ctx_aead_exit(struct crypto_aead *tfm);
+ void nx_crypto_ctx_shash_exit(struct crypto_shash *tfm);
diff --git a/queue-7.1/exfat-fix-potential-use-after-free-in-exfat_find_dir_entry.patch b/queue-7.1/exfat-fix-potential-use-after-free-in-exfat_find_dir_entry.patch
new file mode 100644 (file)
index 0000000..d0aac0f
--- /dev/null
@@ -0,0 +1,90 @@
+From 3f5f8ee9917cc2b9076ac533492d8a200edcabb8 Mon Sep 17 00:00:00 2001
+From: Michael Bommarito <michael.bommarito@gmail.com>
+Date: Wed, 22 Apr 2026 11:58:44 -0400
+Subject: exfat: fix potential use-after-free in exfat_find_dir_entry()
+
+From: Michael Bommarito <michael.bommarito@gmail.com>
+
+commit 3f5f8ee9917cc2b9076ac533492d8a200edcabb8 upstream.
+
+In exfat_find_dir_entry(), the buffer_head obtained from
+exfat_get_dentry() is released with brelse(bh) before the fall-through
+TYPE_EXTEND branch reads the directory entry through ep (which points
+into bh->b_data):
+
+       brelse(bh);
+       if (entry_type == TYPE_EXTEND) {
+               ...
+               len = exfat_extract_uni_name(ep, entry_uniname);
+               ...
+       }
+
+After brelse() drops our reference, nothing guarantees that the
+underlying page backing bh->b_data remains valid for the subsequent
+exfat_extract_uni_name() read. This is the same pattern fixed in
+commit fc961522ddbd ("exfat: Fix potential use after free in
+exfat_load_upcase_table()").
+
+Move brelse(bh) so it runs after ep is no longer dereferenced on
+each branch.
+
+Confirmed on QEMU x86_64 with CONFIG_KASAN=y + CONFIG_DEBUG_PAGEALLOC=y
++ CONFIG_PAGE_POISONING=y on linux-next, using a crafted exFAT image
+(long filename with same-hash collisions forcing the TYPE_EXTEND path).
+With a debug-only invalidate_bdev() inserted between brelse(bh) and
+the ep read to make the stale-deref window deterministic, the
+unpatched kernel faults:
+
+  BUG: KASAN: use-after-free in exfat_find_dir_entry+0x133b/0x15a0
+  BUG: unable to handle page fault for address: ffff88801a5fa0c2
+  Oops: 0000 [#1] SMP DEBUG_PAGEALLOC KASAN NOPTI
+  RIP: 0010:exfat_find_dir_entry+0x1188/0x15a0
+
+With this patch applied, the same instrumented harness completes
+cleanly under the same sanitizer stack. I have not reproduced a
+crash on an uninstrumented kernel under ordinary reclaim; the
+instrumented A/B establishes the lifetime violation and that the
+patch closes it, not an unaided triggerability claim.
+
+Fixes: ca06197382bd ("exfat: add directory operations")
+Cc: stable@vger.kernel.org
+Assisted-by: Claude:claude-opus-4-7
+Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
+Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/exfat/dir.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/fs/exfat/dir.c
++++ b/fs/exfat/dir.c
+@@ -1027,12 +1027,12 @@ rewind:
+                               continue;
+                       }
+-                      brelse(bh);
+                       if (entry_type == TYPE_EXTEND) {
+                               unsigned short entry_uniname[16], unichar;
+                               if (step != DIRENT_STEP_NAME ||
+                                   name_len >= MAX_NAME_LENGTH) {
++                                      brelse(bh);
+                                       step = DIRENT_STEP_FILE;
+                                       continue;
+                               }
+@@ -1043,6 +1043,7 @@ rewind:
+                                       uniname += EXFAT_FILE_NAME_LEN;
+                               len = exfat_extract_uni_name(ep, entry_uniname);
++                              brelse(bh);
+                               name_len += len;
+                               unichar = *(uniname+len);
+@@ -1061,6 +1062,7 @@ rewind:
+                               continue;
+                       }
++                      brelse(bh);
+                       if (entry_type &
+                                       (TYPE_CRITICAL_SEC | TYPE_BENIGN_SEC)) {
+                               if (step == DIRENT_STEP_SECD) {
diff --git a/queue-7.1/f2fs-atomic-fix-uaf-issue-on-f2fs_inode_info.atomic_inode.patch b/queue-7.1/f2fs-atomic-fix-uaf-issue-on-f2fs_inode_info.atomic_inode.patch
new file mode 100644 (file)
index 0000000..b324736
--- /dev/null
@@ -0,0 +1,164 @@
+From e0288584baa5dc41df4a829a023c4c1b33fe53d7 Mon Sep 17 00:00:00 2001
+From: Chao Yu <chao@kernel.org>
+Date: Thu, 21 May 2026 10:15:05 +0800
+Subject: f2fs: atomic: fix UAF issue on f2fs_inode_info.atomic_inode
+
+From: Chao Yu <chao@kernel.org>
+
+commit e0288584baa5dc41df4a829a023c4c1b33fe53d7 upstream.
+
+- ioctl(F2FS_IOC_GARBAGE_COLLECT_RANGE)                - shrink
+ - f2fs_gc
+  - gc_data_segment
+   - ra_data_block(cow_inode)
+    - mapping = F2FS_I(inode)->atomic_inode->i_mapping
+    : f2fs_is_cow_file(cow_inode) is true
+                                                - f2fs_evict_inode(atomic_inode)
+                                                 - clear_inode_flag(fi->cow_inode, FI_COW_FILE)
+                                                 - F2FS_I(fi->cow_inode)->atomic_inode = NULL
+                                                 ...
+                                                 - truncate_inode_pages_final(atomic_inode)
+    - f2fs_grab_cache_folio(mapping)
+    : create folio in atomic_inode->mapping
+                                                 - clear_inode(atomic_inode)
+                                                  - BUG_ON(atomic_inode->i_data.nrpages)
+
+We need to add a reference on fi->atomic_inode before using its mapping
+field during garbage collection, otherwise, it will cause UAF issue.
+
+Cc: stable@kernel.org
+Cc: Daeho Jeong <daehojeong@google.com>
+Cc: Sunmin Jeong <s_min.jeong@samsung.com>
+Fixes: 3db1de0e582c ("f2fs: change the current atomic write way")
+Fixes: f18d00769336 ("f2fs: use meta inode for GC of COW file")
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/gc.c    |   50 ++++++++++++++++++++++++++++++++++++++++++--------
+ fs/f2fs/inode.c |   11 ++++++++---
+ 2 files changed, 50 insertions(+), 11 deletions(-)
+
+--- a/fs/f2fs/gc.c
++++ b/fs/f2fs/gc.c
+@@ -1220,8 +1220,8 @@ static bool is_alive(struct f2fs_sb_info
+ static int ra_data_block(struct inode *inode, pgoff_t index)
+ {
+       struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
+-      struct address_space *mapping = f2fs_is_cow_file(inode) ?
+-                              F2FS_I(inode)->atomic_inode->i_mapping : inode->i_mapping;
++      struct address_space *mapping = inode->i_mapping;
++      struct inode *atomic_inode = NULL;
+       struct dnode_of_data dn;
+       struct folio *folio, *efolio;
+       struct f2fs_io_info fio = {
+@@ -1236,9 +1236,22 @@ static int ra_data_block(struct inode *i
+       };
+       int err = 0;
++      f2fs_down_read(&F2FS_I(inode)->i_sem);
++      if (f2fs_is_cow_file(inode)) {
++              atomic_inode = igrab(F2FS_I(inode)->atomic_inode);
++              if (!atomic_inode) {
++                      f2fs_up_read(&F2FS_I(inode)->i_sem);
++                      return -EBUSY;
++              }
++              mapping = atomic_inode->i_mapping;
++      }
++      f2fs_up_read(&F2FS_I(inode)->i_sem);
++
+       folio = f2fs_grab_cache_folio(mapping, index, true);
+-      if (IS_ERR(folio))
+-              return PTR_ERR(folio);
++      if (IS_ERR(folio)) {
++              err = PTR_ERR(folio);
++              goto out_iput;
++      }
+       if (f2fs_lookup_read_extent_cache_block(inode, index,
+                                               &dn.data_blkaddr)) {
+@@ -1299,11 +1312,16 @@ got_it:
+       f2fs_update_iostat(sbi, inode, FS_DATA_READ_IO, F2FS_BLKSIZE);
+       f2fs_update_iostat(sbi, NULL, FS_GDATA_READ_IO, F2FS_BLKSIZE);
++      if (atomic_inode)
++              iput(atomic_inode);
+       return 0;
+ put_encrypted_page:
+       f2fs_put_page(fio.encrypted_page, true);
+ put_folio:
+       f2fs_folio_put(folio, true);
++out_iput:
++      if (atomic_inode)
++              iput(atomic_inode);
+       return err;
+ }
+@@ -1314,8 +1332,8 @@ put_folio:
+ static int move_data_block(struct inode *inode, block_t bidx,
+                               int gc_type, unsigned int segno, int off)
+ {
+-      struct address_space *mapping = f2fs_is_cow_file(inode) ?
+-                              F2FS_I(inode)->atomic_inode->i_mapping : inode->i_mapping;
++      struct address_space *mapping = inode->i_mapping;
++      struct inode *atomic_inode = NULL;
+       struct f2fs_io_info fio = {
+               .sbi = F2FS_I_SB(inode),
+               .ino = inode->i_ino,
+@@ -1337,10 +1355,23 @@ static int move_data_block(struct inode
+                               (fio.sbi->gc_mode != GC_URGENT_HIGH) ?
+                               CURSEG_ALL_DATA_ATGC : CURSEG_COLD_DATA;
++      f2fs_down_read(&F2FS_I(inode)->i_sem);
++      if (f2fs_is_cow_file(inode)) {
++              atomic_inode = igrab(F2FS_I(inode)->atomic_inode);
++              if (!atomic_inode) {
++                      f2fs_up_read(&F2FS_I(inode)->i_sem);
++                      return -EBUSY;
++              }
++              mapping = atomic_inode->i_mapping;
++      }
++      f2fs_up_read(&F2FS_I(inode)->i_sem);
++
+       /* do not read out */
+       folio = f2fs_grab_cache_folio(mapping, bidx, false);
+-      if (IS_ERR(folio))
+-              return PTR_ERR(folio);
++      if (IS_ERR(folio)) {
++              err = PTR_ERR(folio);
++              goto out_iput;
++      }
+       if (!check_valid_map(F2FS_I_SB(inode), segno, off)) {
+               err = -ENOENT;
+@@ -1473,6 +1504,9 @@ out:
+       folio_unlock(folio);
+       folio_end_dropbehind(folio);
+       folio_put(folio);
++out_iput:
++      if (atomic_inode)
++              iput(atomic_inode);
+       return err;
+ }
+--- a/fs/f2fs/inode.c
++++ b/fs/f2fs/inode.c
+@@ -863,10 +863,15 @@ void f2fs_evict_inode(struct inode *inod
+       f2fs_abort_atomic_write(inode, true);
+       if (fi->cow_inode && f2fs_is_cow_file(fi->cow_inode)) {
+-              clear_inode_flag(fi->cow_inode, FI_COW_FILE);
+-              F2FS_I(fi->cow_inode)->atomic_inode = NULL;
+-              iput(fi->cow_inode);
++              struct inode *cow_inode = fi->cow_inode;
++
++              f2fs_down_write(&F2FS_I(cow_inode)->i_sem);
++              clear_inode_flag(cow_inode, FI_COW_FILE);
++              F2FS_I(cow_inode)->atomic_inode = NULL;
+               fi->cow_inode = NULL;
++              f2fs_up_write(&F2FS_I(cow_inode)->i_sem);
++
++              iput(cow_inode);
+       }
+       trace_f2fs_evict_inode(inode);
diff --git a/queue-7.1/f2fs-bound-i_inline_xattr_size-for-non-inline-xattr-inodes.patch b/queue-7.1/f2fs-bound-i_inline_xattr_size-for-non-inline-xattr-inodes.patch
new file mode 100644 (file)
index 0000000..c3b0a71
--- /dev/null
@@ -0,0 +1,72 @@
+From 378acf3cf19b6af6cba55e8dd1154c4e1504bae8 Mon Sep 17 00:00:00 2001
+From: Bryam Vargas <hexlabsecurity@proton.me>
+Date: Thu, 11 Jun 2026 23:00:36 -0500
+Subject: f2fs: bound i_inline_xattr_size for non-inline-xattr inodes
+
+From: Bryam Vargas <hexlabsecurity@proton.me>
+
+commit 378acf3cf19b6af6cba55e8dd1154c4e1504bae8 upstream.
+
+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: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/inode.c |    6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/fs/f2fs/inode.c
++++ b/fs/f2fs/inode.c
+@@ -324,9 +324,9 @@ static bool sanity_check_inode(struct in
+       }
+       if (f2fs_sb_has_flexible_inline_xattr(sbi) &&
+-              f2fs_has_inline_xattr(inode) &&
+-              (fi->i_inline_xattr_size < MIN_INLINE_XATTR_SIZE ||
+-              fi->i_inline_xattr_size > MAX_INLINE_XATTR_SIZE)) {
++              (fi->i_inline_xattr_size > MAX_INLINE_XATTR_SIZE ||
++              (f2fs_has_inline_xattr(inode) &&
++              fi->i_inline_xattr_size < MIN_INLINE_XATTR_SIZE))) {
+               f2fs_warn(sbi, "%s: inode (ino=%llx) has corrupted i_inline_xattr_size: %d, min: %zu, max: %lu",
+                         __func__, inode->i_ino, fi->i_inline_xattr_size,
+                         MIN_INLINE_XATTR_SIZE, MAX_INLINE_XATTR_SIZE);
diff --git a/queue-7.1/f2fs-fix-incorrect-fi_no_extent-handling-in-__destroy_extent_node.patch b/queue-7.1/f2fs-fix-incorrect-fi_no_extent-handling-in-__destroy_extent_node.patch
new file mode 100644 (file)
index 0000000..2d5aaa2
--- /dev/null
@@ -0,0 +1,85 @@
+From 1f70ddb28a3c71df124da5fa4040c808116d6bb9 Mon Sep 17 00:00:00 2001
+From: Yongpeng Yang <yangyongpeng@xiaomi.com>
+Date: Mon, 27 Apr 2026 21:10:51 +0800
+Subject: f2fs: fix incorrect FI_NO_EXTENT handling in __destroy_extent_node()
+
+From: Yongpeng Yang <yangyongpeng@xiaomi.com>
+
+commit 1f70ddb28a3c71df124da5fa4040c808116d6bb9 upstream.
+
+When __destroy_extent_node() sets the inode flag FI_NO_EXTENT, it does
+not reset the length of the largest extent to 0 and update the inode
+folio. Since modifications to the extent tree are disallowed afterward,
+the cached largest extent may become stale. This can trigger the
+following error in xfstests generic/388:
+
+F2FS-fs (dm-0): sanity_check_extent_cache: inode (ino=1761) extent info [220057, 57, 6] is incorrect, run fsck to fix
+
+In the f2fs_drop_inode path, __destroy_extent_node() does not need to
+guarantee that et->node_cnt is 0, because concurrency with writeback
+is expected in this path, and writeback may update the extent cache.
+
+This patch reverts commit ed78aeebef05 ("f2fs: fix node_cnt race between
+extent node destroy and writeback"), and remove the unnecessary zero
+check of et->node_cnt.
+
+Fixes: ed78aeebef05 ("f2fs: fix node_cnt race between extent node destroy and writeback")
+Cc: stable@vger.kernel.org
+Reported-by: Chao Yu <chao@kernel.org>
+Suggested-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Yongpeng Yang <yangyongpeng@xiaomi.com>
+Reviewed-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/extent_cache.c |   19 +++++++------------
+ 1 file changed, 7 insertions(+), 12 deletions(-)
+
+--- a/fs/f2fs/extent_cache.c
++++ b/fs/f2fs/extent_cache.c
+@@ -119,10 +119,9 @@ static bool __may_extent_tree(struct ino
+       if (!__init_may_extent_tree(inode, type))
+               return false;
+-      if (is_inode_flag_set(inode, FI_NO_EXTENT))
+-              return false;
+-
+       if (type == EX_READ) {
++              if (is_inode_flag_set(inode, FI_NO_EXTENT))
++                      return false;
+               if (is_inode_flag_set(inode, FI_COMPRESSED_FILE) &&
+                                !f2fs_sb_has_readonly(F2FS_I_SB(inode)))
+                       return false;
+@@ -645,14 +644,10 @@ static unsigned int __destroy_extent_nod
+       while (atomic_read(&et->node_cnt)) {
+               write_lock(&et->lock);
+-              if (!is_inode_flag_set(inode, FI_NO_EXTENT))
+-                      set_inode_flag(inode, FI_NO_EXTENT);
+               node_cnt += __free_extent_tree(sbi, et, nr_shrink);
+               write_unlock(&et->lock);
+       }
+-      f2fs_bug_on(sbi, atomic_read(&et->node_cnt));
+-
+       return node_cnt;
+ }
+@@ -691,12 +686,12 @@ static void __update_extent_tree_range(s
+       write_lock(&et->lock);
+-      if (is_inode_flag_set(inode, FI_NO_EXTENT)) {
+-              write_unlock(&et->lock);
+-              return;
+-      }
+-
+       if (type == EX_READ) {
++              if (is_inode_flag_set(inode, FI_NO_EXTENT)) {
++                      write_unlock(&et->lock);
++                      return;
++              }
++
+               prev = et->largest;
+               dei.len = 0;
diff --git a/queue-7.1/f2fs-fix-missing-read-bio-submission-on-large-folio-error.patch b/queue-7.1/f2fs-fix-missing-read-bio-submission-on-large-folio-error.patch
new file mode 100644 (file)
index 0000000..2f659a5
--- /dev/null
@@ -0,0 +1,67 @@
+From 74c8d2ec95c59a5651ecd975c466998af1961fd4 Mon Sep 17 00:00:00 2001
+From: Wenjie Qi <qiwenjie@xiaomi.com>
+Date: Wed, 20 May 2026 17:52:04 +0800
+Subject: f2fs: fix missing read bio submission on large folio error
+
+From: Wenjie Qi <qiwenjie@xiaomi.com>
+
+commit 74c8d2ec95c59a5651ecd975c466998af1961fd4 upstream.
+
+f2fs_read_data_large_folio() can keep a read bio across multiple
+readahead folios.  If a later folio hits an error before any of its
+blocks are added to the bio, folio_in_bio is false and the current error
+path returns immediately after ending that folio.
+
+This can leave the bio accumulated for earlier folios unsubmitted.  Those
+folios then never receive read completion, and readers can wait
+indefinitely on the locked folios.
+
+Route errors through the common out path so any pending bio is submitted
+before returning.  Stop consuming more readahead folios once an error is
+seen, and only wait on and clear the current folio when it was actually
+added to the bio.
+
+Cc: stable@kernel.org
+Fixes: a5d8b9d94e18 ("f2fs: fix to unlock folio in f2fs_read_data_large_folio()")
+Signed-off-by: Wenjie Qi <qiwenjie@xiaomi.com>
+Reviewed-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/data.c |   11 +++++------
+ 1 file changed, 5 insertions(+), 6 deletions(-)
+
+--- a/fs/f2fs/data.c
++++ b/fs/f2fs/data.c
+@@ -2495,7 +2495,7 @@ static int f2fs_read_data_large_folio(st
+       unsigned nrpages;
+       struct f2fs_folio_state *ffs;
+       int ret = 0;
+-      bool folio_in_bio;
++      bool folio_in_bio = false;
+       if (!IS_IMMUTABLE(inode) || f2fs_compressed_file(inode)) {
+               if (folio)
+@@ -2611,18 +2611,17 @@ submit_and_realloc:
+       }
+       trace_f2fs_read_folio(folio, DATA);
+ err_out:
+-      if (!folio_in_bio) {
++      if (!folio_in_bio)
+               folio_end_read(folio, !ret);
+-              if (ret)
+-                      return ret;
+-      }
++      if (ret)
++              goto out;
+       if (rac) {
+               folio = readahead_folio(rac);
+               goto next_folio;
+       }
+ out:
+       f2fs_submit_read_bio(F2FS_I_SB(inode), bio, DATA);
+-      if (ret) {
++      if (ret && folio_in_bio) {
+               /* Wait bios and clear uptodate. */
+               folio_lock(folio);
+               folio_clear_uptodate(folio);
diff --git a/queue-7.1/f2fs-fix-to-do-sanity-check-on-f2fs_get_node_folio_ra.patch b/queue-7.1/f2fs-fix-to-do-sanity-check-on-f2fs_get_node_folio_ra.patch
new file mode 100644 (file)
index 0000000..8c965e4
--- /dev/null
@@ -0,0 +1,111 @@
+From 8712353ed80f87271d732297567dcdbe4b84e8c7 Mon Sep 17 00:00:00 2001
+From: Chao Yu <chao@kernel.org>
+Date: Fri, 22 May 2026 15:53:29 +0800
+Subject: f2fs: fix to do sanity check on f2fs_get_node_folio_ra()
+
+From: Chao Yu <chao@kernel.org>
+
+commit 8712353ed80f87271d732297567dcdbe4b84e8c7 upstream.
+
+kernel BUG at fs/f2fs/file.c:845!
+Oops: invalid opcode: 0000 [#1] SMP KASAN NOPTI
+CPU: 0 UID: 0 PID: 5336 Comm: syz.0.0 Not tainted syzkaller #0 PREEMPT(full)
+Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
+RIP: 0010:f2fs_do_truncate_blocks+0x1115/0x1140 fs/f2fs/file.c:845
+Code: fc fc 90 0f 0b e8 8b 9d 9a fd 90 0f 0b e8 83 9d 9a fd 48 89 df 48 c7 c6 60 d1 1a 8c e8 54 f1 fc fc 90 0f 0b e8 6c 9d 9a fd 90 <0f> 0b e8 64 9d 9a fd 90 0f 0b 90 e9 93 fd ff ff e8 56 9d 9a fd 90
+RSP: 0018:ffffc9000e4474c0 EFLAGS: 00010283
+RAX: ffffffff842b1d34 RBX: 0000000000000003 RCX: 0000000000100000
+RDX: ffffc9000f03a000 RSI: 0000000000035503 RDI: 0000000000035504
+RBP: ffffc9000e447608 R08: ffff8880123b0000 R09: 0000000000000002
+R10: 00000000fffffffe R11: 0000000000000002 R12: 0000000000000001
+R13: 0000000000000000 R14: 1ffff92001c88ea0 R15: 00000000ffff039c
+FS:  00007f7e02ee36c0(0000) GS:ffff88808c887000(0000) knlGS:0000000000000000
+CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 00007ff0305c4000 CR3: 0000000012d4c000 CR4: 0000000000352ef0
+Call Trace:
+ <TASK>
+ f2fs_truncate_blocks+0x10a/0x300 fs/f2fs/file.c:882
+ f2fs_truncate+0x471/0x7c0 fs/f2fs/file.c:940
+ f2fs_evict_inode+0xa3f/0x1ac0 fs/f2fs/inode.c:907
+ evict+0x61e/0xb10 fs/inode.c:841
+ f2fs_fill_super+0x5f43/0x78f0 fs/f2fs/super.c:5224
+ get_tree_bdev_flags+0x431/0x4f0 fs/super.c:1694
+ vfs_get_tree+0x92/0x2a0 fs/super.c:1754
+ fc_mount fs/namespace.c:1193 [inline]
+ do_new_mount_fc fs/namespace.c:3758 [inline]
+ do_new_mount+0x341/0xd30 fs/namespace.c:3834
+ do_mount fs/namespace.c:4167 [inline]
+ __do_sys_mount fs/namespace.c:4383 [inline]
+ __se_sys_mount+0x31d/0x420 fs/namespace.c:4360
+ do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
+ do_syscall_64+0x15f/0xf80 arch/x86/entry/syscall_64.c:94
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+       count = ADDRS_PER_PAGE(dn.node_folio, inode);
+
+       count -= dn.ofs_in_node;
+       f2fs_bug_on(sbi, count < 0);
+
+The fuzz test will trigger above bug_on in f2fs.
+
+The root cause should be: in the corrupted inode, there is a direct node
+which has the same ino and nid in its footer, so in f2fs_do_truncate_blocks(),
+after f2fs_get_dnode_of_data() finds such dnode:
+1) ADDRS_PER_PAGE(dn.node_folio, inode) will return 923
+2) once dn.ofs_in_node points to addr[923, 1017]
+Then it will trigger the system panic.
+
+Let's introduce NODE_TYPE_NON_IXNODE to indicate current node should
+not be an inode or xattr node, and then use it in below path to detect
+inconsistent node chain in inode mapping table:
+
+- f2fs_do_truncate_blocks
+ - f2fs_get_dnode_of_data
+  - f2fs_get_node_folio_ra
+   -  __get_node_folio
+    - f2fs_sanity_check_node_footer
+     - case NODE_TYPE_NON_IXNODE -> check whether it is inode|xnode
+
+Cc: stable@kernel.org
+Reported-by: syzbot+2488d8d751b27f7ce268@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/all/69fa3697.170a0220.59368.0018.GAE@google.com
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/f2fs.h |    1 +
+ fs/f2fs/node.c |    6 +++++-
+ 2 files changed, 6 insertions(+), 1 deletion(-)
+
+--- a/fs/f2fs/f2fs.h
++++ b/fs/f2fs/f2fs.h
+@@ -1583,6 +1583,7 @@ enum node_type {
+       NODE_TYPE_INODE,
+       NODE_TYPE_XATTR,
+       NODE_TYPE_NON_INODE,
++      NODE_TYPE_NON_IXNODE,   /* non inode and xnode */
+ };
+ /* a threshold of maximum elapsed time in critical region to print tracepoint */
+--- a/fs/f2fs/node.c
++++ b/fs/f2fs/node.c
+@@ -1541,6 +1541,10 @@ int f2fs_sanity_check_node_footer(struct
+               if (is_inode)
+                       goto out_err;
+               break;
++      case NODE_TYPE_NON_IXNODE:
++              if (is_inode || is_xnode)
++                      goto out_err;
++              break;
+       default:
+               break;
+       }
+@@ -1634,7 +1638,7 @@ static struct folio *f2fs_get_node_folio
+       struct f2fs_sb_info *sbi = F2FS_F_SB(parent);
+       nid_t nid = get_nid(parent, start, false);
+-      return __get_node_folio(sbi, nid, parent, start, NODE_TYPE_REGULAR);
++      return __get_node_folio(sbi, nid, parent, start, NODE_TYPE_NON_IXNODE);
+ }
+ static void flush_inline_data(struct f2fs_sb_info *sbi, nid_t ino)
diff --git a/queue-7.1/f2fs-fix-to-round-down-start-offset-of-fallocate-for-pin-file.patch b/queue-7.1/f2fs-fix-to-round-down-start-offset-of-fallocate-for-pin-file.patch
new file mode 100644 (file)
index 0000000..2350568
--- /dev/null
@@ -0,0 +1,71 @@
+From 4275b59673eb60b02eec3997816c83f1f4b909c4 Mon Sep 17 00:00:00 2001
+From: Sunmin Jeong <s_min.jeong@samsung.com>
+Date: Mon, 22 Jun 2026 14:28:17 +0900
+Subject: f2fs: fix to round down start offset of fallocate for pin file
+
+From: Sunmin Jeong <s_min.jeong@samsung.com>
+
+commit 4275b59673eb60b02eec3997816c83f1f4b909c4 upstream.
+
+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: 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
+@@ -1916,8 +1916,15 @@ static int f2fs_expand_inode_data(struct
+       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:
+               f2fs_down_write(&sbi->pin_sem);
diff --git a/queue-7.1/f2fs-keep-atomic-write-retry-from-zeroing-original-data.patch b/queue-7.1/f2fs-keep-atomic-write-retry-from-zeroing-original-data.patch
new file mode 100644 (file)
index 0000000..8d613dd
--- /dev/null
@@ -0,0 +1,76 @@
+From 6d874b65aadce56ac78f76129dbcfc2599b638f8 Mon Sep 17 00:00:00 2001
+From: Wenjie Qi <qwjhust@gmail.com>
+Date: Wed, 27 May 2026 20:06:28 +0800
+Subject: f2fs: keep atomic write retry from zeroing original data
+
+From: Wenjie Qi <qwjhust@gmail.com>
+
+commit 6d874b65aadce56ac78f76129dbcfc2599b638f8 upstream.
+
+A partial atomic write reserves a block in the COW inode before reading the
+original data page for the untouched bytes in that page.
+
+If that read fails, write_begin returns an error but leaves the COW inode
+entry as NEW_ADDR. A retry of the same partial write then finds the COW
+entry, treats it as existing COW data, and f2fs_write_begin() zeroes the
+whole folio because blkaddr is NEW_ADDR.
+
+If the retry is committed, the bytes outside the retried write range are
+committed as zeroes instead of preserving the original file contents.
+
+Only use the COW inode as the read source when it already has a real data
+block. If the COW entry is still NEW_ADDR, treat it as a reservation to
+reuse: keep reading the old data from the original inode and avoid
+reserving or accounting the same atomic block again.
+
+Cc: stable@kernel.org
+Fixes: 3db1de0e582c ("f2fs: change the current atomic write way")
+Signed-off-by: Wenjie Qi <qiwenjie@xiaomi.com>
+Reviewed-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/data.c |   16 +++++++++++-----
+ 1 file changed, 11 insertions(+), 5 deletions(-)
+
+--- a/fs/f2fs/data.c
++++ b/fs/f2fs/data.c
+@@ -3828,6 +3828,7 @@ static int prepare_atomic_write_begin(st
+       pgoff_t index = folio->index;
+       int err = 0;
+       block_t ori_blk_addr = NULL_ADDR;
++      bool cow_has_reserved_block = false;
+       /* If pos is beyond the end of file, reserve a new block in COW inode */
+       if ((pos & PAGE_MASK) >= i_size_read(inode))
+@@ -3837,9 +3838,11 @@ static int prepare_atomic_write_begin(st
+       err = __find_data_block(cow_inode, index, blk_addr);
+       if (err) {
+               return err;
+-      } else if (*blk_addr != NULL_ADDR) {
++      } else if (__is_valid_data_blkaddr(*blk_addr)) {
+               *use_cow = true;
+               return 0;
++      } else if (*blk_addr == NEW_ADDR) {
++              cow_has_reserved_block = true;
+       }
+       if (is_inode_flag_set(inode, FI_ATOMIC_REPLACE))
+@@ -3852,10 +3855,13 @@ static int prepare_atomic_write_begin(st
+ reserve_block:
+       /* Finally, we should reserve a new block in COW inode for the update */
+-      err = __reserve_data_block(cow_inode, index, blk_addr, node_changed);
+-      if (err)
+-              return err;
+-      inc_atomic_write_cnt(inode);
++      if (!cow_has_reserved_block) {
++              err = __reserve_data_block(cow_inode, index, blk_addr,
++                                         node_changed);
++              if (err)
++                      return err;
++              inc_atomic_write_cnt(inode);
++      }
+       if (ori_blk_addr != NULL_ADDR)
+               *blk_addr = ori_blk_addr;
diff --git a/queue-7.1/f2fs-pass-correct-iostat-type-for-single-node-writes.patch b/queue-7.1/f2fs-pass-correct-iostat-type-for-single-node-writes.patch
new file mode 100644 (file)
index 0000000..fd52965
--- /dev/null
@@ -0,0 +1,43 @@
+From fcb05c26c2a67953b420739b85f49386efc9b6c0 Mon Sep 17 00:00:00 2001
+From: Wenjie Qi <qwjhust@gmail.com>
+Date: Wed, 20 May 2026 20:07:05 +0800
+Subject: f2fs: pass correct iostat type for single node writes
+
+From: Wenjie Qi <qwjhust@gmail.com>
+
+commit fcb05c26c2a67953b420739b85f49386efc9b6c0 upstream.
+
+f2fs_write_single_node_folio() takes an io_type argument, but still
+passes FS_GC_NODE_IO to __write_node_folio() unconditionally.
+
+This was harmless while the helper was only used by
+f2fs_move_node_folio(), whose caller passes FS_GC_NODE_IO. However,
+commit fe9b8b30b971 ("f2fs: fix inline data not being written to disk
+in writeback path") made f2fs_inline_data_fiemap() call the helper with
+FS_NODE_IO for FIEMAP_FLAG_SYNC.
+
+Honor the caller supplied io_type so inline-data FIEMAP sync writeback is
+accounted as normal node IO instead of GC node IO, while the GC path
+continues to pass FS_GC_NODE_IO explicitly.
+
+Cc: stable@kernel.org
+Fixes: fe9b8b30b971 ("f2fs: fix inline data not being written to disk in writeback path")
+Signed-off-by: Wenjie Qi <qiwenjie@xiaomi.com>
+Reviewed-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/node.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/f2fs/node.c
++++ b/fs/f2fs/node.c
+@@ -1875,7 +1875,7 @@ int f2fs_write_single_node_folio(struct
+       }
+       if (!__write_node_folio(node_folio, false, false, NULL,
+-                              &wbc, false, FS_GC_NODE_IO, NULL))
++                              &wbc, false, io_type, NULL))
+               err = -EAGAIN;
+       goto release_folio;
+ out_folio:
diff --git a/queue-7.1/f2fs-read-cow-data-with-the-original-inode-during-atomic-write.patch b/queue-7.1/f2fs-read-cow-data-with-the-original-inode-during-atomic-write.patch
new file mode 100644 (file)
index 0000000..24812f1
--- /dev/null
@@ -0,0 +1,137 @@
+From a41075acde0124d2f8a5f563068a5d63e8ffd57b Mon Sep 17 00:00:00 2001
+From: Mikhail Lobanov <m.lobanov@rosa.ru>
+Date: Mon, 15 Jun 2026 14:36:13 +0300
+Subject: f2fs: read COW data with the original inode during atomic write
+
+From: Mikhail Lobanov <m.lobanov@rosa.ru>
+
+commit a41075acde0124d2f8a5f563068a5d63e8ffd57b upstream.
+
+When updating an atomic-write file, f2fs_write_begin() may read the
+previously written data back from the COW inode:
+prepare_atomic_write_begin() locates the block in the COW inode and sets
+use_cow, and the read bio is then built with the COW inode:
+
+       f2fs_submit_page_read(use_cow ? F2FS_I(inode)->cow_inode : inode,
+                             ...);
+
+and f2fs_grab_read_bio() decides whether to schedule fs-layer decryption
+(STEP_DECRYPT) for the bio based on that inode via
+fscrypt_inode_uses_fs_layer_crypto().
+
+However, the folio being filled belongs to the original inode
+(folio->mapping->host == inode), and the data stored in the COW block was
+encrypted (or left as plaintext) using the original inode's context, not
+the COW inode's -- see f2fs_encrypt_one_page(), which keys off
+fio->page->mapping->host.  fscrypt_decrypt_pagecache_blocks() likewise
+operates on folio->mapping->host.
+
+The COW inode is created as a tmpfile in the parent directory and inherits
+its encryption policy from there.  With test_dummy_encryption the newly
+created COW inode gets the dummy policy and becomes encrypted, while a
+pre-existing regular file -- created before the policy applied, e.g.
+already present in the on-disk image -- stays unencrypted.  The read
+path then sets STEP_DECRYPT based on the encrypted COW inode and calls
+fscrypt_decrypt_pagecache_blocks() on a folio whose host (the unencrypted
+original inode) has a NULL ->i_crypt_info, dereferencing it:
+
+  Oops: general protection fault, probably for non-canonical address ...
+  KASAN: null-ptr-deref in range [0x0000000000000008-0x000000000000000f]
+  RIP: 0010:fscrypt_decrypt_pagecache_blocks+0xa0/0x310
+  Workqueue: f2fs_post_read_wq f2fs_post_read_work
+  Call Trace:
+   fscrypt_decrypt_bio+0x1eb/0x340
+   f2fs_post_read_work+0xba/0x140
+   process_one_work+0x91c/0x1a40
+   worker_thread+0x677/0xe90
+   kthread+0x2bc/0x3a0
+
+The COW inode is only needed to locate the on-disk block, and that block
+address is already resolved into @blkaddr by prepare_atomic_write_begin()
+via __find_data_block(cow_inode, ...); f2fs_submit_page_read() then reads
+from that physical @blkaddr directly, so the inode argument only selects
+the post-read crypto context, not which block is fetched.  Reading with
+@inode therefore returns the same (latest, not-yet-committed) COW data,
+while making both the fs-layer decryption decision and the inline crypto
+path use the correct (original inode's) key.
+
+With the COW inode no longer used at the read site, the use_cow flag has no
+remaining consumer; drop it from f2fs_write_begin() and
+prepare_atomic_write_begin().
+
+Fixes: 591fc34e1f98 ("f2fs: use cow inode data when updating atomic write")
+Cc: stable@vger.kernel.org
+Signed-off-by: Mikhail Lobanov <m.lobanov@rosa.ru>
+Reviewed-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/data.c |   26 ++++++++++++++++----------
+ 1 file changed, 16 insertions(+), 10 deletions(-)
+
+--- a/fs/f2fs/data.c
++++ b/fs/f2fs/data.c
+@@ -3821,7 +3821,7 @@ unlock_out:
+ static int prepare_atomic_write_begin(struct f2fs_sb_info *sbi,
+                       struct folio *folio, loff_t pos, unsigned int len,
+-                      block_t *blk_addr, bool *node_changed, bool *use_cow)
++                      block_t *blk_addr, bool *node_changed)
+ {
+       struct inode *inode = folio->mapping->host;
+       struct inode *cow_inode = F2FS_I(inode)->cow_inode;
+@@ -3836,14 +3836,14 @@ static int prepare_atomic_write_begin(st
+       /* Look for the block in COW inode first */
+       err = __find_data_block(cow_inode, index, blk_addr);
+-      if (err) {
++      if (err)
+               return err;
+-      } else if (__is_valid_data_blkaddr(*blk_addr)) {
+-              *use_cow = true;
++
++      if (__is_valid_data_blkaddr(*blk_addr))
+               return 0;
+-      } else if (*blk_addr == NEW_ADDR) {
++
++      if (*blk_addr == NEW_ADDR)
+               cow_has_reserved_block = true;
+-      }
+       if (is_inode_flag_set(inode, FI_ATOMIC_REPLACE))
+               goto reserve_block;
+@@ -3878,7 +3878,6 @@ static int f2fs_write_begin(const struct
+       struct folio *folio;
+       pgoff_t index = pos >> PAGE_SHIFT;
+       bool need_balance = false;
+-      bool use_cow = false;
+       block_t blkaddr = NULL_ADDR;
+       int err = 0;
+@@ -3941,7 +3940,7 @@ repeat:
+       if (f2fs_is_atomic_file(inode))
+               err = prepare_atomic_write_begin(sbi, folio, pos, len,
+-                                      &blkaddr, &need_balance, &use_cow);
++                                      &blkaddr, &need_balance);
+       else
+               err = prepare_write_begin(sbi, folio, pos, len,
+                                       &blkaddr, &need_balance);
+@@ -3981,8 +3980,15 @@ repeat:
+                       err = -EFSCORRUPTED;
+                       goto put_folio;
+               }
+-              f2fs_submit_page_read(use_cow ? F2FS_I(inode)->cow_inode :
+-                                              inode,
++              /*
++               * Although the block may be stored in the COW inode, the folio
++               * belongs to @inode and its data was encrypted (or not) using
++               * @inode's context (see f2fs_encrypt_one_page()).  Read with
++               * @inode so the post-read decryption decision matches the
++               * folio's owner; otherwise an unencrypted @inode whose COW inode
++               * is encrypted hits a NULL ->i_crypt_info on decryption.
++               */
++              f2fs_submit_page_read(inode,
+                                     NULL, /* can't write to fsverity files */
+                                     folio, blkaddr, 0, true);
diff --git a/queue-7.1/f2fs-reject-setattr-size-changes-on-large-folio-files.patch b/queue-7.1/f2fs-reject-setattr-size-changes-on-large-folio-files.patch
new file mode 100644 (file)
index 0000000..5ea707a
--- /dev/null
@@ -0,0 +1,43 @@
+From 242d30bfc0a84b8b5de0a88821b53c9ad7fd31c4 Mon Sep 17 00:00:00 2001
+From: Wenjie Qi <qwjhust@gmail.com>
+Date: Wed, 10 Jun 2026 22:37:35 +0800
+Subject: f2fs: reject setattr size changes on large folio files
+
+From: Wenjie Qi <qwjhust@gmail.com>
+
+commit 242d30bfc0a84b8b5de0a88821b53c9ad7fd31c4 upstream.
+
+F2FS large folios are only enabled for immutable non-compressed files.
+Writable open and writable mmap reject such mappings, but truncate(2)
+through f2fs_setattr() misses the same guard.
+
+If FS_IMMUTABLE_FL is cleared while the inode is still cached, the mapping
+can keep large-folio support and ATTR_SIZE can change i_size. Reject size
+changes in that state.
+
+Cc: stable@kernel.org
+Fixes: 05e65c14ea59 ("f2fs: support large folio for immutable non-compressed case")
+Signed-off-by: Wenjie Qi <qiwenjie@xiaomi.com>
+Reviewed-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/file.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
+index 69aad1060c48..d240ca78a31f 100644
+--- a/fs/f2fs/file.c
++++ b/fs/f2fs/file.c
+@@ -1098,6 +1098,8 @@ int f2fs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
+               return -EPERM;
+       if ((attr->ia_valid & ATTR_SIZE)) {
++              if (mapping_large_folio_support(inode->i_mapping))
++                      return -EOPNOTSUPP;
+               if (!f2fs_is_compress_backend_ready(inode) ||
+                               IS_DEVICE_ALIASING(inode))
+                       return -EOPNOTSUPP;
+-- 
+2.55.0
+
diff --git a/queue-7.1/f2fs-validate-acl-entry-sizes-in-f2fs_acl_from_disk.patch b/queue-7.1/f2fs-validate-acl-entry-sizes-in-f2fs_acl_from_disk.patch
new file mode 100644 (file)
index 0000000..2a6b341
--- /dev/null
@@ -0,0 +1,118 @@
+From c4810ada31e80cbe4011467c4f3b1e93f94134f3 Mon Sep 17 00:00:00 2001
+From: Zhang Cen <rollkingzzc@gmail.com>
+Date: Mon, 15 Jun 2026 15:19:54 +0800
+Subject: f2fs: validate ACL entry sizes in f2fs_acl_from_disk()
+
+From: Zhang Cen <rollkingzzc@gmail.com>
+
+commit c4810ada31e80cbe4011467c4f3b1e93f94134f3 upstream.
+
+f2fs_acl_count() only validates the aggregate ACL xattr length. A
+malformed ACL can still place ACL_USER or ACL_GROUP in a slot that only
+contains struct f2fs_acl_entry_short bytes, and f2fs_acl_from_disk()
+then reads entry->e_id before verifying that a full entry fits.
+
+Require a short entry before reading e_tag and e_perm, and require a
+full entry before reading e_id for ACL_USER and ACL_GROUP. Return
+-EFSCORRUPTED from these new truncated-entry checks, while keeping the
+pre-existing -EINVAL paths unchanged.
+
+Validation reproduced this kernel report:
+KASAN slab-out-of-bounds in __f2fs_get_acl+0x6fb/0x7e0
+RIP: 0033:0x7f4b835ea7aa
+The buggy address belongs to the object at ffff888114589960 which belongs
+to the cache kmalloc-8 of size 8
+The buggy address is located 0 bytes to the right of allocated 8-byte
+region [ffff888114589960, ffff888114589968)
+Read of size 4
+Call trace:
+  dump_stack_lvl+0x66/0xa0 (?:?)
+  print_report+0xce/0x630 (?:?)
+  __f2fs_get_acl+0x6fb/0x7e0 (fs/f2fs/acl.c:169)
+  srso_alias_return_thunk+0x5/0xfbef5 (?:?)
+  __virt_addr_valid+0x224/0x430 (?:?)
+  kasan_report+0xe0/0x110 (?:?)
+  __f2fs_get_acl+0x5/0x7e0 (fs/f2fs/acl.c:169)
+  __get_acl+0x281/0x380 (?:?)
+  vfs_get_acl+0x10b/0x190 (?:?)
+  do_get_acl+0x2a/0x410 (?:?)
+  do_get_acl+0x9/0x410 (?:?)
+  do_getxattr+0xe8/0x260 (?:?)
+  filename_getxattr+0xd1/0x140 (?:?)
+  do_getname+0x2d/0x2d0 (?:?)
+  path_getxattrat+0x16c/0x200 (?:?)
+  lock_release+0xc8/0x290 (?:?)
+  cgroup_update_frozen+0x9d/0x320 (?:?)
+  lockdep_hardirqs_on_prepare+0xea/0x1a0 (?:?)
+  trace_hardirqs_on+0x1a/0x170 (?:?)
+  _raw_spin_unlock_irq+0x28/0x50 (?:?)
+  do_syscall_64+0x115/0x6a0 (arch/x86/entry/syscall_64.c:87)
+  entry_SYSCALL_64_after_hwframe+0x77/0x7f (?:?)
+
+Cc: stable@kernel.org
+Fixes: af48b85b8cd3 ("f2fs: add xattr and acl functionalities")
+Assisted-by: Codex:gpt-5.5
+Signed-off-by: Zhang Cen <rollkingzzc@gmail.com>
+Reviewed-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/acl.c |   18 ++++++++++++++++--
+ 1 file changed, 16 insertions(+), 2 deletions(-)
+
+--- a/fs/f2fs/acl.c
++++ b/fs/f2fs/acl.c
+@@ -47,6 +47,7 @@ static inline int f2fs_acl_count(size_t
+ static struct posix_acl *f2fs_acl_from_disk(const char *value, size_t size)
+ {
+       int i, count;
++      int err = -EINVAL;
+       struct posix_acl *acl;
+       struct f2fs_acl_header *hdr = (struct f2fs_acl_header *)value;
+       struct f2fs_acl_entry *entry = (struct f2fs_acl_entry *)(hdr + 1);
+@@ -70,8 +71,11 @@ static struct posix_acl *f2fs_acl_from_d
+       for (i = 0; i < count; i++) {
+-              if ((char *)entry > end)
++              if (unlikely((char *)entry +
++                              sizeof(struct f2fs_acl_entry_short) > end)) {
++                      err = -EFSCORRUPTED;
+                       goto fail;
++              }
+               acl->a_entries[i].e_tag  = le16_to_cpu(entry->e_tag);
+               acl->a_entries[i].e_perm = le16_to_cpu(entry->e_perm);
+@@ -86,6 +90,11 @@ static struct posix_acl *f2fs_acl_from_d
+                       break;
+               case ACL_USER:
++                      if (unlikely((char *)entry +
++                                      sizeof(struct f2fs_acl_entry) > end)) {
++                              err = -EFSCORRUPTED;
++                              goto fail;
++                      }
+                       acl->a_entries[i].e_uid =
+                               make_kuid(&init_user_ns,
+                                               le32_to_cpu(entry->e_id));
+@@ -93,6 +102,11 @@ static struct posix_acl *f2fs_acl_from_d
+                                       sizeof(struct f2fs_acl_entry));
+                       break;
+               case ACL_GROUP:
++                      if (unlikely((char *)entry +
++                                      sizeof(struct f2fs_acl_entry) > end)) {
++                              err = -EFSCORRUPTED;
++                              goto fail;
++                      }
+                       acl->a_entries[i].e_gid =
+                               make_kgid(&init_user_ns,
+                                               le32_to_cpu(entry->e_id));
+@@ -108,7 +122,7 @@ static struct posix_acl *f2fs_acl_from_d
+       return acl;
+ fail:
+       posix_acl_release(acl);
+-      return ERR_PTR(-EINVAL);
++      return ERR_PTR(err);
+ }
+ static void *f2fs_acl_to_disk(struct f2fs_sb_info *sbi,
diff --git a/queue-7.1/f2fs-validate-compress-cache-inode-only-when-enabled.patch b/queue-7.1/f2fs-validate-compress-cache-inode-only-when-enabled.patch
new file mode 100644 (file)
index 0000000..42ea494
--- /dev/null
@@ -0,0 +1,53 @@
+From 5073c66a96a9c23c0c2533ed4ed06e42f9021208 Mon Sep 17 00:00:00 2001
+From: Wenjie Qi <qwjhust@gmail.com>
+Date: Thu, 21 May 2026 11:16:18 +0800
+Subject: f2fs: validate compress cache inode only when enabled
+
+From: Wenjie Qi <qwjhust@gmail.com>
+
+commit 5073c66a96a9c23c0c2533ed4ed06e42f9021208 upstream.
+
+F2FS_COMPRESS_INO() uses NM_I(sbi)->max_nid as the synthetic inode
+number for the compressed page cache inode. That inode only exists when
+the compress_cache mount option is enabled.
+
+When compress_cache is disabled, max_nid is outside the valid inode
+range. A corrupted directory entry that points to ino == max_nid should
+therefore be rejected by f2fs_check_nid_range(). However, is_meta_ino()
+currently treats F2FS_COMPRESS_INO() as a meta inode unconditionally,
+so f2fs_iget() bypasses do_read_inode() and its nid range check, and
+instantiates a fake internal inode instead.
+
+Gate the compressed cache inode case on COMPRESS_CACHE, matching
+f2fs_init_compress_inode(). With compress_cache disabled, ino ==
+max_nid now follows the normal inode path and is rejected as an
+out-of-range nid.
+
+Cc: stable@kernel.org
+Fixes: 6ce19aff0b8c ("f2fs: compress: add compress_inode to cache compressed blocks")
+Signed-off-by: Wenjie Qi <qiwenjie@xiaomi.com>
+Reviewed-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/inode.c |    9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+--- a/fs/f2fs/inode.c
++++ b/fs/f2fs/inode.c
+@@ -561,8 +561,13 @@ static int do_read_inode(struct inode *i
+ static bool is_meta_ino(struct f2fs_sb_info *sbi, unsigned int ino)
+ {
+-      return ino == F2FS_NODE_INO(sbi) || ino == F2FS_META_INO(sbi) ||
+-              ino == F2FS_COMPRESS_INO(sbi);
++      if (ino == F2FS_NODE_INO(sbi) || ino == F2FS_META_INO(sbi))
++              return true;
++#ifdef CONFIG_F2FS_FS_COMPRESSION
++      if (test_opt(sbi, COMPRESS_CACHE) && ino == F2FS_COMPRESS_INO(sbi))
++              return true;
++#endif
++      return false;
+ }
+ struct inode *f2fs_iget(struct super_block *sb, unsigned long ino)
diff --git a/queue-7.1/f2fs-validate-orphan-inode-entry-count.patch b/queue-7.1/f2fs-validate-orphan-inode-entry-count.patch
new file mode 100644 (file)
index 0000000..b33d75c
--- /dev/null
@@ -0,0 +1,75 @@
+From 846c499a65816d13f1186e3090e825e8bb8bcb8b Mon Sep 17 00:00:00 2001
+From: Wenjie Qi <qwjhust@gmail.com>
+Date: Tue, 26 May 2026 13:35:57 +0800
+Subject: f2fs: validate orphan inode entry count
+
+From: Wenjie Qi <qwjhust@gmail.com>
+
+commit 846c499a65816d13f1186e3090e825e8bb8bcb8b upstream.
+
+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>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/checkpoint.c    |   14 +++++++++++++-
+ include/linux/f2fs_fs.h |    1 +
+ 2 files changed, 14 insertions(+), 1 deletion(-)
+
+--- a/fs/f2fs/checkpoint.c
++++ b/fs/f2fs/checkpoint.c
+@@ -943,6 +943,7 @@ int f2fs_recover_orphan_inodes(struct f2
+       for (i = 0; i < orphan_blocks; i++) {
+               struct folio *folio;
+               struct f2fs_orphan_block *orphan_blk;
++              unsigned int entry_count;
+               folio = f2fs_get_meta_folio(sbi, start_blk + i);
+               if (IS_ERR(folio)) {
+@@ -951,7 +952,18 @@ int f2fs_recover_orphan_inodes(struct f2
+               }
+               orphan_blk = folio_address(folio);
+-              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);
++                      f2fs_handle_error(sbi, ERROR_INCONSISTENT_ORPHAN);
++                      err = -EFSCORRUPTED;
++                      f2fs_folio_put(folio, true);
++                      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);
+--- a/include/linux/f2fs_fs.h
++++ b/include/linux/f2fs_fs.h
+@@ -107,6 +107,7 @@ enum f2fs_error {
+       ERROR_CORRUPTED_XATTR,
+       ERROR_INVALID_NODE_REFERENCE,
+       ERROR_INCONSISTENT_NAT,
++      ERROR_INCONSISTENT_ORPHAN,
+       ERROR_MAX,
+ };
diff --git a/queue-7.1/kvm-replace-guest-triggerable-bug_on-in-ioeventfd-datamatch-with-get_unaligned.patch b/queue-7.1/kvm-replace-guest-triggerable-bug_on-in-ioeventfd-datamatch-with-get_unaligned.patch
new file mode 100644 (file)
index 0000000..6ae2aaa
--- /dev/null
@@ -0,0 +1,116 @@
+From f1edbed787ba67988ed34e0132ca128b052b6ce8 Mon Sep 17 00:00:00 2001
+From: Sean Christopherson <seanjc@google.com>
+Date: Fri, 12 Jun 2026 15:52:41 -0700
+Subject: KVM: Replace guest-triggerable BUG_ON() in ioeventfd datamatch with get_unaligned()
+
+From: Sean Christopherson <seanjc@google.com>
+
+commit f1edbed787ba67988ed34e0132ca128b052b6ce8 upstream.
+
+Drop a BUG_ON() that has been reachable since it was first added, way back
+in 2009, and instead use get_unaligned() to perform potentially-unaligned
+accesses.
+
+For a given store, KVM x86's emulator tracks the entire value in the
+destination operand, x86_emulate_ctxt.dst.  If the destination is memory,
+and the target splits multiple pages and/or is emulated MMIO, then KVM
+handles each fragment independently.  E.g. on a page split starting at page
+offset 0xffc, KVM writes 4 bytes to the first page, then the remaining
+bytes to the second page, using ctxt->dst as the source for both (with
+appropriate offsets).
+
+If the destination splits a page *and* hits emulated MMIO on the second
+page, then KVM will complete the write to the first page, then emulate the
+MMIO access to the second page.  If there is a datamatch-enabled ioeventfd
+at offset 0 of the second page, then KVM will process the remainder of the
+store as a potential ioeventfd signal.
+
+Putting it all together, if the guest emits a store that splits a page
+starting at page offset N, and the second page has a datamatch-enabled
+ioeventfd at offset 0, then KVM will check for datamatch using
+&dst.valptr[N] as the source.  Due to dst (and thus dst.valptr) being
+32-byte aligned, if N is not aligned to @len, the BUG_ON() fires.
+
+E.g. with a 16-byte store at page offset 0xffc, to an ioeventfd of len 8,
+all initial checks in ioeventfd_in_range() will succeed, and the BUG_ON()
+fires due to @val being 4-byte aligned, but not 8-byte aligned.
+
+  ------------[ cut here ]------------
+  kernel BUG at arch/x86/kvm/../../../virt/kvm/eventfd.c:783!
+  Oops: invalid opcode: 0000 [#1] SMP
+  CPU: 0 UID: 1000 PID: 615 Comm: repro Not tainted 7.1.0-rc2-ff238429d1ea #365 PREEMPT
+  Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015
+  RIP: 0010:ioeventfd_write+0x6c/0x70 [kvm]
+  Call Trace:
+   <TASK>
+   __kvm_io_bus_write+0x85/0xb0 [kvm]
+   kvm_io_bus_write+0x53/0x80 [kvm]
+   vcpu_mmio_write+0x66/0xf0 [kvm]
+   emulator_read_write_onepage+0x12a/0x540 [kvm]
+   emulator_read_write+0x109/0x2b0 [kvm]
+   x86_emulate_insn+0x4f8/0xfb0 [kvm]
+   x86_emulate_instruction+0x181/0x790 [kvm]
+   kvm_mmu_page_fault+0x313/0x630 [kvm]
+   vmx_handle_exit+0x18a/0x590 [kvm_intel]
+   kvm_arch_vcpu_ioctl_run+0xc81/0x1c90 [kvm]
+   kvm_vcpu_ioctl+0x2d5/0x970 [kvm]
+   __x64_sys_ioctl+0x8a/0xd0
+   do_syscall_64+0xb7/0x890
+   entry_SYSCALL_64_after_hwframe+0x4b/0x53
+  RIP: 0033:0x7f19c931a9bf
+   </TASK>
+  Modules linked in: kvm_intel kvm irqbypass
+  ---[ end trace 0000000000000000 ]---
+
+In a perfect world, the fix would be to simply delete the BUG_ON(), as KVM
+x86 doesn't perform alignment checks on "normal" memory accesses at CPL0.
+Sadly, C99 ruins all the fun; while the x86 architecture plays nice,
+dereferencing an unaligned pointer directly is undefined behavior in C,
+e.g. triggers splats when running with CONFIG_UBSAN_ALIGNMENT=y.
+
+Fixes: d34e6b175e61 ("KVM: add ioeventfd support")
+Cc: stable@vger.kernel.org
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Message-ID: <20260612225241.678509-1-seanjc@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ virt/kvm/eventfd.c |   12 +++++-------
+ 1 file changed, 5 insertions(+), 7 deletions(-)
+
+--- a/virt/kvm/eventfd.c
++++ b/virt/kvm/eventfd.c
+@@ -24,6 +24,7 @@
+ #include <linux/slab.h>
+ #include <linux/seqlock.h>
+ #include <linux/irqbypass.h>
++#include <linux/unaligned.h>
+ #include <trace/events/kvm.h>
+ #include <kvm/iodev.h>
+@@ -779,21 +780,18 @@ ioeventfd_in_range(struct _ioeventfd *p,
+               return true;
+       /* otherwise, we have to actually compare the data */
+-
+-      BUG_ON(!IS_ALIGNED((unsigned long)val, len));
+-
+       switch (len) {
+       case 1:
+-              _val = *(u8 *)val;
++              _val = get_unaligned((u8 *)val);
+               break;
+       case 2:
+-              _val = *(u16 *)val;
++              _val = get_unaligned((u16 *)val);
+               break;
+       case 4:
+-              _val = *(u32 *)val;
++              _val = get_unaligned((u32 *)val);
+               break;
+       case 8:
+-              _val = *(u64 *)val;
++              _val = get_unaligned((u64 *)val);
+               break;
+       default:
+               return false;
diff --git a/queue-7.1/kvm-x86-mmu-ensure-hugepage-is-in-by-slot-before-checking-max-mapping-level.patch b/queue-7.1/kvm-x86-mmu-ensure-hugepage-is-in-by-slot-before-checking-max-mapping-level.patch
new file mode 100644 (file)
index 0000000..de0f623
--- /dev/null
@@ -0,0 +1,128 @@
+From ef057cbf825e03b63f6edf5980f96abf3c53089d Mon Sep 17 00:00:00 2001
+From: Sean Christopherson <seanjc@google.com>
+Date: Wed, 29 Apr 2026 09:34:01 -0700
+Subject: KVM: x86/mmu: Ensure hugepage is in by slot before checking max mapping level
+
+From: Sean Christopherson <seanjc@google.com>
+
+commit ef057cbf825e03b63f6edf5980f96abf3c53089d upstream.
+
+When recovering hugepages in the shadow MMU, verify that the base gfn of
+the shadow page is actually contained within the target memslot, *before*
+querying the max mapping level given the shadow page's gfn.  Failure to
+pre-check the validity of the gfn can lead to an out-of-bounds access to
+the slot's lpage_info (which typically manifests as a host #PF because the
+lpage_info is vmalloc'd) if the guest creates a hugepage mapping (in its
+PTEs) that extends "below" the bounds of a memslot.
+
+When faulting in memory for a guest, and the size of the guest mapping is
+greater than KVM's (current) max mapping, then KVM will create a "direct"
+shadow page (direct in that there are no gPTEs to shadow, and so the target
+gfn is a direct calculation given the base gfn of the shadow page).  The
+hugepage recovery flow looks for such direct shadow pages, as forcing 4KiB
+mappings when dirty logging generates the guest > host mapping size case.
+When the 4KiB restriction is lifted, then KVM can replace the shadow page
+with a hugepage.
+
+But if KVM originally used a smaller mapping than the guest because the
+range of memory covered by the guest hugepage exceeds the bounds of a
+memslot, then KVM will link a direct shadow page with a gfn that is outside
+the bounds of the memslot being used to fault in memory.  The rmap entry
+added for the leaf mapping is correct and within bounds, but the gfn of the
+leaf SPTE's parent shadow page will be out of bounds.
+
+  BUG: unable to handle page fault for address: ffffc90000806ffc
+  #PF: supervisor read access in kernel mode
+  #PF: error_code(0x0000) - not-present page
+  PGD 100000067 P4D 100000067 PUD 1002a7067 PMD 10612f067 PTE 0
+  Oops: Oops: 0000 [#1] SMP
+  CPU: 13 UID: 1000 PID: 757 Comm: mmu_stress_test Not tainted 7.1.0-rc1-48ce1e26eace-x86_pir_to_irr_comments-vm #341 PREEMPT
+  Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015
+  RIP: 0010:kvm_mmu_max_mapping_level+0x79/0x2b0 [kvm]
+  Call Trace:
+   <TASK>
+   kvm_mmu_recover_huge_pages+0x21b/0x320 [kvm]
+   kvm_set_memslot+0x1ee/0x590 [kvm]
+   kvm_set_memory_region.part.0+0x3a1/0x4d0 [kvm]
+   kvm_vm_ioctl+0x9bf/0x15d0 [kvm]
+   __x64_sys_ioctl+0x8a/0xd0
+   do_syscall_64+0xb7/0xbb0
+   entry_SYSCALL_64_after_hwframe+0x4b/0x53
+  RIP: 0033:0x7f21c0f1a9bf
+   </TASK>
+
+Don't bother pre-checking the bounds of the potential hugepage, i.e. don't
+check that e.g. sp->gfn + KVM_PAGES_PER_HPAGE(sp->role.level + 1) is also
+within the memslot, as the checks performed by kvm_mmu_max_mapping_level()
+are a superset of the basic bounds checks.  I.e. pre-checking the full
+range would be a dubious micro-optimization.
+
+Fixes: 9eba50f8d7fc ("KVM: x86/mmu: Consult max mapping level when zapping collapsible SPTEs")
+Cc: stable@vger.kernel.org
+Cc: David Matlack <dmatlack@google.com>
+Cc: James Houghton <jthoughton@google.com>
+Cc: Alexander Bulekov <bkov@amazon.com>
+Cc: Fred Griffoul <fgriffo@amazon.co.uk>
+Cc: Alexander Graf <graf@amazon.de>
+Cc: David Woodhouse <dwmw@amazon.co.uk>
+Cc: Filippo Sironi <sironi@amazon.de>
+Cc: Ivan Orlov <iorlov@amazon.co.uk>
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kvm/mmu/mmu.c   |   18 ++++++++++++------
+ include/linux/kvm_host.h |    7 ++++++-
+ 2 files changed, 18 insertions(+), 7 deletions(-)
+
+--- a/arch/x86/kvm/mmu/mmu.c
++++ b/arch/x86/kvm/mmu/mmu.c
+@@ -7288,13 +7288,19 @@ restart:
+               sp = sptep_to_sp(sptep);
+               /*
+-               * We cannot do huge page mapping for indirect shadow pages,
+-               * which are found on the last rmap (level = 1) when not using
+-               * tdp; such shadow pages are synced with the page table in
+-               * the guest, and the guest page table is using 4K page size
+-               * mapping if the indirect sp has level = 1.
++               * Direct shadow page can be replaced by a hugepage if the host
++               * mapping level allows it and the memslot maps all of the host
++               * hugepage.  Note!  If the memslot maps only part of the
++               * hugepage, sp->gfn may be below slot->base_gfn, and querying
++               * the max mapping level would cause an out-of-bounds lpage_info
++               * access.  So the gfn bounds check *must* be done first.
++               *
++               * Indirect shadow pages are created when the guest page tables
++               * are using 4K pages.  Since the host mapping is always
++               * constrained by the page size in the guest, indirect shadow
++               * pages are never collapsible.
+                */
+-              if (sp->role.direct &&
++              if (sp->role.direct && is_gfn_in_memslot(slot, sp->gfn) &&
+                   sp->role.level < kvm_mmu_max_mapping_level(kvm, NULL, slot, sp->gfn)) {
+                       kvm_zap_one_rmap_spte(kvm, rmap_head, sptep);
+--- a/include/linux/kvm_host.h
++++ b/include/linux/kvm_host.h
+@@ -1815,6 +1815,11 @@ void kvm_unregister_irq_ack_notifier(str
+                                  struct kvm_irq_ack_notifier *kian);
+ bool kvm_arch_irqfd_allowed(struct kvm *kvm, struct kvm_irqfd *args);
++static inline bool is_gfn_in_memslot(const struct kvm_memory_slot *slot, gfn_t gfn)
++{
++      return gfn >= slot->base_gfn && gfn < slot->base_gfn + slot->npages;
++}
++
+ /*
+  * Returns a pointer to the memslot if it contains gfn.
+  * Otherwise returns NULL.
+@@ -1825,7 +1830,7 @@ try_get_memslot(struct kvm_memory_slot *
+       if (!slot)
+               return NULL;
+-      if (gfn >= slot->base_gfn && gfn < slot->base_gfn + slot->npages)
++      if (is_gfn_in_memslot(slot, gfn))
+               return slot;
+       else
+               return NULL;
diff --git a/queue-7.1/mips-dec-prevent-initial-console-buffer-from-landing-in-xkphys.patch b/queue-7.1/mips-dec-prevent-initial-console-buffer-from-landing-in-xkphys.patch
new file mode 100644 (file)
index 0000000..92f4cda
--- /dev/null
@@ -0,0 +1,116 @@
+From 7fb13fd35110ebe95eb053faf79d018f51144d85 Mon Sep 17 00:00:00 2001
+From: "Maciej W. Rozycki" <macro@orcam.me.uk>
+Date: Wed, 6 May 2026 23:42:27 +0100
+Subject: MIPS: DEC: Prevent initial console buffer from landing in XKPHYS
+
+From: Maciej W. Rozycki <macro@orcam.me.uk>
+
+commit 7fb13fd35110ebe95eb053faf79d018f51144d85 upstream.
+
+In 64-bit configurations calling the initial console output handler from
+a kernel thread other than the initial one will result in a situation
+where the stack has been placed in the XKPHYS 64-bit memory segment and
+consequently so has been the buffer allocated there that is used as the
+argument corresponding to the `%s' output conversion specifier for the
+firmware's printf() entry point.
+
+This 64-bit address will then be truncated by 32-bit firmware, resulting
+in an attempt to access the wrong memory location, which in turn will
+cause all kinds of unpredictable behaviour, such as a kernel crash:
+
+  Console: colour dummy device 160x64
+  Calibrating delay loop... 49.36 BogoMIPS (lpj=192512)
+  pid_max: default: 32768 minimum: 301
+  CPU 0 Unable to handle kernel paging request at virtual address 000000000203bd00, epc == ffffffffbfc08364, ra == ffffffffbfc08800
+  Oops[#1]:
+  CPU: 0 PID: 0 Comm: swapper Not tainted 5.18.0-rc2-00254-gfb649bda6f56-dirty #121
+  $ 0   : 0000000000000000 0000000000000001 0000000000000023 ffffffff80684ba0
+  $ 4   : 000000000203bd00 ffffffffbfc0f3b4 ffffffffffffffff 0000000000000073
+  $ 8   : 0a303d7469000000 0000000000000000 0000000000000073 ffffffffbfc0f473
+  $12   : 0000000000000002 0000000000000000 ffffffff80684c1c 0000000000000000
+  $16   : 0000000000000000 ffffffff80596dc9 0000000000000000 ffffffffbfc09240
+  $20   : ffffffff80684c40 ffffffffbfc0f400 000000000000002d 000000000000002b
+  $24   : ffffffffffffffbf 000000000203bd00
+  $28   : ffffffff805f0000 ffffffff80684b58 0000000000000030 ffffffffbfc08800
+  Hi    : 0000000000000000
+  Lo    : 0000000000000aa8
+  epc   : ffffffffbfc08364 0xffffffffbfc08364
+  ra    : ffffffffbfc08800 0xffffffffbfc08800
+  Status: 140120e2        KX SX UX KERNEL EXL
+  Cause : 00000008 (ExcCode 02)
+  BadVA : 000000000203bd00
+  PrId  : 00000430 (R4000SC)
+  Modules linked in:
+  Process swapper (pid: 0, threadinfo=(____ptrval____), task=(____ptrval____), tls=0000000000000000)
+  Stack : 0000000000000000 0000000000000000 0000000000000000 0000004d0000004d
+          80684cc0806a2a40 80596dc80000004d 8061000000000000 bfc0850c80684c38
+          0000000000000000 000000000203bd00 0000000000000000 0000000000000000
+          0000000000000000 00000000bfc0f3b4 0000000000000000 0000000000000000
+          0000000000000000 0000000000000000 0000000000000000 0000000000000000
+          0000000000000000 0000000000000000 0000000000000000 0000000000000000
+          0000002500000000 0000000000000000 0000000000000000 802c1a7400000000
+          0203bd0080596dc8 0203bd4d69000000 6c61632000000018 5f746567646e6172
+          6c616320625f6d6f 5f736e5f6d6f7266 206361323778302b 303d74696e726320
+          806a0a38806b0000 806a0a38806b0000 00000000806b0000 80683c58806b0000
+          ...
+  Call Trace:
+
+  Code: a082ffff  03e00008  00601021 <80820000> 00001821  10400005  24840001  80820000  24630001
+
+  ---[ end trace 0000000000000000 ]---
+  Kernel panic - not syncing: Fatal exception in interrupt
+
+  KN04 V2.1k    (PC: 0xa0026768, SP: 0x806848e8)
+  >>
+
+In this case the pointer in $4 was truncated from 0x980000000203bd00 to
+0x000000000203bd00.
+
+This may happen when no final console driver has been enabled in the
+configuration and consequently the initial console continues being used
+late into bootstrap or with an upcoming change that will switch the zs
+driver to use a platform device, which in turn will make the console
+handover happen only after other kernel threads have already been
+started.
+
+Fix the issue by making the buffer static and initdata, and therefore
+placed in the CKSEG0 32-bit compatibility segment, observing that the
+console output handler is called with the console lock held, implying
+no need for this code to be reentrant.  Add an assertion to verify the
+buffer actually has been placed in a compatibility segment.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Maciej W. Rozycki <macro@orcam.me.uk>
+Cc: stable@vger.kernel.org # v2.6.12+
+Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/mips/dec/prom/console.c |    7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+--- a/arch/mips/dec/prom/console.c
++++ b/arch/mips/dec/prom/console.c
+@@ -2,8 +2,9 @@
+ /*
+  *    DECstation PROM-based early console support.
+  *
+- *    Copyright (C) 2004, 2007  Maciej W. Rozycki
++ *    Copyright (C) 2004, 2007, 2026  Maciej W. Rozycki
+  */
++#include <linux/bug.h>
+ #include <linux/console.h>
+ #include <linux/init.h>
+ #include <linux/kernel.h>
+@@ -14,9 +15,11 @@
+ static void __init prom_console_write(struct console *con, const char *s,
+                                     unsigned int c)
+ {
+-      char buf[81];
++      static char buf[81] __initdata = { 0 };
+       unsigned int chunk = sizeof(buf) - 1;
++      BUG_ON((long)buf != (int)(long)buf);
++
+       while (c > 0) {
+               if (chunk > c)
+                       chunk = c;
diff --git a/queue-7.1/revert-f2fs-remove-non-uptodate-folio-from-the-page-cache-in-move_data_block.patch b/queue-7.1/revert-f2fs-remove-non-uptodate-folio-from-the-page-cache-in-move_data_block.patch
new file mode 100644 (file)
index 0000000..6b156e3
--- /dev/null
@@ -0,0 +1,152 @@
+From ccaba785821970f422c47770331c7e3271763f17 Mon Sep 17 00:00:00 2001
+From: Zhaoyang Huang <zhaoyang.huang@unisoc.com>
+Date: Mon, 8 Jun 2026 17:09:39 +0800
+Subject: Revert "f2fs: remove non-uptodate folio from the page cache in move_data_block"
+
+From: Zhaoyang Huang <zhaoyang.huang@unisoc.com>
+
+commit ccaba785821970f422c47770331c7e3271763f17 upstream.
+
+This reverts commit 9609dd704725a40cd63d915f2ab6c44248a44598.
+
+The kernel panics are keeping to be reported especially when the f2fs
+partition get almost full. By investigation, we find that the reason is
+one f2fs page got freed to buddy without being deleted from LRU and the
+root cause is the race happened in [2] which is enrolled by this commit.
+
+There are 3 race processes in this scenario, please find below for their
+main activities.
+
+The changed code in move_data_block() lets the GC path evict the tail-end
+folio from the page cache through folio_end_dropbehind().  Once
+folio_unmap_invalidate() removes the folio from mapping->i_pages, the
+page-cache references for all pages in the folio are dropped.  The folio
+is then kept alive only by temporary external references, which allows a
+later split to operate on a folio whose subpages are no longer protected
+by page-cache references.
+
+After the page-cache references are gone, split_folio_to_order() can
+split the big folio into individual pages and put the resulting subpages
+back on the LRU.  For tail pages beyond EOF, split removes them from the
+page cache and drops their page-cache references.  A tail page can then
+remain on the LRU with PG_lru set while holding only the split caller's
+temporary reference.  When free_folio_and_swap_cache() drops that final
+reference, the page enters the final folio_put() release path.
+
+In parallel, folio_isolate_lru() can observe the same tail page with a
+non-zero refcount and PG_lru set.  It clears PG_lru before taking its own
+reference.  If this races with the final folio_put() from the split path,
+__folio_put() sees PG_lru already cleared and skips lruvec_del_folio().
+The page is then freed back to the allocator while its lru links are
+still present in the LRU list.  A later LRU operation on a neighboring
+page detects the stale link and reports list corruption.
+
+[1]
+[   22.486082] list_del corruption. next->prev should be fffffffec10e0ac8, but was dead000000000122. (next=fffffffec10e0a88)
+[   22.486130] ------------[ cut here ]------------
+[   22.486134] kernel BUG at lib/list_debug.c:67!
+[   22.486141] Internal error: Oops - BUG: 00000000f2000800 [#1]  SMP
+[   22.488502] Tainted: [W]=WARN, [O]=OOT_MODULE
+[   22.488506] Hardware name: Spreadtrum UMS9230 1H10 SoC (DT)
+[   22.488511] pstate: 604000c5 (nZCv daIF +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
+[   22.488517] pc : __list_del_entry_valid_or_report+0x14c/0x154
+[   22.488531] lr : __list_del_entry_valid_or_report+0x14c/0x154
+[   22.488539] sp : ffffffc08006b830
+[   22.488542] x29: ffffffc08006b868 x28: 0000000000003020 x27: 0000000000000000
+[   22.488553] x26: 0000000000000000 x25: 0000000000000004 x24: fffffffec10e0ac0
+[   22.488564] x23: 00000000000000e8 x22: 0000000000000024 x21: dead000000000122
+[   22.488574] x20: fffffffec10e0a88 x19: fffffffec10e0ac8 x18: ffffffc080061060
+[   22.488585] x17: 20747562202c3863 x16: 6130653031636566 x15: 0000000000000058
+[   22.488595] x14: 0000000000000004 x13: ffffff80f91e0000 x12: 0000000000000003
+[   22.488605] x11: 0000000000000003 x10: 0000000000000001 x9 : ffe85721f0e25f00
+[   22.488615] x8 : ffe85721f0e25f00 x7 : 0000000000000000 x6 : 6c65645f7473696c
+[   22.488625] x5 : ffffffed39b23026 x4 : 0000000000000000 x3 : 0000000000000010
+[   22.488636] x2 : 0000000000000000 x1 : 0000000000000000 x0 : 000000000000006d
+[   22.488647] Call trace:
+[   22.488651]  __list_del_entry_valid_or_report+0x14c/0x154 (P)
+[   22.488661]  __folio_put+0x2bc/0x434
+[   22.488670]  folio_put+0x28/0x58
+[   22.488678]  do_garbage_collect+0x1a34/0x2584
+[   22.488689]  f2fs_gc+0x230/0x9b4
+[   22.488697]  f2fs_fallocate+0xb90/0xdf4
+[   22.488706]  vfs_fallocate+0x1b4/0x2bc
+[   22.488716]  __arm64_sys_fallocate+0x44/0x78
+[   22.488725]  invoke_syscall+0x58/0xe4
+[   22.488732]  do_el0_svc+0x48/0xdc
+[   22.488739]  el0_svc+0x3c/0x98
+[   22.488747]  el0t_64_sync_handler+0x20/0x130
+[   22.488754]  el0t_64_sync+0x1c4/0x1c8
+
+[2]
+CPU0 (f2fs GC)              CPU1 (split_folio_to_order)          CPU2 (folio_isolate_lru)
+
+F: pagecache refs = n
+F: extra refs = GC + split
+F: PG_lru set
+move_data_block()
+folio = f2fs_grab_cache_folio(F)
+...
+__folio_set_dropbehind(F)
+folio_unlock(F)
+folio_end_dropbehind(F)
+  folio_unmap_invalidate(F)
+    __filemap_remove_folio(F)
+    folio_put_refs(F, n)
+folio_put(F)
+                            split_folio_to_order(F)
+                              folio_ref_freeze(F, 1)
+                              ...
+                              lru_add_split_folio(T)
+                                list_add_tail(&T->lru, &F->lru)
+                                folio_set_lru(T)
+                              __filemap_remove_folio(T)
+                              folio_put_refs(T, 1)
+                              /* T refcount == 1, PageLRU set */
+                                                                  folio_isolate_lru(T)
+                                                                    folio_test_clear_lru(T)
+                            free_folio_and_swap_cache(T)
+                              folio_put(T)
+                                /* refcount: 1 -> 0 */
+                                __folio_put(T)
+                                  __page_cache_release(T)
+                                    folio_test_lru(T) == false
+                                    /* skip lruvec_del_folio(T) */
+                                  free_frozen_pages(T)
+                                                                  folio_get(T)
+                                                                  lruvec_del_folio(T)
+later:
+  list_del(adjacent->lru)
+    next == &T->lru
+    next->prev == LIST_POISON / PCP freelist
+    BUG
+
+Cc: stable@vger.kernel.org
+Fixes: 9609dd704725 ("f2fs: remove non-uptodate folio from the page cache in move_data_block")
+Signed-off-by: Zhaoyang Huang <zhaoyang.huang@unisoc.com>
+Reviewed-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/gc.c | 6 +-----
+ 1 file changed, 1 insertion(+), 5 deletions(-)
+
+diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
+index 69e0a867219d..56a1c0547d76 100644
+--- a/fs/f2fs/gc.c
++++ b/fs/f2fs/gc.c
+@@ -1499,11 +1499,7 @@ static int move_data_block(struct inode *inode, block_t bidx,
+ put_out:
+       f2fs_put_dnode(&dn);
+ out:
+-      if (!folio_test_uptodate(folio))
+-              __folio_set_dropbehind(folio);
+-      folio_unlock(folio);
+-      folio_end_dropbehind(folio);
+-      folio_put(folio);
++      f2fs_folio_put(folio, true);
+ out_iput:
+       if (atomic_inode)
+               iput(atomic_inode);
+-- 
+2.55.0
+
index 11eda06db667123ea92a508c4a1e12dbffff3f30..5b7049de9592192bdd0526cc1eade8e6b5d46bb0 100644 (file)
@@ -56,3 +56,24 @@ wifi-rtw88-usb-fix-memory-leaks-on-usb-write-failures.patch
 wifi-iwlwifi-mvm-fix-race-condition-in-ptp-removal.patch
 wifi-iwlwifi-mld-fix-race-condition-in-ptp-removal.patch
 wifi-iwlwifi-mld-validate-sta_mask-before-ffs-in-ba-session-handlers.patch
+f2fs-fix-missing-read-bio-submission-on-large-folio-error.patch
+f2fs-pass-correct-iostat-type-for-single-node-writes.patch
+f2fs-reject-setattr-size-changes-on-large-folio-files.patch
+f2fs-fix-to-do-sanity-check-on-f2fs_get_node_folio_ra.patch
+f2fs-validate-orphan-inode-entry-count.patch
+f2fs-validate-compress-cache-inode-only-when-enabled.patch
+f2fs-atomic-fix-uaf-issue-on-f2fs_inode_info.atomic_inode.patch
+f2fs-fix-to-round-down-start-offset-of-fallocate-for-pin-file.patch
+f2fs-bound-i_inline_xattr_size-for-non-inline-xattr-inodes.patch
+f2fs-validate-acl-entry-sizes-in-f2fs_acl_from_disk.patch
+revert-f2fs-remove-non-uptodate-folio-from-the-page-cache-in-move_data_block.patch
+f2fs-fix-incorrect-fi_no_extent-handling-in-__destroy_extent_node.patch
+f2fs-keep-atomic-write-retry-from-zeroing-original-data.patch
+f2fs-read-cow-data-with-the-original-inode-during-atomic-write.patch
+block-avoid-mounting-the-bdev-pseudo-filesystem-in-userspace.patch
+bpf-use-kvfree-for-replaced-sysctl-write-buffer.patch
+mips-dec-prevent-initial-console-buffer-from-landing-in-xkphys.patch
+exfat-fix-potential-use-after-free-in-exfat_find_dir_entry.patch
+kvm-x86-mmu-ensure-hugepage-is-in-by-slot-before-checking-max-mapping-level.patch
+kvm-replace-guest-triggerable-bug_on-in-ioeventfd-datamatch-with-get_unaligned.patch
+crypto-nx-fix-nx_crypto_ctx_exit-argument.patch