From: Greg Kroah-Hartman Date: Tue, 7 Jul 2026 14:30:43 +0000 (+0200) Subject: 6.18-stable patches X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1c6d7b4bbabf9b39a42a8e3140627ae9e53580fe;p=thirdparty%2Fkernel%2Fstable-queue.git 6.18-stable patches added patches: 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-detect-more-inconsistent-cases-in-sanity_check_node_footer.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-fix-to-do-sanity-check-on-f2fs_get_node_folio_ra.patch f2fs-introduce-f2fs_schedule_timeout.patch f2fs-optimize-trace_f2fs_write_checkpoint-with-enums.patch f2fs-remove-non-uptodate-folio-from-the-page-cache-in-move_data_block.patch f2fs-use-memalloc_retry_wait-as-much-as-possible.patch fbdev-fbcon-fix-out-of-bounds-read-in-err_out-of-fbcon_do_set_font.patch --- diff --git a/queue-6.18/device-property-initialize-the-remaining-fields-of-fwnode_handle-in-fwnode_init.patch b/queue-6.18/device-property-initialize-the-remaining-fields-of-fwnode_handle-in-fwnode_init.patch new file mode 100644 index 0000000000..36f03cc1e2 --- /dev/null +++ b/queue-6.18/device-property-initialize-the-remaining-fields-of-fwnode_handle-in-fwnode_init.patch @@ -0,0 +1,49 @@ +From stable+bounces-270567-greg=kroah.com@vger.kernel.org Thu Jul 2 17:40:20 2026 +From: Sasha Levin +Date: Thu, 2 Jul 2026 11:40:11 -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: <20260702154011.3534248-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 +@@ -210,8 +210,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.18/f2fs-atomic-fix-uaf-issue-on-f2fs_inode_info.atomic_inode.patch b/queue-6.18/f2fs-atomic-fix-uaf-issue-on-f2fs_inode_info.atomic_inode.patch new file mode 100644 index 0000000000..a9e3ff5fb3 --- /dev/null +++ b/queue-6.18/f2fs-atomic-fix-uaf-issue-on-f2fs_inode_info.atomic_inode.patch @@ -0,0 +1,168 @@ +From stable+bounces-271758-greg=kroah.com@vger.kernel.org Fri Jul 3 14:50:00 2026 +From: Sasha Levin +Date: Fri, 3 Jul 2026 08:33:30 -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: <20260703123330.3944793-2-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 +@@ -1208,8 +1208,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 = { +@@ -1224,9 +1224,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)) { +@@ -1287,11 +1300,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_folio: + f2fs_folio_put(folio, true); ++out_iput: ++ if (atomic_inode) ++ iput(atomic_inode); + return err; + } + +@@ -1302,8 +1320,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, +@@ -1325,10 +1343,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; +@@ -1461,6 +1492,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 +@@ -853,10 +853,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.18/f2fs-bound-i_inline_xattr_size-for-non-inline-xattr-inodes.patch b/queue-6.18/f2fs-bound-i_inline_xattr_size-for-non-inline-xattr-inodes.patch new file mode 100644 index 0000000000..01a35748ad --- /dev/null +++ b/queue-6.18/f2fs-bound-i_inline_xattr_size-for-non-inline-xattr-inodes.patch @@ -0,0 +1,76 @@ +From stable+bounces-271795-greg=kroah.com@vger.kernel.org Fri Jul 3 16:09:44 2026 +From: Sasha Levin +Date: Fri, 3 Jul 2026 10:09:34 -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: <20260703140934.18093-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 | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/fs/f2fs/inode.c ++++ b/fs/f2fs/inode.c +@@ -318,9 +318,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=%lx) 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-6.18/f2fs-detect-more-inconsistent-cases-in-sanity_check_node_footer.patch b/queue-6.18/f2fs-detect-more-inconsistent-cases-in-sanity_check_node_footer.patch new file mode 100644 index 0000000000..6501da71a3 --- /dev/null +++ b/queue-6.18/f2fs-detect-more-inconsistent-cases-in-sanity_check_node_footer.patch @@ -0,0 +1,66 @@ +From stable+bounces-271969-greg=kroah.com@vger.kernel.org Sat Jul 4 15:01:16 2026 +From: Sasha Levin +Date: Sat, 4 Jul 2026 09:01:05 -0400 +Subject: f2fs: detect more inconsistent cases in sanity_check_node_footer() +To: stable@vger.kernel.org +Cc: Chao Yu , Jaegeuk Kim , Sasha Levin +Message-ID: <20260704130106.828918-4-sashal@kernel.org> + +From: Chao Yu + +[ Upstream commit 93ffb6c28ff180560d2d7313ac106efcd9e012b8 ] + +Let's enhance sanity_check_node_footer() to detect more inconsistent +cases as below: + +Node Type Node Footer Info +=================== ============================= +NODE_TYPE_REGULAR inode = true and xnode = true +NODE_TYPE_INODE inode = false or xnode = true +NODE_TYPE_XATTR inode = true or xnode = false +NODE_TYPE_NON_INODE inode = false + +Signed-off-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Stable-dep-of: 8712353ed80f ("f2fs: fix to do sanity check on f2fs_get_node_folio_ra()") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/f2fs/node.c | 15 ++++++++++++--- + 1 file changed, 12 insertions(+), 3 deletions(-) + +--- a/fs/f2fs/node.c ++++ b/fs/f2fs/node.c +@@ -1504,20 +1504,29 @@ int f2fs_sanity_check_node_footer(struct + struct folio *folio, pgoff_t nid, + enum node_type ntype, bool in_irq) + { ++ bool is_inode, is_xnode; ++ + if (unlikely(nid != nid_of_node(folio))) + goto out_err; + ++ is_inode = IS_INODE(folio); ++ is_xnode = f2fs_has_xattr_block(ofs_of_node(folio)); ++ + switch (ntype) { ++ case NODE_TYPE_REGULAR: ++ if (is_inode && is_xnode) ++ goto out_err; ++ break; + case NODE_TYPE_INODE: +- if (!IS_INODE(folio)) ++ if (!is_inode || is_xnode) + goto out_err; + break; + case NODE_TYPE_XATTR: +- if (!f2fs_has_xattr_block(ofs_of_node(folio))) ++ if (is_inode || !is_xnode) + goto out_err; + break; + case NODE_TYPE_NON_INODE: +- if (IS_INODE(folio)) ++ if (is_inode) + goto out_err; + break; + default: diff --git a/queue-6.18/f2fs-fix-listxattr-handling-of-corrupted-xattr-entries.patch b/queue-6.18/f2fs-fix-listxattr-handling-of-corrupted-xattr-entries.patch new file mode 100644 index 0000000000..e63e645ba8 --- /dev/null +++ b/queue-6.18/f2fs-fix-listxattr-handling-of-corrupted-xattr-entries.patch @@ -0,0 +1,51 @@ +From stable+bounces-271855-greg=kroah.com@vger.kernel.org Fri Jul 3 20:39:51 2026 +From: Sasha Levin +Date: Fri, 3 Jul 2026 14:39:41 -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: <20260703183941.265158-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.18/f2fs-fix-potential-deadlock-in-f2fs_balance_fs.patch b/queue-6.18/f2fs-fix-potential-deadlock-in-f2fs_balance_fs.patch new file mode 100644 index 0000000000..09de9bb9f5 --- /dev/null +++ b/queue-6.18/f2fs-fix-potential-deadlock-in-f2fs_balance_fs.patch @@ -0,0 +1,253 @@ +From stable+bounces-271839-greg=kroah.com@vger.kernel.org Fri Jul 3 20:03:25 2026 +From: Sasha Levin +Date: Fri, 3 Jul 2026 14:03:16 -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: <20260703180317.196634-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 +@@ -898,6 +898,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 +@@ -4084,6 +4084,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 folio *folio); ++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 +@@ -461,6 +461,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.18/f2fs-fix-potential-deadlock-in-gc_merge-path-of-f2fs_balance_fs.patch b/queue-6.18/f2fs-fix-potential-deadlock-in-gc_merge-path-of-f2fs_balance_fs.patch new file mode 100644 index 0000000000..f904c7a76d --- /dev/null +++ b/queue-6.18/f2fs-fix-potential-deadlock-in-gc_merge-path-of-f2fs_balance_fs.patch @@ -0,0 +1,85 @@ +From stable+bounces-271840-greg=kroah.com@vger.kernel.org Fri Jul 3 20:03:28 2026 +From: Sasha Levin +Date: Fri, 3 Jul 2026 14:03:17 -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: <20260703180317.196634-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 +@@ -443,6 +443,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); +@@ -462,13 +469,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.18/f2fs-fix-to-do-sanity-check-on-f2fs_get_node_folio_ra.patch b/queue-6.18/f2fs-fix-to-do-sanity-check-on-f2fs_get_node_folio_ra.patch new file mode 100644 index 0000000000..3a23b87b79 --- /dev/null +++ b/queue-6.18/f2fs-fix-to-do-sanity-check-on-f2fs_get_node_folio_ra.patch @@ -0,0 +1,115 @@ +From stable+bounces-271971-greg=kroah.com@vger.kernel.org Sat Jul 4 15:01:32 2026 +From: Sasha Levin +Date: Sat, 4 Jul 2026 09:01:06 -0400 +Subject: f2fs: fix to do sanity check on f2fs_get_node_folio_ra() +To: stable@vger.kernel.org +Cc: Chao Yu , stable@kernel.org, syzbot+2488d8d751b27f7ce268@syzkaller.appspotmail.com, Jaegeuk Kim , Sasha Levin +Message-ID: <20260704130106.828918-5-sashal@kernel.org> + +From: Chao Yu + +[ Upstream commit 8712353ed80f87271d732297567dcdbe4b84e8c7 ] + +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: + + 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 +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 +@@ -1533,6 +1533,7 @@ enum node_type { + NODE_TYPE_INODE, + NODE_TYPE_XATTR, + NODE_TYPE_NON_INODE, ++ NODE_TYPE_NON_IXNODE, /* non inode and xnode */ + }; + + +--- a/fs/f2fs/node.c ++++ b/fs/f2fs/node.c +@@ -1529,6 +1529,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; + } +@@ -1622,7 +1626,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-6.18/f2fs-introduce-f2fs_schedule_timeout.patch b/queue-6.18/f2fs-introduce-f2fs_schedule_timeout.patch new file mode 100644 index 0000000000..4f9485a857 --- /dev/null +++ b/queue-6.18/f2fs-introduce-f2fs_schedule_timeout.patch @@ -0,0 +1,174 @@ +From stable+bounces-271967-greg=kroah.com@vger.kernel.org Sat Jul 4 15:01:16 2026 +From: Sasha Levin +Date: Sat, 4 Jul 2026 09:01:03 -0400 +Subject: f2fs: introduce f2fs_schedule_timeout() +To: stable@vger.kernel.org +Cc: Chao Yu , Jaegeuk Kim , Sasha Levin +Message-ID: <20260704130106.828918-2-sashal@kernel.org> + +From: Chao Yu + +[ Upstream commit 76e780d88c771921ea643fb8a6c8d0b08c17cb7b ] + +In f2fs retry logic, we will call f2fs_io_schedule_timeout() to sleep as +uninterruptible state (waiting for IO) for a while, however, in several +paths below, we are not blocked by IO: +- f2fs_write_single_data_page() return -EAGAIN due to racing on cp_rwsem. +- f2fs_flush_device_cache() failed to submit preflush command. +- __issue_discard_cmd_range() sleeps periodically in between two in batch +discard submissions. + +So, in order to reveal state of task more accurate, let's introduce +f2fs_schedule_timeout() and call it in above paths in where we are waiting +for non-IO reasons. + +Then we can get real reason of uninterruptible sleep for a thread in +tracepoint, perfetto, etc. + +Signed-off-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Stable-dep-of: 8712353ed80f ("f2fs: fix to do sanity check on f2fs_get_node_folio_ra()") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/f2fs/checkpoint.c | 4 ++-- + fs/f2fs/compress.c | 4 ++-- + fs/f2fs/data.c | 4 ++-- + fs/f2fs/f2fs.h | 22 +++++++++++++++------- + fs/f2fs/segment.c | 4 ++-- + fs/f2fs/super.c | 2 +- + 6 files changed, 24 insertions(+), 16 deletions(-) + +--- a/fs/f2fs/checkpoint.c ++++ b/fs/f2fs/checkpoint.c +@@ -1330,7 +1330,7 @@ void f2fs_wait_on_all_pages(struct f2fs_ + f2fs_submit_merged_write(sbi, DATA); + + prepare_to_wait(&sbi->cp_wait, &wait, TASK_UNINTERRUPTIBLE); +- io_schedule_timeout(DEFAULT_IO_TIMEOUT); ++ io_schedule_timeout(DEFAULT_SCHEDULE_TIMEOUT); + } + finish_wait(&sbi->cp_wait, &wait); + } +@@ -1986,7 +1986,7 @@ void f2fs_flush_ckpt_thread(struct f2fs_ + + /* Let's wait for the previous dispatched checkpoint. */ + while (atomic_read(&cprc->queued_ckpt)) +- io_schedule_timeout(DEFAULT_IO_TIMEOUT); ++ io_schedule_timeout(DEFAULT_SCHEDULE_TIMEOUT); + } + + void f2fs_init_ckpt_req_control(struct f2fs_sb_info *sbi) +--- a/fs/f2fs/compress.c ++++ b/fs/f2fs/compress.c +@@ -1057,7 +1057,7 @@ static void cancel_cluster_writeback(str + f2fs_submit_merged_write(F2FS_I_SB(cc->inode), DATA); + while (atomic_read(&cic->pending_pages) != + (cc->valid_nr_cpages - submitted + 1)) +- f2fs_io_schedule_timeout(DEFAULT_IO_TIMEOUT); ++ f2fs_io_schedule_timeout(DEFAULT_SCHEDULE_TIMEOUT); + } + + /* Cancel writeback and stay locked. */ +@@ -1582,7 +1582,7 @@ continue_unlock: + */ + if (IS_NOQUOTA(cc->inode)) + goto out; +- f2fs_io_schedule_timeout(DEFAULT_IO_TIMEOUT); ++ f2fs_schedule_timeout(DEFAULT_SCHEDULE_TIMEOUT); + goto retry_write; + } + goto out; +--- a/fs/f2fs/data.c ++++ b/fs/f2fs/data.c +@@ -3214,8 +3214,8 @@ result: + } else if (ret == -EAGAIN) { + ret = 0; + if (wbc->sync_mode == WB_SYNC_ALL) { +- f2fs_io_schedule_timeout( +- DEFAULT_IO_TIMEOUT); ++ f2fs_schedule_timeout( ++ DEFAULT_SCHEDULE_TIMEOUT); + goto retry_write; + } + goto next; +--- a/fs/f2fs/f2fs.h ++++ b/fs/f2fs/f2fs.h +@@ -665,8 +665,8 @@ enum { + + #define DEFAULT_RETRY_IO_COUNT 8 /* maximum retry read IO or flush count */ + +-/* congestion wait timeout value, default: 20ms */ +-#define DEFAULT_IO_TIMEOUT (msecs_to_jiffies(20)) ++/* IO/non-IO congestion wait timeout value, default: 20ms */ ++#define DEFAULT_SCHEDULE_TIMEOUT (msecs_to_jiffies(20)) + + /* timeout value injected, default: 1000ms */ + #define DEFAULT_FAULT_TIMEOUT (msecs_to_jiffies(1000)) +@@ -4940,22 +4940,30 @@ static inline bool f2fs_block_unit_disca + return F2FS_OPTION(sbi).discard_unit == DISCARD_UNIT_BLOCK; + } + +-static inline void f2fs_io_schedule_timeout(long timeout) ++static inline void __f2fs_schedule_timeout(long timeout, bool io) + { + set_current_state(TASK_UNINTERRUPTIBLE); +- io_schedule_timeout(timeout); ++ if (io) ++ io_schedule_timeout(timeout); ++ else ++ schedule_timeout(timeout); + } + ++#define f2fs_io_schedule_timeout(timeout) \ ++ __f2fs_schedule_timeout(timeout, true) ++#define f2fs_schedule_timeout(timeout) \ ++ __f2fs_schedule_timeout(timeout, false) ++ + static inline void f2fs_io_schedule_timeout_killable(long timeout) + { + while (timeout) { + if (fatal_signal_pending(current)) + return; + set_current_state(TASK_UNINTERRUPTIBLE); +- io_schedule_timeout(DEFAULT_IO_TIMEOUT); +- if (timeout <= DEFAULT_IO_TIMEOUT) ++ io_schedule_timeout(DEFAULT_SCHEDULE_TIMEOUT); ++ if (timeout <= DEFAULT_SCHEDULE_TIMEOUT) + return; +- timeout -= DEFAULT_IO_TIMEOUT; ++ timeout -= DEFAULT_SCHEDULE_TIMEOUT; + } + } + +--- a/fs/f2fs/segment.c ++++ b/fs/f2fs/segment.c +@@ -758,7 +758,7 @@ int f2fs_flush_device_cache(struct f2fs_ + do { + ret = __submit_flush_wait(sbi, FDEV(i).bdev); + if (ret) +- f2fs_io_schedule_timeout(DEFAULT_IO_TIMEOUT); ++ f2fs_schedule_timeout(DEFAULT_SCHEDULE_TIMEOUT); + } while (ret && --count); + + if (ret) { +@@ -3480,7 +3480,7 @@ next: + blk_finish_plug(&plug); + mutex_unlock(&dcc->cmd_lock); + trimmed += __wait_all_discard_cmd(sbi, NULL); +- f2fs_io_schedule_timeout(DEFAULT_IO_TIMEOUT); ++ f2fs_schedule_timeout(DEFAULT_SCHEDULE_TIMEOUT); + goto next; + } + skip: +--- a/fs/f2fs/super.c ++++ b/fs/f2fs/super.c +@@ -2656,7 +2656,7 @@ static int f2fs_enable_checkpoint(struct + /* we should flush all the data to keep data consistency */ + while (get_pages(sbi, F2FS_DIRTY_DATA)) { + writeback_inodes_sb_nr(sbi->sb, nr_pages, WB_REASON_SYNC); +- f2fs_io_schedule_timeout(DEFAULT_IO_TIMEOUT); ++ f2fs_io_schedule_timeout(DEFAULT_SCHEDULE_TIMEOUT); + + if (f2fs_time_over(sbi, ENABLE_TIME)) + break; diff --git a/queue-6.18/f2fs-optimize-trace_f2fs_write_checkpoint-with-enums.patch b/queue-6.18/f2fs-optimize-trace_f2fs_write_checkpoint-with-enums.patch new file mode 100644 index 0000000000..67635d48c8 --- /dev/null +++ b/queue-6.18/f2fs-optimize-trace_f2fs_write_checkpoint-with-enums.patch @@ -0,0 +1,138 @@ +From stable+bounces-271968-greg=kroah.com@vger.kernel.org Sat Jul 4 15:01:19 2026 +From: Sasha Levin +Date: Sat, 4 Jul 2026 09:01:04 -0400 +Subject: f2fs: optimize trace_f2fs_write_checkpoint with enums +To: stable@vger.kernel.org +Cc: YH Lin , Chao Yu , Jaegeuk Kim , Sasha Levin +Message-ID: <20260704130106.828918-3-sashal@kernel.org> + +From: YH Lin + +[ Upstream commit 8d1cb17aca466b361cca17834b8bb1cf3e3d1818 ] + +This patch optimizes the tracepoint by replacing these hardcoded strings +with a new enumeration f2fs_cp_phase. + +1.Defines enum f2fs_cp_phase with values for each checkpoint phase. +2.Updates trace_f2fs_write_checkpoint to accept a u16 phase argument +instead of a string pointer. +3.Uses __print_symbolic in TP_printk to convert the enum values +back to their corresponding strings for human-readable trace output. + +This change reduces the storage overhead for each trace event +by replacing a variable-length string with a 2-byte integer, +while maintaining the same readable output in ftrace. + +Signed-off-by: YH Lin +Reviewed-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Stable-dep-of: 8712353ed80f ("f2fs: fix to do sanity check on f2fs_get_node_folio_ra()") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/f2fs/checkpoint.c | 6 +++--- + fs/f2fs/f2fs.h | 6 ++++++ + include/trace/events/f2fs.h | 19 ++++++++++++++----- + 3 files changed, 23 insertions(+), 8 deletions(-) + +--- a/fs/f2fs/checkpoint.c ++++ b/fs/f2fs/checkpoint.c +@@ -1685,7 +1685,7 @@ int f2fs_write_checkpoint(struct f2fs_sb + goto out; + } + +- trace_f2fs_write_checkpoint(sbi->sb, cpc->reason, "start block_ops"); ++ trace_f2fs_write_checkpoint(sbi->sb, cpc->reason, CP_PHASE_START_BLOCK_OPS); + + err = block_operations(sbi); + if (err) +@@ -1693,7 +1693,7 @@ int f2fs_write_checkpoint(struct f2fs_sb + + stat_cp_time(cpc, CP_TIME_OP_LOCK); + +- trace_f2fs_write_checkpoint(sbi->sb, cpc->reason, "finish block_ops"); ++ trace_f2fs_write_checkpoint(sbi->sb, cpc->reason, CP_PHASE_FINISH_BLOCK_OPS); + + f2fs_flush_merged_writes(sbi); + +@@ -1759,7 +1759,7 @@ stop: + + /* update CP_TIME to trigger checkpoint periodically */ + f2fs_update_time(sbi, CP_TIME); +- trace_f2fs_write_checkpoint(sbi->sb, cpc->reason, "finish checkpoint"); ++ trace_f2fs_write_checkpoint(sbi->sb, cpc->reason, CP_PHASE_FINISH_CHECKPOINT); + out: + if (cpc->reason != CP_RESIZE) + f2fs_up_write(&sbi->cp_global_sem); +--- a/fs/f2fs/f2fs.h ++++ b/fs/f2fs/f2fs.h +@@ -319,6 +319,12 @@ struct cp_control { + struct cp_stats stats; + }; + ++enum f2fs_cp_phase { ++ CP_PHASE_START_BLOCK_OPS, ++ CP_PHASE_FINISH_BLOCK_OPS, ++ CP_PHASE_FINISH_CHECKPOINT, ++}; ++ + /* + * indicate meta/data type + */ +--- a/include/trace/events/f2fs.h ++++ b/include/trace/events/f2fs.h +@@ -50,6 +50,9 @@ TRACE_DEFINE_ENUM(CP_PAUSE); + TRACE_DEFINE_ENUM(CP_RESIZE); + TRACE_DEFINE_ENUM(EX_READ); + TRACE_DEFINE_ENUM(EX_BLOCK_AGE); ++TRACE_DEFINE_ENUM(CP_PHASE_START_BLOCK_OPS); ++TRACE_DEFINE_ENUM(CP_PHASE_FINISH_BLOCK_OPS); ++TRACE_DEFINE_ENUM(CP_PHASE_FINISH_CHECKPOINT); + + #define show_block_type(type) \ + __print_symbolic(type, \ +@@ -175,6 +178,12 @@ TRACE_DEFINE_ENUM(EX_BLOCK_AGE); + #define S_ALL_PERM (S_ISUID | S_ISGID | S_ISVTX | \ + S_IRWXU | S_IRWXG | S_IRWXO) + ++#define show_cp_phase(phase) \ ++ __print_symbolic(phase, \ ++ { CP_PHASE_START_BLOCK_OPS, "start block_ops" }, \ ++ { CP_PHASE_FINISH_BLOCK_OPS, "finish block_ops" }, \ ++ { CP_PHASE_FINISH_CHECKPOINT, "finish checkpoint" }) ++ + struct f2fs_sb_info; + struct f2fs_io_info; + struct extent_info; +@@ -1541,26 +1550,26 @@ TRACE_EVENT(f2fs_readpages, + + TRACE_EVENT(f2fs_write_checkpoint, + +- TP_PROTO(struct super_block *sb, int reason, const char *msg), ++ TP_PROTO(struct super_block *sb, int reason, u16 phase), + +- TP_ARGS(sb, reason, msg), ++ TP_ARGS(sb, reason, phase), + + TP_STRUCT__entry( + __field(dev_t, dev) + __field(int, reason) +- __string(dest_msg, msg) ++ __field(u16, phase) + ), + + TP_fast_assign( + __entry->dev = sb->s_dev; + __entry->reason = reason; +- __assign_str(dest_msg); ++ __entry->phase = phase; + ), + + TP_printk("dev = (%d,%d), checkpoint for %s, state = %s", + show_dev(__entry->dev), + show_cpreason(__entry->reason), +- __get_str(dest_msg)) ++ show_cp_phase(__entry->phase)) + ); + + DECLARE_EVENT_CLASS(f2fs_discard, diff --git a/queue-6.18/f2fs-remove-non-uptodate-folio-from-the-page-cache-in-move_data_block.patch b/queue-6.18/f2fs-remove-non-uptodate-folio-from-the-page-cache-in-move_data_block.patch new file mode 100644 index 0000000000..201fadeb06 --- /dev/null +++ b/queue-6.18/f2fs-remove-non-uptodate-folio-from-the-page-cache-in-move_data_block.patch @@ -0,0 +1,44 @@ +From stable+bounces-271757-greg=kroah.com@vger.kernel.org Fri Jul 3 14:49:57 2026 +From: Sasha Levin +Date: Fri, 3 Jul 2026 08:33:29 -0400 +Subject: f2fs: remove non-uptodate folio from the page cache in move_data_block +To: stable@vger.kernel.org +Cc: Yongpeng Yang , Yunlei He , Chao Yu , Jaegeuk Kim , Sasha Levin +Message-ID: <20260703123330.3944793-1-sashal@kernel.org> + +From: Yongpeng Yang + +[ Upstream commit 9609dd704725a40cd63d915f2ab6c44248a44598 ] + +During data movement, move_data_block acquires file folio without +triggering a file read. Such folio are typically not uptodate, they need +to be removed from the page cache after gc complete. This patch marks +folio with the PG_dropbehind flag and uses folio_end_dropbehind to +remove folio from the page cache. + +Signed-off-by: Yunlei He +Signed-off-by: Yongpeng Yang +Reviewed-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Stable-dep-of: e0288584baa5 ("f2fs: atomic: fix UAF issue on f2fs_inode_info.atomic_inode") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/f2fs/gc.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/fs/f2fs/gc.c ++++ b/fs/f2fs/gc.c +@@ -1456,7 +1456,11 @@ up_out: + put_out: + f2fs_put_dnode(&dn); + out: +- f2fs_folio_put(folio, true); ++ if (!folio_test_uptodate(folio)) ++ __folio_set_dropbehind(folio); ++ folio_unlock(folio); ++ folio_end_dropbehind(folio); ++ folio_put(folio); + return err; + } + diff --git a/queue-6.18/f2fs-use-memalloc_retry_wait-as-much-as-possible.patch b/queue-6.18/f2fs-use-memalloc_retry_wait-as-much-as-possible.patch new file mode 100644 index 0000000000..2eaca6e9c4 --- /dev/null +++ b/queue-6.18/f2fs-use-memalloc_retry_wait-as-much-as-possible.patch @@ -0,0 +1,47 @@ +From stable+bounces-271966-greg=kroah.com@vger.kernel.org Sat Jul 4 15:01:12 2026 +From: Sasha Levin +Date: Sat, 4 Jul 2026 09:01:02 -0400 +Subject: f2fs: use memalloc_retry_wait() as much as possible +To: stable@vger.kernel.org +Cc: Chao Yu , Jaegeuk Kim , Sasha Levin +Message-ID: <20260704130106.828918-1-sashal@kernel.org> + +From: Chao Yu + +[ Upstream commit 30a8496694f1a93328e5d7f19206380346918b5a ] + +memalloc_retry_wait() is recommended in memory allocation retry logic, +use it as much as possible. + +Signed-off-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Stable-dep-of: 8712353ed80f ("f2fs: fix to do sanity check on f2fs_get_node_folio_ra()") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/f2fs/segment.c | 2 +- + fs/f2fs/super.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +--- a/fs/f2fs/segment.c ++++ b/fs/f2fs/segment.c +@@ -234,7 +234,7 @@ retry: + err = f2fs_get_dnode_of_data(&dn, index, ALLOC_NODE); + if (err) { + if (err == -ENOMEM) { +- f2fs_io_schedule_timeout(DEFAULT_IO_TIMEOUT); ++ memalloc_retry_wait(GFP_NOFS); + goto retry; + } + return err; +--- a/fs/f2fs/super.c ++++ b/fs/f2fs/super.c +@@ -3128,7 +3128,7 @@ retry: + &folio, &fsdata); + if (unlikely(err)) { + if (err == -ENOMEM) { +- f2fs_io_schedule_timeout(DEFAULT_IO_TIMEOUT); ++ memalloc_retry_wait(GFP_NOFS); + goto retry; + } + set_sbi_flag(F2FS_SB(sb), SBI_QUOTA_NEED_REPAIR); diff --git a/queue-6.18/fbdev-fbcon-fix-out-of-bounds-read-in-err_out-of-fbcon_do_set_font.patch b/queue-6.18/fbdev-fbcon-fix-out-of-bounds-read-in-err_out-of-fbcon_do_set_font.patch new file mode 100644 index 0000000000..24e55860b0 --- /dev/null +++ b/queue-6.18/fbdev-fbcon-fix-out-of-bounds-read-in-err_out-of-fbcon_do_set_font.patch @@ -0,0 +1,70 @@ +From stable+bounces-271975-greg=kroah.com@vger.kernel.org Sat Jul 4 17:19:57 2026 +From: Sasha Levin +Date: Sat, 4 Jul 2026 11:19:43 -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: <20260704151943.1019054-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 +@@ -2422,6 +2422,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); +@@ -2475,6 +2476,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.18/series b/queue-6.18/series index bafe9a3f46..3a532f89c6 100644 --- a/queue-6.18/series +++ b/queue-6.18/series @@ -5,3 +5,16 @@ nfsd-release-layout-stid-on-setlease-failure.patch rust-str-use-the-kernel-vertical-imports-style.patch rust-str-clean-unused-import-for-rust-1.98.patch userfaultfd-gate-must_wait-writability-check-on-pte_.patch +device-property-initialize-the-remaining-fields-of-fwnode_handle-in-fwnode_init.patch +f2fs-remove-non-uptodate-folio-from-the-page-cache-in-move_data_block.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 +f2fs-use-memalloc_retry_wait-as-much-as-possible.patch +f2fs-introduce-f2fs_schedule_timeout.patch +f2fs-optimize-trace_f2fs_write_checkpoint-with-enums.patch +f2fs-detect-more-inconsistent-cases-in-sanity_check_node_footer.patch +f2fs-fix-to-do-sanity-check-on-f2fs_get_node_folio_ra.patch +fbdev-fbcon-fix-out-of-bounds-read-in-err_out-of-fbcon_do_set_font.patch