From: Greg Kroah-Hartman Date: Wed, 8 Jul 2026 08:49:11 +0000 (+0200) Subject: 6.6-stable patches X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d02417964608bc8626061214006d6025c289afbc;p=thirdparty%2Fkernel%2Fstable-queue.git 6.6-stable patches added patches: apparmor-advertise-the-tcp-fast-open-fix-is-applied.patch block-avoid-mounting-the-bdev-pseudo-filesystem-in-userspace.patch device-property-initialize-the-remaining-fields-of-fwnode_handle-in-fwnode_init.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-listxattr-handling-of-corrupted-xattr-entries.patch f2fs-fix-potential-deadlock-in-f2fs_balance_fs.patch f2fs-fix-potential-deadlock-in-gc_merge-path-of-f2fs_balance_fs.patch f2fs-validate-orphan-inode-entry-count.patch fbdev-fbcon-fix-out-of-bounds-read-in-err_out-of-fbcon_do_set_font.patch i2c-core-fix-adapter-debugfs-creation.patch i2c-core-fix-adapter-registration-race.patch i2c-core-fix-hang-on-adapter-registration-failure.patch i2c-core-fix-irq-domain-leak-on-adapter-registration-failure.patch i2c-core-fix-null-deref-on-adapter-registration-failure.patch kvm-replace-guest-triggerable-bug_on-in-ioeventfd-datamatch-with-get_unaligned.patch net-ip_gre-require-cap_net_admin-in-the-device-netns-for-changelink.patch nfsd-don-t-reset-the-write-verifier-on-a-commit-eagain.patch nfsv4-flexfiles-reject-zero-filehandle-version-count.patch --- diff --git a/queue-6.6/apparmor-advertise-the-tcp-fast-open-fix-is-applied.patch b/queue-6.6/apparmor-advertise-the-tcp-fast-open-fix-is-applied.patch new file mode 100644 index 0000000000..7b4a0e0875 --- /dev/null +++ b/queue-6.6/apparmor-advertise-the-tcp-fast-open-fix-is-applied.patch @@ -0,0 +1,36 @@ +From stable+bounces-272228-greg=kroah.com@vger.kernel.org Mon Jul 6 16:19:11 2026 +From: Sasha Levin +Date: Mon, 6 Jul 2026 09:34:07 -0400 +Subject: apparmor: advertise the tcp fast open fix is applied +To: stable@vger.kernel.org +Cc: John Johansen , Sasha Levin +Message-ID: <20260706133407.2334924-1-sashal@kernel.org> + +From: John Johansen + +[ Upstream commit 2f6701a5ce6257ae7a64ddc6d89d0a08d2a034f8 ] + +The fix for tcp-fast-open ensures that the connect permission is being +mediated correctly but it didn't add an artifact to the feature set to +advertise the fix is available. Add an artifact so that the test suite +can identify if the fix has not been properly applied or a new +unexpected regression has occurred. + +Fixes: 4d587cd8a7215 ("apparmor: mediate the implicit connect of TCP fast open sendmsg") +Signed-off-by: John Johansen +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + security/apparmor/net.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/security/apparmor/net.c ++++ b/security/apparmor/net.c +@@ -21,6 +21,7 @@ + + struct aa_sfs_entry aa_sfs_entry_network[] = { + AA_SFS_FILE_STRING("af_mask", AA_SFS_AF_MASK), ++ AA_SFS_FILE_BOOLEAN("tcp-fast-open", 1), + { } + }; + diff --git a/queue-6.6/block-avoid-mounting-the-bdev-pseudo-filesystem-in-userspace.patch b/queue-6.6/block-avoid-mounting-the-bdev-pseudo-filesystem-in-userspace.patch new file mode 100644 index 0000000000..89906f7a31 --- /dev/null +++ b/queue-6.6/block-avoid-mounting-the-bdev-pseudo-filesystem-in-userspace.patch @@ -0,0 +1,81 @@ +From stable+bounces-271945-greg=kroah.com@vger.kernel.org Sat Jul 4 13:53:40 2026 +From: Sasha Levin +Date: Sat, 4 Jul 2026 07:53:14 -0400 +Subject: block: Avoid mounting the bdev pseudo-filesystem in userspace +To: stable@vger.kernel.org +Cc: Denis Arefev , Christoph Hellwig , Jens Axboe , Sasha Levin +Message-ID: <20260704115314.624530-1-sashal@kernel.org> + +From: Denis Arefev + +[ Upstream commit f73aa66dffcb8e61e78f01b56163ec16a15d06d2 ] + +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: + + 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 +Reviewed-by: Christoph Hellwig +Link: https://patch.msgid.link/20260521072857.5078-1-arefev@swemel.ru +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + block/bdev.c | 4 ---- + 1 file changed, 4 deletions(-) + +--- a/block/bdev.c ++++ b/block/bdev.c +@@ -383,16 +383,12 @@ EXPORT_SYMBOL_GPL(blockdev_superblock); + + void __init bdev_cache_init(void) + { +- int err; + static struct vfsmount *bd_mnt; + + bdev_cachep = kmem_cache_create("bdev_cache", sizeof(struct bdev_inode), + 0, (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT| + SLAB_MEM_SPREAD|SLAB_ACCOUNT|SLAB_PANIC), + init_once); +- err = register_filesystem(&bd_type); +- if (err) +- panic("Cannot register bdev pseudo-fs"); + bd_mnt = kern_mount(&bd_type); + if (IS_ERR(bd_mnt)) + panic("Cannot create bdev pseudo-fs"); diff --git a/queue-6.6/device-property-initialize-the-remaining-fields-of-fwnode_handle-in-fwnode_init.patch b/queue-6.6/device-property-initialize-the-remaining-fields-of-fwnode_handle-in-fwnode_init.patch new file mode 100644 index 0000000000..d5524347ab --- /dev/null +++ b/queue-6.6/device-property-initialize-the-remaining-fields-of-fwnode_handle-in-fwnode_init.patch @@ -0,0 +1,49 @@ +From stable+bounces-271596-greg=kroah.com@vger.kernel.org Fri Jul 3 03:29:39 2026 +From: Sasha Levin +Date: Thu, 2 Jul 2026 21:29:31 -0400 +Subject: device property: initialize the remaining fields of fwnode_handle in fwnode_init() +To: stable@vger.kernel.org +Cc: Bartosz Golaszewski , Sakari Ailus , "Rafael J. Wysocki (Intel)" , Andy Shevchenko , Danilo Krummrich , Sasha Levin +Message-ID: <20260703012931.3803369-1-sashal@kernel.org> + +From: Bartosz Golaszewski + +[ Upstream commit 7eba000621fff223dd7bab484d48918c7c77a307 ] + +If a firmware node is allocated on the stack (for instance: temporary +software node whose life-time we control) or on the heap - but using a +non-zeroing allocation function - and initialized using fwnode_init(), +its secondary pointer will contain uninitialized memory which likely +will be neither NULL nor IS_ERR() and so may end up being dereferenced +(for example: in dev_to_swnode()). Set fwnode->secondary to NULL on +initialization. While at it: initialize the remaining fields of struct +fwnode_handle too just to be sure. + +Cc: stable@vger.kernel.org +Fixes: 01bb86b380a3 ("driver core: Add fwnode_init()") +Reviewed-by: Sakari Ailus +Reviewed-by: Rafael J. Wysocki (Intel) +Reviewed-by: Andy Shevchenko +Signed-off-by: Bartosz Golaszewski +Link: https://patch.msgid.link/20260511074927.9473-1-bartosz.golaszewski@oss.qualcomm.com +[ Fix typo in commit message. - Danilo ] +Signed-off-by: Danilo Krummrich +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/fwnode.h | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/include/linux/fwnode.h ++++ b/include/linux/fwnode.h +@@ -195,8 +195,10 @@ static inline void fwnode_init(struct fw + { + fwnode->secondary = NULL; + fwnode->ops = ops; ++ fwnode->dev = NULL; + INIT_LIST_HEAD(&fwnode->consumers); + INIT_LIST_HEAD(&fwnode->suppliers); ++ fwnode->flags = 0; + } + + static inline void fwnode_set_flag(struct fwnode_handle *fwnode, diff --git a/queue-6.6/f2fs-atomic-fix-uaf-issue-on-f2fs_inode_info.atomic_inode.patch b/queue-6.6/f2fs-atomic-fix-uaf-issue-on-f2fs_inode_info.atomic_inode.patch new file mode 100644 index 0000000000..8cbbc78d3f --- /dev/null +++ b/queue-6.6/f2fs-atomic-fix-uaf-issue-on-f2fs_inode_info.atomic_inode.patch @@ -0,0 +1,168 @@ +From stable+bounces-271781-greg=kroah.com@vger.kernel.org Fri Jul 3 15:39:45 2026 +From: Sasha Levin +Date: Fri, 3 Jul 2026 09:31:04 -0400 +Subject: f2fs: atomic: fix UAF issue on f2fs_inode_info.atomic_inode +To: stable@vger.kernel.org +Cc: Chao Yu , stable@kernel.org, Daeho Jeong , Sunmin Jeong , Jaegeuk Kim , Sasha Levin +Message-ID: <20260703133105.4123725-1-sashal@kernel.org> + +From: Chao Yu + +[ Upstream commit e0288584baa5dc41df4a829a023c4c1b33fe53d7 ] + +- 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 +Cc: Sunmin Jeong +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 +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 +@@ -1173,8 +1173,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 page *page; + struct f2fs_io_info fio = { +@@ -1189,9 +1189,22 @@ static int ra_data_block(struct inode *i + }; + int err; + ++ 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); ++ + page = f2fs_grab_cache_page(mapping, index, true); +- if (!page) +- return -ENOMEM; ++ if (!page) { ++ err = -ENOMEM; ++ goto out_iput; ++ } + + if (f2fs_lookup_read_extent_cache_block(inode, index, + &dn.data_blkaddr)) { +@@ -1250,11 +1263,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, 1); + put_page: + f2fs_put_page(page, 1); ++out_iput: ++ if (atomic_inode) ++ iput(atomic_inode); + return err; + } + +@@ -1265,8 +1283,8 @@ put_page: + 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, +@@ -1288,10 +1306,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 */ + page = f2fs_grab_cache_page(mapping, bidx, false); +- if (!page) +- return -ENOMEM; ++ if (!page) { ++ err = -ENOMEM; ++ goto out_iput; ++ } + + if (!check_valid_map(F2FS_I_SB(inode), segno, off)) { + err = -ENOENT; +@@ -1413,6 +1444,9 @@ put_out: + f2fs_put_dnode(&dn); + out: + f2fs_put_page(page, 1); ++out_iput: ++ if (atomic_inode) ++ iput(atomic_inode); + return err; + } + +--- a/fs/f2fs/inode.c ++++ b/fs/f2fs/inode.c +@@ -842,10 +842,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-6.6/f2fs-bound-i_inline_xattr_size-for-non-inline-xattr-inodes.patch b/queue-6.6/f2fs-bound-i_inline_xattr_size-for-non-inline-xattr-inodes.patch new file mode 100644 index 0000000000..3f5f242d7a --- /dev/null +++ b/queue-6.6/f2fs-bound-i_inline_xattr_size-for-non-inline-xattr-inodes.patch @@ -0,0 +1,96 @@ +From stable+bounces-271841-greg=kroah.com@vger.kernel.org Fri Jul 3 20:03:46 2026 +From: Sasha Levin +Date: Fri, 3 Jul 2026 14:03:22 -0400 +Subject: f2fs: bound i_inline_xattr_size for non-inline-xattr inodes +To: stable@vger.kernel.org +Cc: Bryam Vargas , Chao Yu , Jaegeuk Kim , Sasha Levin +Message-ID: <20260703180322.196790-1-sashal@kernel.org> + +From: Bryam Vargas + +[ Upstream commit 378acf3cf19b6af6cba55e8dd1154c4e1504bae8 ] + +When the flexible_inline_xattr feature is enabled, do_read_inode() loads +the on-disk i_inline_xattr_size unconditionally: + + if (f2fs_sb_has_flexible_inline_xattr(sbi)) + fi->i_inline_xattr_size = le16_to_cpu(ri->i_inline_xattr_size); + +but sanity_check_inode() only range-checks it when the inode also has the +FI_INLINE_XATTR flag set. An inode that carries an inline dentry or inline +data but not FI_INLINE_XATTR -- the normal layout for an inline +directory -- therefore keeps a fully attacker-controlled +i_inline_xattr_size from a crafted image. + +get_inline_xattr_addrs() returns that value with no flag gating, so it +feeds the inode geometry: + + MAX_INLINE_DATA() = 4 * (CUR_ADDRS_PER_INODE - i_inline_xattr_size - 1) + NR_INLINE_DENTRY() = MAX_INLINE_DATA() * BITS_PER_BYTE / (...) + addrs_per_page() = CUR_ADDRS_PER_INODE - i_inline_xattr_size + +A large i_inline_xattr_size drives MAX_INLINE_DATA() and NR_INLINE_DENTRY() +negative, so make_dentry_ptr_inline() sets d->max (int) to a negative +value. The inline directory walk then compares an unsigned long bit_pos +against that negative d->max, which is promoted to a huge unsigned bound, +and reads far past the inline area: + + while (bit_pos < d->max) /* fs/f2fs/dir.c */ + ... test_bit_le(bit_pos, d->bitmap) / d->dentry[bit_pos] ... + +Mounting a crafted image and reading such a directory triggers an +out-of-bounds read in f2fs_fill_dentries(); the same underflow also +corrupts ADDRS_PER_INODE for regular files. + +Validate i_inline_xattr_size against MAX_INLINE_XATTR_SIZE whenever the +flexible_inline_xattr feature is enabled -- i.e. whenever the value is +loaded from disk and consumed -- and keep the lower MIN_INLINE_XATTR_SIZE +bound gated on inodes that actually carry an inline xattr, so legitimate +inodes with i_inline_xattr_size == 0 are still accepted. + +Cc: stable@vger.kernel.org +Fixes: 6afc662e68b5 ("f2fs: support flexible inline xattr size") +Signed-off-by: Bryam Vargas +Reviewed-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/f2fs/inode.c | 19 ++++++++++--------- + 1 file changed, 10 insertions(+), 9 deletions(-) + +--- a/fs/f2fs/inode.c ++++ b/fs/f2fs/inode.c +@@ -307,15 +307,6 @@ static bool sanity_check_inode(struct in + F2FS_TOTAL_EXTRA_ATTR_SIZE); + return false; + } +- if (f2fs_sb_has_flexible_inline_xattr(sbi) && +- f2fs_has_inline_xattr(inode) && +- (!fi->i_inline_xattr_size || +- fi->i_inline_xattr_size > MAX_INLINE_XATTR_SIZE)) { +- f2fs_warn(sbi, "%s: inode (ino=%lx) has corrupted i_inline_xattr_size: %d, max: %zu", +- __func__, inode->i_ino, fi->i_inline_xattr_size, +- MAX_INLINE_XATTR_SIZE); +- return false; +- } + if (f2fs_sb_has_compression(sbi) && + fi->i_flags & F2FS_COMPR_FL && + F2FS_FITS_IN_INODE(ri, fi->i_extra_isize, +@@ -329,6 +320,16 @@ static bool sanity_check_inode(struct in + return false; + } + ++ if (f2fs_sb_has_flexible_inline_xattr(sbi) && ++ (fi->i_inline_xattr_size > MAX_INLINE_XATTR_SIZE || ++ (f2fs_has_inline_xattr(inode) && ++ fi->i_inline_xattr_size < MIN_INLINE_XATTR_SIZE))) { ++ f2fs_warn(sbi, "%s: inode (ino=%lx) has corrupted i_inline_xattr_size: %d, min: %zu, max: %zu", ++ __func__, inode->i_ino, fi->i_inline_xattr_size, ++ MIN_INLINE_XATTR_SIZE, MAX_INLINE_XATTR_SIZE); ++ return false; ++ } ++ + if (!f2fs_sb_has_extra_attr(sbi)) { + if (f2fs_sb_has_project_quota(sbi)) { + f2fs_warn(sbi, "%s: corrupted inode ino=%lx, wrong feature flag: %u, run fsck to fix.", diff --git a/queue-6.6/f2fs-fix-listxattr-handling-of-corrupted-xattr-entries.patch b/queue-6.6/f2fs-fix-listxattr-handling-of-corrupted-xattr-entries.patch new file mode 100644 index 0000000000..dbc3863c6e --- /dev/null +++ b/queue-6.6/f2fs-fix-listxattr-handling-of-corrupted-xattr-entries.patch @@ -0,0 +1,51 @@ +From stable+bounces-271859-greg=kroah.com@vger.kernel.org Fri Jul 3 21:00:36 2026 +From: Sasha Levin +Date: Fri, 3 Jul 2026 15:00:26 -0400 +Subject: f2fs: fix listxattr handling of corrupted xattr entries +To: stable@vger.kernel.org +Cc: Keshav Verma , stable@kernel.org, Chao Yu , Jaegeuk Kim , Sasha Levin +Message-ID: <20260703190026.290198-1-sashal@kernel.org> + +From: Keshav Verma + +[ Upstream commit 5ef5bc304f23c3fe255d4936472378dcb74d0e94 ] + +Validate the xattr entry before reading its fields in f2fs_listxattr(). +Return -EFSCORRUPTED when the entry is outside the valid xattr storage +area instead of returning a successful partial result. + +Fixes: 688078e7f36c ("f2fs: fix to avoid memory leakage in f2fs_listxattr") +Cc: stable@kernel.org +Reviewed-by: Chao Yu +Signed-off-by: Keshav Verma +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/f2fs/xattr.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/fs/f2fs/xattr.c ++++ b/fs/f2fs/xattr.c +@@ -581,8 +581,6 @@ ssize_t f2fs_listxattr(struct dentry *de + size_t prefix_len; + size_t size; + +- prefix = f2fs_xattr_prefix(entry->e_name_index, dentry); +- + if ((void *)(entry) + sizeof(__u32) > last_base_addr || + (void *)XATTR_NEXT_ENTRY(entry) > last_base_addr) { + f2fs_err(F2FS_I_SB(inode), "list inode (%lu) has corrupted xattr", +@@ -590,9 +588,11 @@ ssize_t f2fs_listxattr(struct dentry *de + set_sbi_flag(F2FS_I_SB(inode), SBI_NEED_FSCK); + f2fs_handle_error(F2FS_I_SB(inode), + ERROR_CORRUPTED_XATTR); +- break; ++ error = -EFSCORRUPTED; ++ goto cleanup; + } + ++ prefix = f2fs_xattr_prefix(entry->e_name_index, dentry); + if (!prefix) + continue; + diff --git a/queue-6.6/f2fs-fix-potential-deadlock-in-f2fs_balance_fs.patch b/queue-6.6/f2fs-fix-potential-deadlock-in-f2fs_balance_fs.patch new file mode 100644 index 0000000000..eae000d844 --- /dev/null +++ b/queue-6.6/f2fs-fix-potential-deadlock-in-f2fs_balance_fs.patch @@ -0,0 +1,253 @@ +From stable+bounces-271852-greg=kroah.com@vger.kernel.org Fri Jul 3 20:38:36 2026 +From: Sasha Levin +Date: Fri, 3 Jul 2026 14:38:14 -0400 +Subject: f2fs: fix potential deadlock in f2fs_balance_fs() +To: stable@vger.kernel.org +Cc: Ruipeng Qi , Chao Yu , Jaegeuk Kim , Sasha Levin +Message-ID: <20260703183815.261615-1-sashal@kernel.org> + +From: Ruipeng Qi + +[ Upstream commit dd3114870771562036fdcf5abe813956f36d224d ] + +When the f2fs filesystem space is nearly exhausted, we encounter deadlock +issues as below: + +INFO: task A:1890 blocked for more than 120 seconds. + Tainted: G O 6.12.41-g3fe07ddf05ab #1 +"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. +task:A state:D stack:0 pid:1890 tgid:1626 ppid:1153 flags:0x00000204 +Call trace: + __switch_to+0xf4/0x158 + __schedule+0x27c/0x908 + schedule+0x3c/0x118 + io_schedule+0x44/0x68 + folio_wait_bit_common+0x174/0x370 + folio_wait_bit+0x20/0x38 + folio_wait_writeback+0x54/0xc8 + truncate_inode_partial_folio+0x70/0x1e0 + truncate_inode_pages_range+0x1b0/0x450 + truncate_pagecache+0x54/0x88 + f2fs_file_write_iter+0x3e8/0xb80 + do_iter_readv_writev+0xf0/0x1e0 + vfs_writev+0x138/0x2c8 + do_writev+0x88/0x130 + __arm64_sys_writev+0x28/0x40 + invoke_syscall+0x50/0x120 + el0_svc_common.constprop.0+0xc8/0xf0 + do_el0_svc+0x24/0x38 + el0_svc+0x30/0xf8 + el0t_64_sync_handler+0x120/0x130 + el0t_64_sync+0x190/0x198 + +INFO: task kworker/u8:11:2680853 blocked for more than 120 seconds. + Tainted: G O 6.12.41-g3fe07ddf05ab #1 +"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. +task:kworker/u8:11 state:D stack:0 pid:2680853 tgid:2680853 ppid:2 flags:0x00000208 +Workqueue: writeback wb_workfn (flush-254:0) +Call trace: + __switch_to+0xf4/0x158 + __schedule+0x27c/0x908 + schedule+0x3c/0x118 + io_schedule+0x44/0x68 + folio_wait_bit_common+0x174/0x370 + __filemap_get_folio+0x214/0x348 + pagecache_get_page+0x20/0x70 + f2fs_get_read_data_page+0x150/0x3e8 + f2fs_get_lock_data_page+0x2c/0x160 + move_data_page+0x50/0x478 + do_garbage_collect+0xd38/0x1528 + f2fs_gc+0x240/0x7e0 + f2fs_balance_fs+0x1a0/0x208 + f2fs_write_single_data_page+0x6e4/0x730 + f2fs_write_cache_pages+0x378/0x9b0 + f2fs_write_data_pages+0x2e4/0x388 + do_writepages+0x8c/0x2c8 + __writeback_single_inode+0x4c/0x498 + writeback_sb_inodes+0x234/0x4a8 + __writeback_inodes_wb+0x58/0x118 + wb_writeback+0x2f8/0x3c0 + wb_workfn+0x2c4/0x508 + process_one_work+0x180/0x408 + worker_thread+0x258/0x368 + kthread+0x118/0x128 + ret_from_fork+0x10/0x200 + +INFO: task kworker/u8:8:2641297 blocked for more than 120 seconds. + Tainted: G O 6.12.41-g3fe07ddf05ab #1 +"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. +task:kworker/u8:8 state:D stack:0 pid:2641297 tgid:2641297 ppid:2 flags:0x00000208 +Workqueue: writeback wb_workfn (flush-254:0) +Call trace: + __switch_to+0xf4/0x158 + __schedule+0x27c/0x908 + rt_mutex_schedule+0x30/0x60 + __rt_mutex_slowlock_locked.constprop.0+0x460/0x8a8 + rwbase_write_lock+0x24c/0x378 + down_write+0x1c/0x30 + f2fs_balance_fs+0x184/0x208 + f2fs_write_inode+0xf4/0x328 + __writeback_single_inode+0x370/0x498 + writeback_sb_inodes+0x234/0x4a8 + __writeback_inodes_wb+0x58/0x118 + wb_writeback+0x2f8/0x3c0 + wb_workfn+0x2c4/0x508 + process_one_work+0x180/0x408 + worker_thread+0x258/0x368 + kthread+0x118/0x128 + ret_from_fork+0x10/0x20 + +INFO: task B:1902 blocked for more than 120 seconds. + Tainted: G O 6.12.41-g3fe07ddf05ab #1 +"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. +task:B state:D stack:0 pid:1902 tgid:1626 ppid:1153 flags:0x0000020c +Call trace: + __switch_to+0xf4/0x158 + __schedule+0x27c/0x908 + rt_mutex_schedule+0x30/0x60 + __rt_mutex_slowlock_locked.constprop.0+0x460/0x8a8 + rwbase_write_lock+0x24c/0x378 + down_write+0x1c/0x30 + f2fs_balance_fs+0x184/0x208 + f2fs_map_blocks+0x94c/0x1110 + f2fs_file_write_iter+0x228/0xb80 + do_iter_readv_writev+0xf0/0x1e0 + vfs_writev+0x138/0x2c8 + do_writev+0x88/0x130 + __arm64_sys_writev+0x28/0x40 + invoke_syscall+0x50/0x120 + el0_svc_common.constprop.0+0xc8/0xf0 + do_el0_svc+0x24/0x38 + el0_svc+0x30/0xf8 + el0t_64_sync_handler+0x120/0x130 + el0t_64_sync+0x190/0x198 + +INFO: task sync:2769849 blocked for more than 120 seconds. + Tainted: G O 6.12.41-g3fe07ddf05ab #1 +"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. +task:sync state:D stack:0 pid:2769849 tgid:2769849 ppid:736 flags:0x0000020c +Call trace: + __switch_to+0xf4/0x158 + __schedule+0x27c/0x908 + schedule+0x3c/0x118 + wb_wait_for_completion+0xb0/0xe8 + sync_inodes_sb+0xc8/0x2b0 + sync_inodes_one_sb+0x24/0x38 + iterate_supers+0xa8/0x138 + ksys_sync+0x54/0xc8 + __arm64_sys_sync+0x18/0x30 + invoke_syscall+0x50/0x120 + el0_svc_common.constprop.0+0xc8/0xf0 + do_el0_svc+0x24/0x38 + el0_svc+0x30/0xf8 + el0t_64_sync_handler+0x120/0x130 + el0t_64_sync+0x190/0x198 + +The root cause is a potential deadlock between the following tasks: + +kworker/u8:11 Thread A +- f2fs_write_single_data_page + - f2fs_do_write_data_page + - folio_start_writeback(X) + - f2fs_outplace_write_data + - bio_add_folio(X) + - folio_unlock(X) + - truncate_inode_pages_range + - __filemap_get_folio(X, FGP_LOCK) + - truncate_inode_partial_folio(X) + - folio_wait_writeback(X) + - f2fs_balance_fs + - f2fs_gc + - do_garbage_collect + - move_data_page + - f2fs_get_lock_data_page + - __filemap_get_folio(X, FGP_LOCK) + +Both threads try to access folio X. Thread A holds the lock but waits +for writeback, while kworker waits for the lock. This causes a deadlock. + +Other threads also enter D state, waiting for locks such as gc_lock and +writepages. + +OPU/IPU DATA folio are all affected by this issue. To avoid such +potential deadlocks, always commit these cached folios before +triggering f2fs_gc() in f2fs_balance_fs(). + +Suggested-by: Chao Yu +Reviewed-by: Chao Yu +Signed-off-by: Ruipeng Qi +Signed-off-by: Jaegeuk Kim +Stable-dep-of: 8b4468ec023d ("f2fs: fix potential deadlock in gc_merge path of f2fs_balance_fs()") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/f2fs/data.c | 29 +++++++++++++++++++++++++++++ + fs/f2fs/f2fs.h | 1 + + fs/f2fs/segment.c | 8 ++++++++ + 3 files changed, 38 insertions(+) + +--- a/fs/f2fs/data.c ++++ b/fs/f2fs/data.c +@@ -887,6 +887,35 @@ void f2fs_submit_merged_ipu_write(struct + } + } + ++void f2fs_submit_all_merged_ipu_writes(struct f2fs_sb_info *sbi) ++{ ++ struct bio_entry *be, *tmp; ++ struct f2fs_bio_info *io; ++ enum temp_type temp; ++ ++ for (temp = HOT; temp < NR_TEMP_TYPE; temp++) { ++ LIST_HEAD(list); ++ ++ io = sbi->write_io[DATA] + temp; ++ ++ /* A lockless list_empty() check is safe here: any bios from ++ * other kworkers that we miss will be submitted by those ++ * kworkers accordingly. ++ */ ++ if (list_empty(&io->bio_list)) ++ continue; ++ ++ f2fs_down_write(&io->bio_list_lock); ++ list_splice_init(&io->bio_list, &list); ++ f2fs_up_write(&io->bio_list_lock); ++ ++ list_for_each_entry_safe(be, tmp, &list, list) { ++ f2fs_submit_write_bio(sbi, be->bio, DATA); ++ del_bio_entry(be); ++ } ++ } ++} ++ + int f2fs_merge_page_bio(struct f2fs_io_info *fio) + { + struct bio *bio = *fio->bio; +--- a/fs/f2fs/f2fs.h ++++ b/fs/f2fs/f2fs.h +@@ -3866,6 +3866,7 @@ void f2fs_submit_merged_write_cond(struc + nid_t ino, enum page_type type); + void f2fs_submit_merged_ipu_write(struct f2fs_sb_info *sbi, + struct bio **bio, struct page *page); ++void f2fs_submit_all_merged_ipu_writes(struct f2fs_sb_info *sbi); + void f2fs_flush_merged_writes(struct f2fs_sb_info *sbi); + int f2fs_submit_page_bio(struct f2fs_io_info *fio); + int f2fs_merge_page_bio(struct f2fs_io_info *fio); +--- a/fs/f2fs/segment.c ++++ b/fs/f2fs/segment.c +@@ -450,6 +450,14 @@ void f2fs_balance_fs(struct f2fs_sb_info + .should_migrate_blocks = false, + .err_gc_skipped = false, + .nr_free_secs = 1 }; ++ ++ /* ++ * Submit all cached OPU/IPU DATA bios before triggering ++ * foreground GC to avoid potential deadlocks. ++ */ ++ f2fs_submit_merged_write(sbi, DATA); ++ f2fs_submit_all_merged_ipu_writes(sbi); ++ + f2fs_down_write(&sbi->gc_lock); + stat_inc_gc_call_count(sbi, FOREGROUND); + f2fs_gc(sbi, &gc_control); diff --git a/queue-6.6/f2fs-fix-potential-deadlock-in-gc_merge-path-of-f2fs_balance_fs.patch b/queue-6.6/f2fs-fix-potential-deadlock-in-gc_merge-path-of-f2fs_balance_fs.patch new file mode 100644 index 0000000000..04e8cc8d88 --- /dev/null +++ b/queue-6.6/f2fs-fix-potential-deadlock-in-gc_merge-path-of-f2fs_balance_fs.patch @@ -0,0 +1,85 @@ +From stable+bounces-271853-greg=kroah.com@vger.kernel.org Fri Jul 3 20:38:22 2026 +From: Sasha Levin +Date: Fri, 3 Jul 2026 14:38:15 -0400 +Subject: f2fs: fix potential deadlock in gc_merge path of f2fs_balance_fs() +To: stable@vger.kernel.org +Cc: Chao Yu , stable@kernel.org, Ruipeng Qi , Chao Yu , Jaegeuk Kim , Sasha Levin +Message-ID: <20260703183815.261615-2-sashal@kernel.org> + +From: Chao Yu + +[ Upstream commit 8b4468ec023d0d1b4669dfb867588997cc03a06b ] + +When we mount device w/ gc_merge mount option, we may suffer below +potential deadlock: + +Kworker GC trehad Truncator +- f2fs_write_cache_pages + - f2fs_write_single_data_page + - f2fs_do_write_data_page + - folio_start_writeback --- set writeback flag on folio + - f2fs_outplace_write_data + : cached folio in internal bio cache + - f2fs_balance_fs + - wake_up(gc_thread) + : wake up gc thread to run foreground GC + - finish_wait(fggc_wq) + : wait on the waitqueue --- wait on GC thread to finish the work + - truncate_inode_pages_range + - __filemap_get_folio(, FGP_LOCK) --- lock folio + - truncate_inode_partial_folio + - folio_wait_writeback --- wait on writeback being cleared + - do_garbage_collect + - move_data_page + - f2fs_get_lock_data_folio + - lock on folio --- blocked on folio's lock + +In order to avoid such deadlock, let's call below functions to commit +cached bios in GC_MERGE path of f2fs_balance_fs() as the same as we did +in NOGC_MERGE path. +- f2fs_submit_merged_write(sbi, DATA); +- f2fs_submit_all_merged_ipu_writes(sbi); + +Cc: stable@kernel.org +Fixes: 351df4b20115 ("f2fs: add segment operations") +Cc: Ruipeng Qi +Reported: Sandeep Dhavale +Signed-off-by: Chao Yu +Signed-off-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/f2fs/segment.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +--- a/fs/f2fs/segment.c ++++ b/fs/f2fs/segment.c +@@ -433,6 +433,13 @@ void f2fs_balance_fs(struct f2fs_sb_info + if (has_enough_free_secs(sbi, 0, 0)) + return; + ++ /* ++ * Submit all cached OPU/IPU DATA bios before triggering ++ * foreground GC to avoid potential deadlocks. ++ */ ++ f2fs_submit_merged_write(sbi, DATA); ++ f2fs_submit_all_merged_ipu_writes(sbi); ++ + if (test_opt(sbi, GC_MERGE) && sbi->gc_thread && + sbi->gc_thread->f2fs_gc_task) { + DEFINE_WAIT(wait); +@@ -451,13 +458,6 @@ void f2fs_balance_fs(struct f2fs_sb_info + .err_gc_skipped = false, + .nr_free_secs = 1 }; + +- /* +- * Submit all cached OPU/IPU DATA bios before triggering +- * foreground GC to avoid potential deadlocks. +- */ +- f2fs_submit_merged_write(sbi, DATA); +- f2fs_submit_all_merged_ipu_writes(sbi); +- + f2fs_down_write(&sbi->gc_lock); + stat_inc_gc_call_count(sbi, FOREGROUND); + f2fs_gc(sbi, &gc_control); diff --git a/queue-6.6/f2fs-validate-orphan-inode-entry-count.patch b/queue-6.6/f2fs-validate-orphan-inode-entry-count.patch new file mode 100644 index 0000000000..2f8d86e14a --- /dev/null +++ b/queue-6.6/f2fs-validate-orphan-inode-entry-count.patch @@ -0,0 +1,79 @@ +From stable+bounces-271773-greg=kroah.com@vger.kernel.org Fri Jul 3 15:25:58 2026 +From: Sasha Levin +Date: Fri, 3 Jul 2026 09:23:37 -0400 +Subject: f2fs: validate orphan inode entry count +To: stable@vger.kernel.org +Cc: Wenjie Qi , stable@kernel.org, Wenjie Qi , Chao Yu , Jaegeuk Kim , Sasha Levin +Message-ID: <20260703132337.4099385-1-sashal@kernel.org> + +From: Wenjie Qi + +[ Upstream commit 846c499a65816d13f1186e3090e825e8bb8bcb8b ] + +f2fs_recover_orphan_inodes() trusts the orphan block entry_count when +replaying orphan inodes from the checkpoint pack. A corrupted entry_count +larger than F2FS_ORPHANS_PER_BLOCK makes the recovery loop read past the +ino[] array and interpret footer or following data as inode numbers. + +On a crafted image, mounting an unpatched kernel can drive orphan recovery +into f2fs_bug_on() and panic the kernel. Validate entry_count before +consuming entries so corrupted checkpoint data fails the mount with +-EFSCORRUPTED and requests fsck instead. + +Set ERROR_INCONSISTENT_ORPHAN as well, so the corruption reason can be +recorded in the superblock s_errors[] field. This gives fsck a persistent +hint even though mount-time orphan recovery failure may leave no chance to +persist SBI_NEED_FSCK through a checkpoint. + +Cc: stable@kernel.org +Fixes: 127e670abfa7 ("f2fs: add checkpoint operations") +Signed-off-by: Wenjie Qi +Reviewed-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 +@@ -742,6 +742,7 @@ int f2fs_recover_orphan_inodes(struct f2 + for (i = 0; i < orphan_blocks; i++) { + struct page *page; + struct f2fs_orphan_block *orphan_blk; ++ unsigned int entry_count; + + page = f2fs_get_meta_page(sbi, start_blk + i); + if (IS_ERR(page)) { +@@ -750,7 +751,18 @@ int f2fs_recover_orphan_inodes(struct f2 + } + + orphan_blk = (struct f2fs_orphan_block *)page_address(page); +- for (j = 0; j < le32_to_cpu(orphan_blk->entry_count); j++) { ++ entry_count = le32_to_cpu(orphan_blk->entry_count); ++ if (entry_count > F2FS_ORPHANS_PER_BLOCK) { ++ f2fs_err(sbi, "invalid orphan inode entry count %u", ++ entry_count); ++ set_sbi_flag(sbi, SBI_NEED_FSCK); ++ f2fs_handle_error(sbi, ERROR_INCONSISTENT_ORPHAN); ++ err = -EFSCORRUPTED; ++ f2fs_put_page(page, 1); ++ goto out; ++ } ++ ++ for (j = 0; j < entry_count; j++) { + nid_t ino = le32_to_cpu(orphan_blk->ino[j]); + + err = recover_orphan_inode(sbi, ino); +--- a/include/linux/f2fs_fs.h ++++ b/include/linux/f2fs_fs.h +@@ -102,6 +102,7 @@ enum f2fs_error { + ERROR_CORRUPTED_XATTR, + ERROR_INVALID_NODE_REFERENCE, + ERROR_INCONSISTENT_NAT, ++ ERROR_INCONSISTENT_ORPHAN, + ERROR_MAX, + }; + diff --git a/queue-6.6/fbdev-fbcon-fix-out-of-bounds-read-in-err_out-of-fbcon_do_set_font.patch b/queue-6.6/fbdev-fbcon-fix-out-of-bounds-read-in-err_out-of-fbcon_do_set_font.patch new file mode 100644 index 0000000000..831382984d --- /dev/null +++ b/queue-6.6/fbdev-fbcon-fix-out-of-bounds-read-in-err_out-of-fbcon_do_set_font.patch @@ -0,0 +1,70 @@ +From stable+bounces-272052-greg=kroah.com@vger.kernel.org Sun Jul 5 15:48:29 2026 +From: Sasha Levin +Date: Sun, 5 Jul 2026 09:48:02 -0400 +Subject: fbdev: fbcon: fix out-of-bounds read in err_out of fbcon_do_set_font() +To: stable@vger.kernel.org +Cc: Mingyu Wang <25181214217@stu.xidian.edu.cn>, Thomas Zimmermann , Helge Deller , Sasha Levin +Message-ID: <20260705134802.1722907-1-sashal@kernel.org> + +From: Mingyu Wang <25181214217@stu.xidian.edu.cn> + +[ Upstream commit 8fdc8c2057eea08d40ce2c8eed41ff9e451c65c2 ] + +When fbcon_do_set_font() fails (e.g., due to a memory allocation failure +inside vc_resize() under heavy memory pressure), it jumps to the `err_out` +label to roll back the console state. However, the current rollback logic +forgets to restore the `hi_font` state, leading to a severe state machine +corruption. + +Earlier in the function, `set_vc_hi_font()` might be called to change +`vc->vc_hi_font_mask` and mutate the screen buffer. If `vc_resize()` +subsequently fails, the `err_out` path restores `vc_font.charcount` +but entirely skips rolling back the `vc_hi_font_mask` and the screen +buffer. + +This mismatch leaves the terminal in a desynchronized state. Because +`vc_hi_font_mask` remains set, the VT subsystem will still accept +character indices greater than 255 from userspace and write them to the +screen buffer. Subsequent rendering calls (e.g., `fbcon_putcs()`) will +then use these inflated indices to access the reverted, 256-character +font array, leading to a deterministic out-of-bounds read and potential +kernel memory disclosure. + +Fix this by adding the missing rollback logic for the `hi_font` mask +and screen buffer in the error path. + +Fixes: a5a923038d70 ("fbdev: fbcon: Properly revert changes when vc_resize() failed") +Cc: stable@vger.kernel.org +Signed-off-by: Mingyu Wang <25181214217@stu.xidian.edu.cn> +Reviewed-by: Thomas Zimmermann +Signed-off-by: Helge Deller +[ Adjust context ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/video/fbdev/core/fbcon.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/drivers/video/fbdev/core/fbcon.c ++++ b/drivers/video/fbdev/core/fbcon.c +@@ -2418,6 +2418,7 @@ static int fbcon_do_set_font(struct vc_d + struct fbcon_display *p = &fb_display[vc->vc_num]; + int resize, ret, old_userfont, old_width, old_height, old_charcount; + u8 *old_data = vc->vc_font.data; ++ unsigned short old_hi_font_mask = vc->vc_hi_font_mask; + + resize = (w != vc->vc_font.width) || (h != vc->vc_font.height); + vc->vc_font.data = (void *)(p->fontdata = data); +@@ -2471,6 +2472,12 @@ err_out: + vc->vc_font.height = old_height; + vc->vc_font.charcount = old_charcount; + ++ /* Restore the hi_font state and screen buffer */ ++ if (old_hi_font_mask && !vc->vc_hi_font_mask) ++ set_vc_hi_font(vc, true); ++ else if (!old_hi_font_mask && vc->vc_hi_font_mask) ++ set_vc_hi_font(vc, false); ++ + return ret; + } + diff --git a/queue-6.6/i2c-core-fix-adapter-debugfs-creation.patch b/queue-6.6/i2c-core-fix-adapter-debugfs-creation.patch new file mode 100644 index 0000000000..11b0494577 --- /dev/null +++ b/queue-6.6/i2c-core-fix-adapter-debugfs-creation.patch @@ -0,0 +1,83 @@ +From stable+bounces-272004-greg=kroah.com@vger.kernel.org Sun Jul 5 05:12:30 2026 +From: Sasha Levin +Date: Sat, 4 Jul 2026 23:11:55 -0400 +Subject: i2c: core: fix adapter debugfs creation +To: stable@vger.kernel.org +Cc: Johan Hovold , Wolfram Sang , Sasha Levin +Message-ID: <20260705031156.1601242-4-sashal@kernel.org> + +From: Johan Hovold + +[ Upstream commit 07d5fb537928aad4369aaff0cbae73ba38a719af ] + +Clients can be registered from bus notifier callbacks so the debugfs +directory needs to be created before registering the adapter as clients +use that directory as their debugfs parent. + +Move debugfs creation before adapter registration to avoid having +clients create their debugfs directories in the debugfs root (which is +also more likely to fail due to name collisions). + +Note that failure to allocate the adapter name must now be handled +explicitly as debugfs_create_dir() cannot handle a NULL name (unlike +device_add() which returns an error). + +Fixes: 73febd775bdb ("i2c: create debugfs entry per adapter") +Cc: stable@vger.kernel.org # 6.8 +Cc: Wolfram Sang +Signed-off-by: Johan Hovold +Signed-off-by: Wolfram Sang +Stable-dep-of: ba14d7cf2fe7 ("i2c: core: fix adapter registration race") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/i2c/i2c-core-base.c | 21 +++++++++++++-------- + 1 file changed, 13 insertions(+), 8 deletions(-) + +--- a/drivers/i2c/i2c-core-base.c ++++ b/drivers/i2c/i2c-core-base.c +@@ -1546,17 +1546,22 @@ static int i2c_register_adapter(struct i + goto out_list; + } + +- dev_set_name(&adap->dev, "i2c-%d", adap->nr); ++ res = dev_set_name(&adap->dev, "i2c-%d", adap->nr); ++ if (res) ++ goto err_remove_irq_domain; ++ + adap->dev.bus = &i2c_bus_type; + adap->dev.type = &i2c_adapter_type; +- res = device_register(&adap->dev); ++ device_initialize(&adap->dev); ++ ++ adap->debugfs = debugfs_create_dir(dev_name(&adap->dev), i2c_debugfs_root); ++ ++ res = device_add(&adap->dev); + if (res) { + pr_err("adapter '%s': can't register device (%d)\n", adap->name, res); +- goto err_put_adap; ++ goto err_remove_debugfs; + } + +- adap->debugfs = debugfs_create_dir(dev_name(&adap->dev), i2c_debugfs_root); +- + res = i2c_setup_smbus_alert(adap); + if (res) + goto out_reg; +@@ -1597,13 +1602,13 @@ static int i2c_register_adapter(struct i + + out_reg: + i2c_deregister_clients(adap); +- debugfs_remove_recursive(adap->debugfs); + device_del(&adap->dev); +-err_put_adap: ++err_remove_debugfs: ++ debugfs_remove_recursive(adap->debugfs); + init_completion(&adap->dev_released); + put_device(&adap->dev); + wait_for_completion(&adap->dev_released); +- ++err_remove_irq_domain: + i2c_host_notify_irq_teardown(adap); + out_list: + mutex_lock(&core_lock); diff --git a/queue-6.6/i2c-core-fix-adapter-registration-race.patch b/queue-6.6/i2c-core-fix-adapter-registration-race.patch new file mode 100644 index 0000000000..2d80cf7a81 --- /dev/null +++ b/queue-6.6/i2c-core-fix-adapter-registration-race.patch @@ -0,0 +1,65 @@ +From stable+bounces-272005-greg=kroah.com@vger.kernel.org Sun Jul 5 05:12:08 2026 +From: Sasha Levin +Date: Sat, 4 Jul 2026 23:11:56 -0400 +Subject: i2c: core: fix adapter registration race +To: stable@vger.kernel.org +Cc: Johan Hovold , Wolfram Sang , Sasha Levin +Message-ID: <20260705031156.1601242-5-sashal@kernel.org> + +From: Johan Hovold + +[ Upstream commit ba14d7cf2fe7284610a29854bdff22b2537d3ce6 ] + +Adapters can be looked up based on their id using i2c_get_adapter() +which takes a reference to the embedded struct device. + +Make sure that the adapter (including its struct device) has been +initialised before adding it to the IDR to avoid accessing uninitialised +data which could, for example, lead to NULL-pointer dereferences or +use-after-free. + +Note that the i2c-dev chardev, which is registered from a bus notifier, +currently uses i2c_get_adapter() so the adapter needs to be added to the +IDR before registration. + +Fixes: 6e13e6418418 ("i2c: Add i2c_add_numbered_adapter()") +Cc: stable@vger.kernel.org # 2.6.22 +Signed-off-by: Johan Hovold +Signed-off-by: Wolfram Sang +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/i2c/i2c-core-base.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/drivers/i2c/i2c-core-base.c ++++ b/drivers/i2c/i2c-core-base.c +@@ -1556,6 +1556,10 @@ static int i2c_register_adapter(struct i + + adap->debugfs = debugfs_create_dir(dev_name(&adap->dev), i2c_debugfs_root); + ++ mutex_lock(&core_lock); ++ idr_replace(&i2c_adapter_idr, adap, adap->nr); ++ mutex_unlock(&core_lock); ++ + res = device_add(&adap->dev); + if (res) { + pr_err("adapter '%s': can't register device (%d)\n", adap->name, res); +@@ -1629,7 +1633,7 @@ static int __i2c_add_numbered_adapter(st + int id; + + mutex_lock(&core_lock); +- id = idr_alloc(&i2c_adapter_idr, adap, adap->nr, adap->nr + 1, GFP_KERNEL); ++ id = idr_alloc(&i2c_adapter_idr, NULL, adap->nr, adap->nr + 1, GFP_KERNEL); + mutex_unlock(&core_lock); + if (WARN(id < 0, "couldn't get idr")) + return id == -ENOSPC ? -EBUSY : id; +@@ -1665,7 +1669,7 @@ int i2c_add_adapter(struct i2c_adapter * + } + + mutex_lock(&core_lock); +- id = idr_alloc(&i2c_adapter_idr, adapter, ++ id = idr_alloc(&i2c_adapter_idr, NULL, + __i2c_first_dynamic_bus_num, 0, GFP_KERNEL); + mutex_unlock(&core_lock); + if (WARN(id < 0, "couldn't get idr")) diff --git a/queue-6.6/i2c-core-fix-hang-on-adapter-registration-failure.patch b/queue-6.6/i2c-core-fix-hang-on-adapter-registration-failure.patch new file mode 100644 index 0000000000..ed8147a7e1 --- /dev/null +++ b/queue-6.6/i2c-core-fix-hang-on-adapter-registration-failure.patch @@ -0,0 +1,114 @@ +From stable+bounces-272002-greg=kroah.com@vger.kernel.org Sun Jul 5 05:12:22 2026 +From: Sasha Levin +Date: Sat, 4 Jul 2026 23:11:53 -0400 +Subject: i2c: core: fix hang on adapter registration failure +To: stable@vger.kernel.org +Cc: Johan Hovold , Phil Reid , Wolfram Sang , Sasha Levin +Message-ID: <20260705031156.1601242-2-sashal@kernel.org> + +From: Johan Hovold + +[ Upstream commit 3c7e164344e5bcf6f274bbf59a3274f5caad9bc1 ] + +Clients may be registered from bus notifier callbacks when the adapter +is registered. On a subsequent error during registration, the adapter +references taken by such clients prevent the wait for the references to +be released from ever completing. + +Fix this by refactoring client deregistration and deregistering also on +late adapter registration failures. + +Fixes: f8756c67b3de ("i2c: core: call of_i2c_setup_smbus_alert in i2c_register_adapter") +Cc: stable@vger.kernel.org # 4.15 +Cc: Phil Reid +Signed-off-by: Johan Hovold +Signed-off-by: Wolfram Sang +Stable-dep-of: ba14d7cf2fe7 ("i2c: core: fix adapter registration race") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/i2c/i2c-core-base.c | 49 ++++++++++++++++++++++++++------------------ + 1 file changed, 29 insertions(+), 20 deletions(-) + +--- a/drivers/i2c/i2c-core-base.c ++++ b/drivers/i2c/i2c-core-base.c +@@ -63,6 +63,7 @@ + static DEFINE_MUTEX(core_lock); + static DEFINE_IDR(i2c_adapter_idr); + ++static void i2c_deregister_clients(struct i2c_adapter *adap); + static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver); + + static DEFINE_STATIC_KEY_FALSE(i2c_trace_msg_key); +@@ -1595,6 +1596,7 @@ static int i2c_register_adapter(struct i + return 0; + + out_reg: ++ i2c_deregister_clients(adap); + debugfs_remove_recursive(adap->debugfs); + init_completion(&adap->dev_released); + device_unregister(&adap->dev); +@@ -1738,29 +1740,10 @@ static int __process_removed_adapter(str + return 0; + } + +-/** +- * i2c_del_adapter - unregister I2C adapter +- * @adap: the adapter being unregistered +- * Context: can sleep +- * +- * This unregisters an I2C adapter which was previously registered +- * by @i2c_add_adapter or @i2c_add_numbered_adapter. +- */ +-void i2c_del_adapter(struct i2c_adapter *adap) ++static void i2c_deregister_clients(struct i2c_adapter *adap) + { +- struct i2c_adapter *found; + struct i2c_client *client, *next; + +- /* First make sure that this adapter was ever added */ +- mutex_lock(&core_lock); +- found = idr_find(&i2c_adapter_idr, adap->nr); +- mutex_unlock(&core_lock); +- if (found != adap) { +- pr_debug("attempting to delete unregistered adapter [%s]\n", adap->name); +- return; +- } +- +- i2c_acpi_remove_space_handler(adap); + /* Tell drivers about this removal */ + mutex_lock(&core_lock); + bus_for_each_drv(&i2c_bus_type, NULL, adap, +@@ -1786,6 +1769,32 @@ void i2c_del_adapter(struct i2c_adapter + * them up properly, so we give them a chance to do that first. */ + device_for_each_child(&adap->dev, NULL, __unregister_client); + device_for_each_child(&adap->dev, NULL, __unregister_dummy); ++} ++ ++/** ++ * i2c_del_adapter - unregister I2C adapter ++ * @adap: the adapter being unregistered ++ * Context: can sleep ++ * ++ * This unregisters an I2C adapter which was previously registered ++ * by @i2c_add_adapter or @i2c_add_numbered_adapter. ++ */ ++void i2c_del_adapter(struct i2c_adapter *adap) ++{ ++ struct i2c_adapter *found; ++ ++ /* First make sure that this adapter was ever added */ ++ mutex_lock(&core_lock); ++ found = idr_find(&i2c_adapter_idr, adap->nr); ++ mutex_unlock(&core_lock); ++ if (found != adap) { ++ pr_debug("attempting to delete unregistered adapter [%s]\n", adap->name); ++ return; ++ } ++ ++ i2c_acpi_remove_space_handler(adap); ++ ++ i2c_deregister_clients(adap); + + #ifdef CONFIG_I2C_COMPAT + class_compat_remove_link(i2c_adapter_compat_class, &adap->dev, diff --git a/queue-6.6/i2c-core-fix-irq-domain-leak-on-adapter-registration-failure.patch b/queue-6.6/i2c-core-fix-irq-domain-leak-on-adapter-registration-failure.patch new file mode 100644 index 0000000000..871997fee8 --- /dev/null +++ b/queue-6.6/i2c-core-fix-irq-domain-leak-on-adapter-registration-failure.patch @@ -0,0 +1,50 @@ +From stable+bounces-272001-greg=kroah.com@vger.kernel.org Sun Jul 5 05:12:03 2026 +From: Sasha Levin +Date: Sat, 4 Jul 2026 23:11:52 -0400 +Subject: i2c: core: fix irq domain leak on adapter registration failure +To: stable@vger.kernel.org +Cc: Johan Hovold , Benjamin Tissoires , Wolfram Sang , Sasha Levin +Message-ID: <20260705031156.1601242-1-sashal@kernel.org> + +From: Johan Hovold + +[ Upstream commit 8ce19524e4cc2462685f596a6402fbd8fb984ab2 ] + +Make sure to tear down the host notify irq domain on adapter +registration failure to avoid leaking it. + +This issue was flagged by Sashiko when reviewing another adapter +registration fix. + +Fixes: 4d5538f5882a ("i2c: use an IRQ to report Host Notify events, not alert") +Cc: stable@vger.kernel.org # 4.10 +Cc: Benjamin Tissoires +Signed-off-by: Johan Hovold +Signed-off-by: Wolfram Sang +Stable-dep-of: ba14d7cf2fe7 ("i2c: core: fix adapter registration race") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/i2c/i2c-core-base.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/i2c/i2c-core-base.c ++++ b/drivers/i2c/i2c-core-base.c +@@ -1551,7 +1551,7 @@ static int i2c_register_adapter(struct i + res = device_register(&adap->dev); + if (res) { + pr_err("adapter '%s': can't register device (%d)\n", adap->name, res); +- goto out_list; ++ goto err_remove_irq_domain; + } + + adap->debugfs = debugfs_create_dir(dev_name(&adap->dev), i2c_debugfs_root); +@@ -1599,6 +1599,8 @@ out_reg: + init_completion(&adap->dev_released); + device_unregister(&adap->dev); + wait_for_completion(&adap->dev_released); ++err_remove_irq_domain: ++ i2c_host_notify_irq_teardown(adap); + out_list: + mutex_lock(&core_lock); + idr_remove(&i2c_adapter_idr, adap->nr); diff --git a/queue-6.6/i2c-core-fix-null-deref-on-adapter-registration-failure.patch b/queue-6.6/i2c-core-fix-null-deref-on-adapter-registration-failure.patch new file mode 100644 index 0000000000..b25ec8e0ae --- /dev/null +++ b/queue-6.6/i2c-core-fix-null-deref-on-adapter-registration-failure.patch @@ -0,0 +1,57 @@ +From stable+bounces-272003-greg=kroah.com@vger.kernel.org Sun Jul 5 05:12:07 2026 +From: Sasha Levin +Date: Sat, 4 Jul 2026 23:11:54 -0400 +Subject: i2c: core: fix NULL-deref on adapter registration failure +To: stable@vger.kernel.org +Cc: Johan Hovold , Joe Hattori , Wolfram Sang , Sasha Levin +Message-ID: <20260705031156.1601242-3-sashal@kernel.org> + +From: Johan Hovold + +[ Upstream commit 2295d2bb101faa663fbc45fadbb3fec45f107441 ] + +If adapter registration ever fails the release callback would trigger a +NULL-pointer dereference as the completion struct has not been +initialised. + +Note that before the offending commit this would instead have resulted +in a minor memory leak of the adapter name. + +Fixes: 3f8c4f5e9a57 ("i2c: core: fix reference leak in i2c_register_adapter()") +Cc: stable@vger.kernel.org +Cc: Joe Hattori +Signed-off-by: Johan Hovold +Signed-off-by: Wolfram Sang +Stable-dep-of: ba14d7cf2fe7 ("i2c: core: fix adapter registration race") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/i2c/i2c-core-base.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +--- a/drivers/i2c/i2c-core-base.c ++++ b/drivers/i2c/i2c-core-base.c +@@ -1552,7 +1552,7 @@ static int i2c_register_adapter(struct i + res = device_register(&adap->dev); + if (res) { + pr_err("adapter '%s': can't register device (%d)\n", adap->name, res); +- goto err_remove_irq_domain; ++ goto err_put_adap; + } + + adap->debugfs = debugfs_create_dir(dev_name(&adap->dev), i2c_debugfs_root); +@@ -1598,10 +1598,12 @@ static int i2c_register_adapter(struct i + out_reg: + i2c_deregister_clients(adap); + debugfs_remove_recursive(adap->debugfs); ++ device_del(&adap->dev); ++err_put_adap: + init_completion(&adap->dev_released); +- device_unregister(&adap->dev); ++ put_device(&adap->dev); + wait_for_completion(&adap->dev_released); +-err_remove_irq_domain: ++ + i2c_host_notify_irq_teardown(adap); + out_list: + mutex_lock(&core_lock); diff --git a/queue-6.6/kvm-replace-guest-triggerable-bug_on-in-ioeventfd-datamatch-with-get_unaligned.patch b/queue-6.6/kvm-replace-guest-triggerable-bug_on-in-ioeventfd-datamatch-with-get_unaligned.patch new file mode 100644 index 0000000000..ae06974f10 --- /dev/null +++ b/queue-6.6/kvm-replace-guest-triggerable-bug_on-in-ioeventfd-datamatch-with-get_unaligned.patch @@ -0,0 +1,121 @@ +From stable+bounces-271879-greg=kroah.com@vger.kernel.org Sat Jul 4 02:47:26 2026 +From: Sasha Levin +Date: Fri, 3 Jul 2026 20:47:15 -0400 +Subject: KVM: Replace guest-triggerable BUG_ON() in ioeventfd datamatch with get_unaligned() +To: stable@vger.kernel.org +Cc: Sean Christopherson , Paolo Bonzini , Sasha Levin +Message-ID: <20260704004716.434516-1-sashal@kernel.org> + +From: Sean Christopherson + +[ Upstream commit f1edbed787ba67988ed34e0132ca128b052b6ce8 ] + +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: + + __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 + + 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 +Message-ID: <20260612225241.678509-1-seanjc@google.com> +Signed-off-by: Paolo Bonzini +[ Adjusted context to use `#include ` since `linux/unaligned.h` doesn't exist in 6.6. ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 + #include + #include ++#include + #include + + #include +@@ -757,21 +758,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-6.6/net-ip_gre-require-cap_net_admin-in-the-device-netns-for-changelink.patch b/queue-6.6/net-ip_gre-require-cap_net_admin-in-the-device-netns-for-changelink.patch new file mode 100644 index 0000000000..0a39470b4f --- /dev/null +++ b/queue-6.6/net-ip_gre-require-cap_net_admin-in-the-device-netns-for-changelink.patch @@ -0,0 +1,99 @@ +From stable+bounces-270541-greg=kroah.com@vger.kernel.org Thu Jul 2 16:34:17 2026 +From: Sasha Levin +Date: Thu, 2 Jul 2026 10:34:08 -0400 +Subject: net: ip_gre: require CAP_NET_ADMIN in the device netns for changelink +To: stable@vger.kernel.org +Cc: Maoyi Xie , Xiao Liang , Kuniyuki Iwashima , Jakub Kicinski , Sasha Levin +Message-ID: <20260702143408.3487262-1-sashal@kernel.org> + +From: Maoyi Xie + +[ Upstream commit 8165f7ff57d9667d2bb477ef6af83ede7fed4ad7 ] + +A tunnel changelink() operates on at most two netns, dev_net(dev) and +the tunnel link netns t->net. They differ once the device is created in +or moved to a netns other than the one the request runs in. The rtnl +changelink path checks CAP_NET_ADMIN only against dev_net(dev), so a +caller privileged there but not in t->net can rewrite a tunnel that +lives in t->net. + +Add rtnl_dev_link_net_capable() next to rtnl_get_net_ns_capable() in +net/core/rtnetlink.c. It requires CAP_NET_ADMIN in the link netns and is +skipped when the link netns is dev_net(dev), where the rtnl path already +checked it. The other patches in this series use the same helper. + +Gate ipgre_changelink() and erspan_changelink() with it, at the top of +the op before any attribute is parsed, because the parsers update live +tunnel fields first. ipgre_netlink_parms() sets t->collect_md before +ip_tunnel_changelink() runs. + +Commit 8b484efd5cb4 ("ip6: vti: Use ip6_tnl.net in +vti6_siocdevprivate().") added the same check on the ioctl path. This +adds it on RTM_NEWLINK. + +Reported-by: Xiao Liang +Closes: https://lore.kernel.org/netdev/CABAhCOSzP1vaThGV35_VnsRCb=87_CPjPVsTHbq905k8A+BuUg@mail.gmail.com/ +Fixes: b57708add314 ("gre: add x-netns support") +Cc: stable@vger.kernel.org +Signed-off-by: Maoyi Xie +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20260612085941.3158249-2-maoyixie.tju@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + include/net/rtnetlink.h | 2 ++ + net/core/rtnetlink.c | 8 ++++++++ + net/ipv4/ip_gre.c | 6 ++++++ + 3 files changed, 16 insertions(+) + +--- a/include/net/rtnetlink.h ++++ b/include/net/rtnetlink.h +@@ -211,6 +211,8 @@ int rtnl_configure_link(struct net_devic + int rtnl_nla_parse_ifinfomsg(struct nlattr **tb, const struct nlattr *nla_peer, + struct netlink_ext_ack *exterr); + struct net *rtnl_get_net_ns_capable(struct sock *sk, int netnsid); ++bool rtnl_dev_link_net_capable(const struct net_device *dev, ++ const struct net *link_net); + + #define MODULE_ALIAS_RTNL_LINK(kind) MODULE_ALIAS("rtnl-link-" kind) + +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -2157,6 +2157,14 @@ struct net *rtnl_get_net_ns_capable(stru + } + EXPORT_SYMBOL_GPL(rtnl_get_net_ns_capable); + ++bool rtnl_dev_link_net_capable(const struct net_device *dev, ++ const struct net *link_net) ++{ ++ return net_eq(link_net, dev_net(dev)) || ++ ns_capable(link_net->user_ns, CAP_NET_ADMIN); ++} ++EXPORT_SYMBOL_GPL(rtnl_dev_link_net_capable); ++ + static int rtnl_valid_dump_ifinfo_req(const struct nlmsghdr *nlh, + bool strict_check, struct nlattr **tb, + struct netlink_ext_ack *extack) +--- a/net/ipv4/ip_gre.c ++++ b/net/ipv4/ip_gre.c +@@ -1412,6 +1412,9 @@ static int ipgre_changelink(struct net_d + struct ip_tunnel_parm p; + int err; + ++ if (!rtnl_dev_link_net_capable(dev, t->net)) ++ return -EPERM; ++ + err = ipgre_newlink_encap_setup(dev, data); + if (err) + return err; +@@ -1441,6 +1444,9 @@ static int erspan_changelink(struct net_ + struct ip_tunnel_parm p; + int err; + ++ if (!rtnl_dev_link_net_capable(dev, t->net)) ++ return -EPERM; ++ + err = ipgre_newlink_encap_setup(dev, data); + if (err) + return err; diff --git a/queue-6.6/nfsd-don-t-reset-the-write-verifier-on-a-commit-eagain.patch b/queue-6.6/nfsd-don-t-reset-the-write-verifier-on-a-commit-eagain.patch new file mode 100644 index 0000000000..03f0fa6d81 --- /dev/null +++ b/queue-6.6/nfsd-don-t-reset-the-write-verifier-on-a-commit-eagain.patch @@ -0,0 +1,106 @@ +From stable+bounces-272078-greg=kroah.com@vger.kernel.org Sun Jul 5 16:40:33 2026 +From: Sasha Levin +Date: Sun, 5 Jul 2026 10:40:22 -0400 +Subject: nfsd: Don't reset the write verifier on a commit EAGAIN +To: stable@vger.kernel.org +Cc: Trond Myklebust , Jeff Layton , Chuck Lever , Sasha Levin +Message-ID: <20260705144023.1865360-1-sashal@kernel.org> + +From: Trond Myklebust + +[ Upstream commit 1b2021bdeeca12364ad0fa7aac9ddba5cae964f3 ] + +If fsync() is returning EAGAIN, then we can assume that the filesystem +being exported is something like NFS with the 'softerr' mount option +enabled, and that it is just asking us to replay the fsync() operation +at a later date. + +If we see an ESTALE, then ditto: the file is gone, so there is no danger +of losing the error. + +For those cases, do not reset the write verifier. A write verifier +change has a global effect, causing retransmission by all clients of +all uncommitted unstable writes for all files, so it is worth +mitigating where possible. + +Link: https://lore.kernel.org/linux-nfs/20230911184357.11739-1-trond.myklebust@hammerspace.com/ +Signed-off-by: Trond Myklebust +Reviewed-by: Jeff Layton +Signed-off-by: Chuck Lever +Stable-dep-of: 2090b05803fa ("nfsd: reset write verifier on deferred writeback errors") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/nfsd/vfs.c | 33 +++++++++++++++++++++++---------- + 1 file changed, 23 insertions(+), 10 deletions(-) + +--- a/fs/nfsd/vfs.c ++++ b/fs/nfsd/vfs.c +@@ -338,6 +338,24 @@ out: + return err; + } + ++static void ++commit_reset_write_verifier(struct nfsd_net *nn, struct svc_rqst *rqstp, ++ int err) ++{ ++ switch (err) { ++ case -EAGAIN: ++ case -ESTALE: ++ /* ++ * Neither of these are the result of a problem with ++ * durable storage, so avoid a write verifier reset. ++ */ ++ break; ++ default: ++ nfsd_reset_write_verifier(nn); ++ trace_nfsd_writeverf_reset(nn, rqstp, err); ++ } ++} ++ + /* + * Commit metadata changes to stable storage. + */ +@@ -659,8 +677,7 @@ __be32 nfsd4_clone_file_range(struct svc + &nfsd4_get_cstate(rqstp)->current_fh, + dst_pos, + count, status); +- nfsd_reset_write_verifier(nn); +- trace_nfsd_writeverf_reset(nn, rqstp, status); ++ commit_reset_write_verifier(nn, rqstp, status); + ret = nfserrno(status); + } + } +@@ -1177,8 +1194,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, s + host_err = vfs_iter_write(file, &iter, &pos, flags); + file_end_write(file); + if (host_err < 0) { +- nfsd_reset_write_verifier(nn); +- trace_nfsd_writeverf_reset(nn, rqstp, host_err); ++ commit_reset_write_verifier(nn, rqstp, host_err); + goto out_nfserr; + } + *cnt = host_err; +@@ -1193,10 +1209,8 @@ nfsd_vfs_write(struct svc_rqst *rqstp, s + + if (stable && use_wgather) { + host_err = wait_for_concurrent_writes(file); +- if (host_err < 0) { +- nfsd_reset_write_verifier(nn); +- trace_nfsd_writeverf_reset(nn, rqstp, host_err); +- } ++ if (host_err < 0) ++ commit_reset_write_verifier(nn, rqstp, host_err); + } + + out_nfserr: +@@ -1343,8 +1357,7 @@ nfsd_commit(struct svc_rqst *rqstp, stru + err = nfserr_notsupp; + break; + default: +- nfsd_reset_write_verifier(nn); +- trace_nfsd_writeverf_reset(nn, rqstp, err2); ++ commit_reset_write_verifier(nn, rqstp, err2); + err = nfserrno(err2); + } + } else diff --git a/queue-6.6/nfsv4-flexfiles-reject-zero-filehandle-version-count.patch b/queue-6.6/nfsv4-flexfiles-reject-zero-filehandle-version-count.patch new file mode 100644 index 0000000000..9d35ee2b80 --- /dev/null +++ b/queue-6.6/nfsv4-flexfiles-reject-zero-filehandle-version-count.patch @@ -0,0 +1,58 @@ +From stable+bounces-272064-greg=kroah.com@vger.kernel.org Sun Jul 5 16:06:09 2026 +From: Sasha Levin +Date: Sun, 5 Jul 2026 10:01:16 -0400 +Subject: NFSv4/flexfiles: reject zero filehandle version count +To: stable@vger.kernel.org +Cc: Michael Bommarito , Anna Schumaker , Sasha Levin +Message-ID: <20260705140116.1746651-1-sashal@kernel.org> + +From: Michael Bommarito + +[ Upstream commit 2c6bb3c40bc24f6aa8dfbe6fe98c3ad6389203f2 ] + +ff_layout_alloc_lseg() decodes the filehandle-version array count +from the flexfiles layout body. The value is used as the count for +kzalloc_objs(), and the current code only rejects NULL. + +A zero count yields ZERO_SIZE_PTR, which can be stored in +dss_info->fh_versions even though later flexfiles paths assume that at +least one filehandle version exists. + +Reject fh_count == 0 before the allocation, matching the existing zero +version_count validation in the flexfiles GETDEVICEINFO parser. + +A QEMU/KASAN run with a malformed flexfiles layout hit: + + KASAN: null-ptr-deref in range [0x0000000000000010-0x0000000000000017] + RIP: 0010:ff_layout_encode_ff_layoutupdate.isra.0+0x15f/0x750 + ff_layout_encode_layoutreturn+0x683/0x970 + nfs4_xdr_enc_layoutreturn+0x278/0x3a0 + Kernel panic - not syncing: Fatal exception + +The patched kernel rejects the malformed layout without KASAN/oops/panic, +and a valid fh_count=1 regression still opens, reads, and unmounts cleanly. + +Cc: stable@vger.kernel.org +Fixes: d67ae825a59d ("pnfs/flexfiles: Add the FlexFile Layout Driver") +Assisted-by: Claude:claude-opus-4-7 +Signed-off-by: Michael Bommarito +Signed-off-by: Anna Schumaker +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/nfs/flexfilelayout/flexfilelayout.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/fs/nfs/flexfilelayout/flexfilelayout.c ++++ b/fs/nfs/flexfilelayout/flexfilelayout.c +@@ -460,6 +460,10 @@ ff_layout_alloc_lseg(struct pnfs_layout_ + if (!p) + goto out_err_free; + fh_count = be32_to_cpup(p); ++ if (fh_count == 0) { ++ rc = -EINVAL; ++ goto out_err_free; ++ } + + fls->mirror_array[i]->fh_versions = + kcalloc(fh_count, sizeof(struct nfs_fh), diff --git a/queue-6.6/series b/queue-6.6/series index 949c161f30..0a9113e8e2 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -19,3 +19,22 @@ slimbus-qcom-ngd-ctrl-correct-pdr-and-ssr-cleanup-ow.patch slimbus-convert-to-platform-remove-callback-returnin.patch slimbus-qcom-ngd-ctrl-register-callbacks-after-creat.patch drm-amd-fix-set-but-not-used-warnings.patch +net-ip_gre-require-cap_net_admin-in-the-device-netns-for-changelink.patch +device-property-initialize-the-remaining-fields-of-fwnode_handle-in-fwnode_init.patch +f2fs-validate-orphan-inode-entry-count.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-potential-deadlock-in-f2fs_balance_fs.patch +f2fs-fix-potential-deadlock-in-gc_merge-path-of-f2fs_balance_fs.patch +f2fs-fix-listxattr-handling-of-corrupted-xattr-entries.patch +kvm-replace-guest-triggerable-bug_on-in-ioeventfd-datamatch-with-get_unaligned.patch +block-avoid-mounting-the-bdev-pseudo-filesystem-in-userspace.patch +i2c-core-fix-irq-domain-leak-on-adapter-registration-failure.patch +i2c-core-fix-hang-on-adapter-registration-failure.patch +i2c-core-fix-null-deref-on-adapter-registration-failure.patch +i2c-core-fix-adapter-debugfs-creation.patch +i2c-core-fix-adapter-registration-race.patch +fbdev-fbcon-fix-out-of-bounds-read-in-err_out-of-fbcon_do_set_font.patch +nfsv4-flexfiles-reject-zero-filehandle-version-count.patch +nfsd-don-t-reset-the-write-verifier-on-a-commit-eagain.patch +apparmor-advertise-the-tcp-fast-open-fix-is-applied.patch