]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.18-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 7 Jul 2026 14:30:43 +0000 (16:30 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 7 Jul 2026 14:30:43 +0000 (16:30 +0200)
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

14 files changed:
queue-6.18/device-property-initialize-the-remaining-fields-of-fwnode_handle-in-fwnode_init.patch [new file with mode: 0644]
queue-6.18/f2fs-atomic-fix-uaf-issue-on-f2fs_inode_info.atomic_inode.patch [new file with mode: 0644]
queue-6.18/f2fs-bound-i_inline_xattr_size-for-non-inline-xattr-inodes.patch [new file with mode: 0644]
queue-6.18/f2fs-detect-more-inconsistent-cases-in-sanity_check_node_footer.patch [new file with mode: 0644]
queue-6.18/f2fs-fix-listxattr-handling-of-corrupted-xattr-entries.patch [new file with mode: 0644]
queue-6.18/f2fs-fix-potential-deadlock-in-f2fs_balance_fs.patch [new file with mode: 0644]
queue-6.18/f2fs-fix-potential-deadlock-in-gc_merge-path-of-f2fs_balance_fs.patch [new file with mode: 0644]
queue-6.18/f2fs-fix-to-do-sanity-check-on-f2fs_get_node_folio_ra.patch [new file with mode: 0644]
queue-6.18/f2fs-introduce-f2fs_schedule_timeout.patch [new file with mode: 0644]
queue-6.18/f2fs-optimize-trace_f2fs_write_checkpoint-with-enums.patch [new file with mode: 0644]
queue-6.18/f2fs-remove-non-uptodate-folio-from-the-page-cache-in-move_data_block.patch [new file with mode: 0644]
queue-6.18/f2fs-use-memalloc_retry_wait-as-much-as-possible.patch [new file with mode: 0644]
queue-6.18/fbdev-fbcon-fix-out-of-bounds-read-in-err_out-of-fbcon_do_set_font.patch [new file with mode: 0644]
queue-6.18/series

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 (file)
index 0000000..36f03cc
--- /dev/null
@@ -0,0 +1,49 @@
+From stable+bounces-270567-greg=kroah.com@vger.kernel.org Thu Jul  2 17:40:20 2026
+From: Sasha Levin <sashal@kernel.org>
+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 <bartosz.golaszewski@oss.qualcomm.com>, Sakari Ailus <sakari.ailus@linux.intel.com>, "Rafael J. Wysocki (Intel)" <rafael@kernel.org>, Andy Shevchenko <andriy.shevchenko@linux.intel.com>, Danilo Krummrich <dakr@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260702154011.3534248-1-sashal@kernel.org>
+
+From: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+
+[ 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 <sakari.ailus@linux.intel.com>
+Reviewed-by: Rafael J. Wysocki (Intel) <rafael@kernel.org>
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Link: https://patch.msgid.link/20260511074927.9473-1-bartosz.golaszewski@oss.qualcomm.com
+[ Fix typo in commit message. - Danilo ]
+Signed-off-by: Danilo Krummrich <dakr@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..a9e3ff5
--- /dev/null
@@ -0,0 +1,168 @@
+From stable+bounces-271758-greg=kroah.com@vger.kernel.org Fri Jul  3 14:50:00 2026
+From: Sasha Levin <sashal@kernel.org>
+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 <chao@kernel.org>, stable@kernel.org, Daeho Jeong <daehojeong@google.com>, Sunmin Jeong <s_min.jeong@samsung.com>, Jaegeuk Kim <jaegeuk@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260703123330.3944793-2-sashal@kernel.org>
+
+From: Chao Yu <chao@kernel.org>
+
+[ 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 <daehojeong@google.com>
+Cc: Sunmin Jeong <s_min.jeong@samsung.com>
+Fixes: 3db1de0e582c ("f2fs: change the current atomic write way")
+Fixes: f18d00769336 ("f2fs: use meta inode for GC of COW file")
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/gc.c    |   50 ++++++++++++++++++++++++++++++++++++++++++--------
+ fs/f2fs/inode.c |   11 ++++++++---
+ 2 files changed, 50 insertions(+), 11 deletions(-)
+
+--- a/fs/f2fs/gc.c
++++ b/fs/f2fs/gc.c
+@@ -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 (file)
index 0000000..01a3574
--- /dev/null
@@ -0,0 +1,76 @@
+From stable+bounces-271795-greg=kroah.com@vger.kernel.org Fri Jul  3 16:09:44 2026
+From: Sasha Levin <sashal@kernel.org>
+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 <hexlabsecurity@proton.me>, Chao Yu <chao@kernel.org>, Jaegeuk Kim <jaegeuk@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260703140934.18093-1-sashal@kernel.org>
+
+From: Bryam Vargas <hexlabsecurity@proton.me>
+
+[ Upstream commit 378acf3cf19b6af6cba55e8dd1154c4e1504bae8 ]
+
+When the flexible_inline_xattr feature is enabled, do_read_inode() loads
+the on-disk i_inline_xattr_size unconditionally:
+
+       if (f2fs_sb_has_flexible_inline_xattr(sbi))
+               fi->i_inline_xattr_size = le16_to_cpu(ri->i_inline_xattr_size);
+
+but sanity_check_inode() only range-checks it when the inode also has the
+FI_INLINE_XATTR flag set.  An inode that carries an inline dentry or inline
+data but not FI_INLINE_XATTR -- the normal layout for an inline
+directory -- therefore keeps a fully attacker-controlled
+i_inline_xattr_size from a crafted image.
+
+get_inline_xattr_addrs() returns that value with no flag gating, so it
+feeds the inode geometry:
+
+       MAX_INLINE_DATA()  = 4 * (CUR_ADDRS_PER_INODE - i_inline_xattr_size - 1)
+       NR_INLINE_DENTRY() = MAX_INLINE_DATA() * BITS_PER_BYTE / (...)
+       addrs_per_page()   = CUR_ADDRS_PER_INODE - i_inline_xattr_size
+
+A large i_inline_xattr_size drives MAX_INLINE_DATA() and NR_INLINE_DENTRY()
+negative, so make_dentry_ptr_inline() sets d->max (int) to a negative
+value.  The inline directory walk then compares an unsigned long bit_pos
+against that negative d->max, which is promoted to a huge unsigned bound,
+and reads far past the inline area:
+
+       while (bit_pos < d->max)                /* fs/f2fs/dir.c */
+               ... test_bit_le(bit_pos, d->bitmap) / d->dentry[bit_pos] ...
+
+Mounting a crafted image and reading such a directory triggers an
+out-of-bounds read in f2fs_fill_dentries(); the same underflow also
+corrupts ADDRS_PER_INODE for regular files.
+
+Validate i_inline_xattr_size against MAX_INLINE_XATTR_SIZE whenever the
+flexible_inline_xattr feature is enabled -- i.e. whenever the value is
+loaded from disk and consumed -- and keep the lower MIN_INLINE_XATTR_SIZE
+bound gated on inodes that actually carry an inline xattr, so legitimate
+inodes with i_inline_xattr_size == 0 are still accepted.
+
+Cc: stable@vger.kernel.org
+Fixes: 6afc662e68b5 ("f2fs: support flexible inline xattr size")
+Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me>
+Reviewed-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/inode.c |    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 (file)
index 0000000..6501da7
--- /dev/null
@@ -0,0 +1,66 @@
+From stable+bounces-271969-greg=kroah.com@vger.kernel.org Sat Jul  4 15:01:16 2026
+From: Sasha Levin <sashal@kernel.org>
+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 <chao@kernel.org>, Jaegeuk Kim <jaegeuk@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260704130106.828918-4-sashal@kernel.org>
+
+From: Chao Yu <chao@kernel.org>
+
+[ 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 <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Stable-dep-of: 8712353ed80f ("f2fs: fix to do sanity check on f2fs_get_node_folio_ra()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..e63e645
--- /dev/null
@@ -0,0 +1,51 @@
+From stable+bounces-271855-greg=kroah.com@vger.kernel.org Fri Jul  3 20:39:51 2026
+From: Sasha Levin <sashal@kernel.org>
+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 <iganschel@gmail.com>, stable@kernel.org, Chao Yu <chao@kernel.org>, Jaegeuk Kim <jaegeuk@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260703183941.265158-1-sashal@kernel.org>
+
+From: Keshav Verma <iganschel@gmail.com>
+
+[ Upstream commit 5ef5bc304f23c3fe255d4936472378dcb74d0e94 ]
+
+Validate the xattr entry before reading its fields in f2fs_listxattr().
+Return -EFSCORRUPTED when the entry is outside the valid xattr storage
+area instead of returning a successful partial result.
+
+Fixes: 688078e7f36c ("f2fs: fix to avoid memory leakage in f2fs_listxattr")
+Cc: stable@kernel.org
+Reviewed-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Keshav Verma <iganschel@gmail.com>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/xattr.c |    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 (file)
index 0000000..09de9bb
--- /dev/null
@@ -0,0 +1,253 @@
+From stable+bounces-271839-greg=kroah.com@vger.kernel.org Fri Jul  3 20:03:25 2026
+From: Sasha Levin <sashal@kernel.org>
+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 <ruipengqi3@gmail.com>, Chao Yu <chao@kernel.org>, Jaegeuk Kim <jaegeuk@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260703180317.196634-1-sashal@kernel.org>
+
+From: Ruipeng Qi <ruipengqi3@gmail.com>
+
+[ Upstream commit dd3114870771562036fdcf5abe813956f36d224d ]
+
+When the f2fs filesystem space is nearly exhausted, we encounter deadlock
+issues as below:
+
+INFO: task A:1890 blocked for more than 120 seconds.
+      Tainted: G           O       6.12.41-g3fe07ddf05ab #1
+"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
+task:A    state:D stack:0     pid:1890  tgid:1626  ppid:1153   flags:0x00000204
+Call trace:
+ __switch_to+0xf4/0x158
+ __schedule+0x27c/0x908
+ schedule+0x3c/0x118
+ io_schedule+0x44/0x68
+ folio_wait_bit_common+0x174/0x370
+ folio_wait_bit+0x20/0x38
+ folio_wait_writeback+0x54/0xc8
+ truncate_inode_partial_folio+0x70/0x1e0
+ truncate_inode_pages_range+0x1b0/0x450
+ truncate_pagecache+0x54/0x88
+ f2fs_file_write_iter+0x3e8/0xb80
+ do_iter_readv_writev+0xf0/0x1e0
+ vfs_writev+0x138/0x2c8
+ do_writev+0x88/0x130
+ __arm64_sys_writev+0x28/0x40
+ invoke_syscall+0x50/0x120
+ el0_svc_common.constprop.0+0xc8/0xf0
+ do_el0_svc+0x24/0x38
+ el0_svc+0x30/0xf8
+ el0t_64_sync_handler+0x120/0x130
+ el0t_64_sync+0x190/0x198
+
+INFO: task kworker/u8:11:2680853 blocked for more than 120 seconds.
+      Tainted: G           O       6.12.41-g3fe07ddf05ab #1
+"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
+task:kworker/u8:11   state:D stack:0     pid:2680853 tgid:2680853 ppid:2      flags:0x00000208
+Workqueue: writeback wb_workfn (flush-254:0)
+Call trace:
+ __switch_to+0xf4/0x158
+ __schedule+0x27c/0x908
+ schedule+0x3c/0x118
+ io_schedule+0x44/0x68
+ folio_wait_bit_common+0x174/0x370
+ __filemap_get_folio+0x214/0x348
+ pagecache_get_page+0x20/0x70
+ f2fs_get_read_data_page+0x150/0x3e8
+ f2fs_get_lock_data_page+0x2c/0x160
+ move_data_page+0x50/0x478
+ do_garbage_collect+0xd38/0x1528
+ f2fs_gc+0x240/0x7e0
+ f2fs_balance_fs+0x1a0/0x208
+ f2fs_write_single_data_page+0x6e4/0x730
+ f2fs_write_cache_pages+0x378/0x9b0
+ f2fs_write_data_pages+0x2e4/0x388
+ do_writepages+0x8c/0x2c8
+ __writeback_single_inode+0x4c/0x498
+ writeback_sb_inodes+0x234/0x4a8
+ __writeback_inodes_wb+0x58/0x118
+ wb_writeback+0x2f8/0x3c0
+ wb_workfn+0x2c4/0x508
+ process_one_work+0x180/0x408
+ worker_thread+0x258/0x368
+ kthread+0x118/0x128
+ ret_from_fork+0x10/0x200
+
+INFO: task kworker/u8:8:2641297 blocked for more than 120 seconds.
+      Tainted: G           O       6.12.41-g3fe07ddf05ab #1
+"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
+task:kworker/u8:8    state:D stack:0     pid:2641297 tgid:2641297 ppid:2      flags:0x00000208
+Workqueue: writeback wb_workfn (flush-254:0)
+Call trace:
+ __switch_to+0xf4/0x158
+ __schedule+0x27c/0x908
+ rt_mutex_schedule+0x30/0x60
+ __rt_mutex_slowlock_locked.constprop.0+0x460/0x8a8
+ rwbase_write_lock+0x24c/0x378
+ down_write+0x1c/0x30
+ f2fs_balance_fs+0x184/0x208
+ f2fs_write_inode+0xf4/0x328
+ __writeback_single_inode+0x370/0x498
+ writeback_sb_inodes+0x234/0x4a8
+ __writeback_inodes_wb+0x58/0x118
+ wb_writeback+0x2f8/0x3c0
+ wb_workfn+0x2c4/0x508
+ process_one_work+0x180/0x408
+ worker_thread+0x258/0x368
+ kthread+0x118/0x128
+ ret_from_fork+0x10/0x20
+
+INFO: task B:1902 blocked for more than 120 seconds.
+      Tainted: G           O       6.12.41-g3fe07ddf05ab #1
+"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
+task:B     state:D stack:0     pid:1902  tgid:1626  ppid:1153   flags:0x0000020c
+Call trace:
+ __switch_to+0xf4/0x158
+ __schedule+0x27c/0x908
+ rt_mutex_schedule+0x30/0x60
+ __rt_mutex_slowlock_locked.constprop.0+0x460/0x8a8
+ rwbase_write_lock+0x24c/0x378
+ down_write+0x1c/0x30
+ f2fs_balance_fs+0x184/0x208
+ f2fs_map_blocks+0x94c/0x1110
+ f2fs_file_write_iter+0x228/0xb80
+ do_iter_readv_writev+0xf0/0x1e0
+ vfs_writev+0x138/0x2c8
+ do_writev+0x88/0x130
+ __arm64_sys_writev+0x28/0x40
+ invoke_syscall+0x50/0x120
+ el0_svc_common.constprop.0+0xc8/0xf0
+ do_el0_svc+0x24/0x38
+ el0_svc+0x30/0xf8
+ el0t_64_sync_handler+0x120/0x130
+ el0t_64_sync+0x190/0x198
+
+INFO: task sync:2769849 blocked for more than 120 seconds.
+      Tainted: G           O       6.12.41-g3fe07ddf05ab #1
+"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
+task:sync            state:D stack:0     pid:2769849 tgid:2769849 ppid:736    flags:0x0000020c
+Call trace:
+ __switch_to+0xf4/0x158
+ __schedule+0x27c/0x908
+ schedule+0x3c/0x118
+ wb_wait_for_completion+0xb0/0xe8
+ sync_inodes_sb+0xc8/0x2b0
+ sync_inodes_one_sb+0x24/0x38
+ iterate_supers+0xa8/0x138
+ ksys_sync+0x54/0xc8
+ __arm64_sys_sync+0x18/0x30
+ invoke_syscall+0x50/0x120
+ el0_svc_common.constprop.0+0xc8/0xf0
+ do_el0_svc+0x24/0x38
+ el0_svc+0x30/0xf8
+ el0t_64_sync_handler+0x120/0x130
+ el0t_64_sync+0x190/0x198
+
+The root cause is a potential deadlock between the following tasks:
+
+kworker/u8:11                          Thread A
+- f2fs_write_single_data_page
+ - f2fs_do_write_data_page
+  - folio_start_writeback(X)
+  - f2fs_outplace_write_data
+   - bio_add_folio(X)
+ - folio_unlock(X)
+                                       - truncate_inode_pages_range
+                                        - __filemap_get_folio(X, FGP_LOCK)
+                                        - truncate_inode_partial_folio(X)
+                                         - folio_wait_writeback(X)
+ - f2fs_balance_fs
+  - f2fs_gc
+   - do_garbage_collect
+    - move_data_page
+     - f2fs_get_lock_data_page
+      - __filemap_get_folio(X, FGP_LOCK)
+
+Both threads try to access folio X. Thread A holds the lock but waits
+for writeback, while kworker waits for the lock. This causes a deadlock.
+
+Other threads also enter D state, waiting for locks such as gc_lock and
+writepages.
+
+OPU/IPU DATA folio are all affected by this issue. To avoid such
+potential deadlocks, always commit these cached folios before
+triggering f2fs_gc() in f2fs_balance_fs().
+
+Suggested-by: Chao Yu <chao@kernel.org>
+Reviewed-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Ruipeng Qi <ruipengqi3@gmail.com>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Stable-dep-of: 8b4468ec023d ("f2fs: fix potential deadlock in gc_merge path of f2fs_balance_fs()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/data.c    |   29 +++++++++++++++++++++++++++++
+ fs/f2fs/f2fs.h    |    1 +
+ fs/f2fs/segment.c |    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 (file)
index 0000000..f904c7a
--- /dev/null
@@ -0,0 +1,85 @@
+From stable+bounces-271840-greg=kroah.com@vger.kernel.org Fri Jul  3 20:03:28 2026
+From: Sasha Levin <sashal@kernel.org>
+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 <chao@kernel.org>, stable@kernel.org, Ruipeng Qi <ruipengqi3@gmail.com>, Chao Yu <chaseyu@google.com>, Jaegeuk Kim <jaegeuk@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260703180317.196634-2-sashal@kernel.org>
+
+From: Chao Yu <chao@kernel.org>
+
+[ 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 <ruipengqi3@gmail.com>
+Reported: Sandeep Dhavale <dhavale@google.com>
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Chao Yu <chaseyu@google.com>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/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 (file)
index 0000000..3a23b87
--- /dev/null
@@ -0,0 +1,115 @@
+From stable+bounces-271971-greg=kroah.com@vger.kernel.org Sat Jul  4 15:01:32 2026
+From: Sasha Levin <sashal@kernel.org>
+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 <chao@kernel.org>, stable@kernel.org, syzbot+2488d8d751b27f7ce268@syzkaller.appspotmail.com, Jaegeuk Kim <jaegeuk@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260704130106.828918-5-sashal@kernel.org>
+
+From: Chao Yu <chao@kernel.org>
+
+[ 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:
+ <TASK>
+ f2fs_truncate_blocks+0x10a/0x300 fs/f2fs/file.c:882
+ f2fs_truncate+0x471/0x7c0 fs/f2fs/file.c:940
+ f2fs_evict_inode+0xa3f/0x1ac0 fs/f2fs/inode.c:907
+ evict+0x61e/0xb10 fs/inode.c:841
+ f2fs_fill_super+0x5f43/0x78f0 fs/f2fs/super.c:5224
+ get_tree_bdev_flags+0x431/0x4f0 fs/super.c:1694
+ vfs_get_tree+0x92/0x2a0 fs/super.c:1754
+ fc_mount fs/namespace.c:1193 [inline]
+ do_new_mount_fc fs/namespace.c:3758 [inline]
+ do_new_mount+0x341/0xd30 fs/namespace.c:3834
+ do_mount fs/namespace.c:4167 [inline]
+ __do_sys_mount fs/namespace.c:4383 [inline]
+ __se_sys_mount+0x31d/0x420 fs/namespace.c:4360
+ do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
+ do_syscall_64+0x15f/0xf80 arch/x86/entry/syscall_64.c:94
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+       count = ADDRS_PER_PAGE(dn.node_folio, inode);
+
+       count -= dn.ofs_in_node;
+       f2fs_bug_on(sbi, count < 0);
+
+The fuzz test will trigger above bug_on in f2fs.
+
+The root cause should be: in the corrupted inode, there is a direct node
+which has the same ino and nid in its footer, so in f2fs_do_truncate_blocks(),
+after f2fs_get_dnode_of_data() finds such dnode:
+1) ADDRS_PER_PAGE(dn.node_folio, inode) will return 923
+2) once dn.ofs_in_node points to addr[923, 1017]
+Then it will trigger the system panic.
+
+Let's introduce NODE_TYPE_NON_IXNODE to indicate current node should
+not be an inode or xattr node, and then use it in below path to detect
+inconsistent node chain in inode mapping table:
+
+- f2fs_do_truncate_blocks
+ - f2fs_get_dnode_of_data
+  - f2fs_get_node_folio_ra
+   -  __get_node_folio
+    - f2fs_sanity_check_node_footer
+     - case NODE_TYPE_NON_IXNODE -> check whether it is inode|xnode
+
+Cc: stable@kernel.org
+Reported-by: syzbot+2488d8d751b27f7ce268@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/all/69fa3697.170a0220.59368.0018.GAE@google.com
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/f2fs.h |    1 +
+ fs/f2fs/node.c |    6 +++++-
+ 2 files changed, 6 insertions(+), 1 deletion(-)
+
+--- a/fs/f2fs/f2fs.h
++++ b/fs/f2fs/f2fs.h
+@@ -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 (file)
index 0000000..4f9485a
--- /dev/null
@@ -0,0 +1,174 @@
+From stable+bounces-271967-greg=kroah.com@vger.kernel.org Sat Jul  4 15:01:16 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat,  4 Jul 2026 09:01:03 -0400
+Subject: f2fs: introduce f2fs_schedule_timeout()
+To: stable@vger.kernel.org
+Cc: Chao Yu <chao@kernel.org>, Jaegeuk Kim <jaegeuk@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260704130106.828918-2-sashal@kernel.org>
+
+From: Chao Yu <chao@kernel.org>
+
+[ 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 <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Stable-dep-of: 8712353ed80f ("f2fs: fix to do sanity check on f2fs_get_node_folio_ra()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..67635d4
--- /dev/null
@@ -0,0 +1,138 @@
+From stable+bounces-271968-greg=kroah.com@vger.kernel.org Sat Jul  4 15:01:19 2026
+From: Sasha Levin <sashal@kernel.org>
+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 <yhli@google.com>, Chao Yu <chao@kernel.org>, Jaegeuk Kim <jaegeuk@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260704130106.828918-3-sashal@kernel.org>
+
+From: YH Lin <yhli@google.com>
+
+[ 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 <yhli@google.com>
+Reviewed-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Stable-dep-of: 8712353ed80f ("f2fs: fix to do sanity check on f2fs_get_node_folio_ra()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..201fade
--- /dev/null
@@ -0,0 +1,44 @@
+From stable+bounces-271757-greg=kroah.com@vger.kernel.org Fri Jul  3 14:49:57 2026
+From: Sasha Levin <sashal@kernel.org>
+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 <yangyongpeng@xiaomi.com>, Yunlei He <heyunlei@xiaomi.com>, Chao Yu <chao@kernel.org>, Jaegeuk Kim <jaegeuk@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260703123330.3944793-1-sashal@kernel.org>
+
+From: Yongpeng Yang <yangyongpeng@xiaomi.com>
+
+[ 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 <heyunlei@xiaomi.com>
+Signed-off-by: Yongpeng Yang <yangyongpeng@xiaomi.com>
+Reviewed-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Stable-dep-of: e0288584baa5 ("f2fs: atomic: fix UAF issue on f2fs_inode_info.atomic_inode")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..2eaca6e
--- /dev/null
@@ -0,0 +1,47 @@
+From stable+bounces-271966-greg=kroah.com@vger.kernel.org Sat Jul  4 15:01:12 2026
+From: Sasha Levin <sashal@kernel.org>
+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 <chao@kernel.org>, Jaegeuk Kim <jaegeuk@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260704130106.828918-1-sashal@kernel.org>
+
+From: Chao Yu <chao@kernel.org>
+
+[ Upstream commit 30a8496694f1a93328e5d7f19206380346918b5a ]
+
+memalloc_retry_wait() is recommended in memory allocation retry logic,
+use it as much as possible.
+
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Stable-dep-of: 8712353ed80f ("f2fs: fix to do sanity check on f2fs_get_node_folio_ra()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..24e5586
--- /dev/null
@@ -0,0 +1,70 @@
+From stable+bounces-271975-greg=kroah.com@vger.kernel.org Sat Jul  4 17:19:57 2026
+From: Sasha Levin <sashal@kernel.org>
+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 <tzimmermann@suse.de>, Helge Deller <deller@gmx.de>, Sasha Levin <sashal@kernel.org>
+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 <tzimmermann@suse.de>
+Signed-off-by: Helge Deller <deller@gmx.de>
+[ Adjust context ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/video/fbdev/core/fbcon.c |    7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/drivers/video/fbdev/core/fbcon.c
++++ b/drivers/video/fbdev/core/fbcon.c
+@@ -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;
+ }
index bafe9a3f464a3d17a5183f67da0b5ab90affb100..3a532f89c6c478b80a523cc3efb747dedca968a8 100644 (file)
@@ -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