linux/fs/btrfs
JP Kobryn 22b10cbb9a btrfs: prevent use-after-free on folio private data in btrfs_subpage_clear_uptodate()
This is a stable-only patch. The issue was inadvertently fixed in 6.17 [0]
as part of a refactoring, but this patch serves as a minimal targeted fix
for prior kernels.

Users of filemap_lock_folio() need to guard against the situation where
release_folio() has been invoked during reclaim but the folio was
ultimately not removed from the page cache. This patch covers one location
that was overlooked.

After acquiring the folio, use set_folio_extent_mapped() to ensure the
folio private state is valid. This is especially important in the subpage
case, where the private field is an allocated struct containing bitmap and
lock data.

Without this protection, the race below is possible:

[mm] page cache reclaim path        [fs] relocation in subpage mode
shrink_folio_list()
  folio_trylock() /* lock acquired */
  filemap_release_folio()
    mapping->a_ops->release_folio()
      btrfs_release_folio()
        __btrfs_release_folio()
          clear_folio_extent_mapped()
            btrfs_detach_subpage()
              subpage = folio_detach_private(folio)
              btrfs_free_subpage(subpage)
                kfree(subpage) /* point A */

                                   prealloc_file_extent_cluster()
                                     filemap_lock_folio()
                                       folio_try_get() /* inc refcount */
                                       folio_lock() /* wait for lock */

  if (...)
    ...
  else if (!mapping || !__remove_mapping(..))
    /*
     * __remove_mapping() returns zero when
     * folio_ref_freeze(folio, refcount) fails /* point B */
     */
    goto keep_locked /* folio remains in cache */

keep_locked:
  folio_unlock(folio) /* lock released */

                                   /* lock acquired */
                                   btrfs_subpage_clear_uptodate()
                                     /* use-after-free */
                                     subpage = folio_get_private(folio)

[0] 4e346baee9 ("btrfs: reloc: unconditionally invalidate the page cache for each cluster")

Fixes: 9d9ea1e68a ("btrfs: subpage: fix relocation potentially overwriting last page data")
Cc: stable@vger.kernel.org # 6.10-6.16
Signed-off-by: JP Kobryn <inwardvessel@gmail.com>
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
History 2026-02-06 16:55:50 +01:00
..
tests btrfs: use unsigned types for constants defined as bit shifts 2025-07-06 11:01:37 +02:00
accessors.c move asm/unaligned.h to linux/unaligned.h 2024-10-02 17:23:23 -04:00
accessors.h move asm/unaligned.h to linux/unaligned.h 2024-10-02 17:23:23 -04:00
acl.c btrfs: remove unused included headers 2024-03-04 16:24:46 +01:00
acl.h btrfs: add forward declarations and headers, part 1 2024-03-04 16:24:49 +01:00
async-thread.c btrfs: remove unused included headers 2024-03-04 16:24:46 +01:00
async-thread.h btrfs: add forward declarations and headers, part 1 2024-03-04 16:24:49 +01:00
backref.c btrfs: drop the backref cache during relocation if we commit 2024-10-01 19:10:26 +02:00
backref.h btrfs: use unsigned types for constants defined as bit shifts 2025-07-06 11:01:37 +02:00
bio.c btrfs: handle bio_split() errors 2025-01-09 13:33:44 +01:00
bio.h btrfs: fix error propagation of split bios 2024-10-23 18:17:43 +02:00
block-group.c btrfs: fix racy bitfield write in btrfs_clear_space_info_full() 2026-01-30 10:28:48 +01:00
block-group.h btrfs: constify more pointer parameters 2024-09-10 16:51:22 +02:00
block-rsv.c btrfs: constify more pointer parameters 2024-09-10 16:51:22 +02:00
block-rsv.h btrfs: constify more pointer parameters 2024-09-10 16:51:22 +02:00
btrfs_inode.h btrfs: fix race between setting last_dir_index_offset and inode logging 2025-09-09 18:58:02 +02:00
compression.c btrfs: compression: adjust cb->compressed_folios allocation type 2025-05-29 11:03:12 +02:00
compression.h btrfs: convert btrfs_decompress() to take a folio 2024-09-10 16:51:21 +02:00
ctree.c btrfs: fix leaf leak in an error path in btrfs_del_items() 2025-12-18 13:55:06 +01:00
ctree.h btrfs: fix improper generation check in snapshot delete 2024-12-27 14:02:14 +01:00
defrag.c btrfs: fix defrag not merging contiguous extents due to merged extent maps 2024-10-31 16:46:41 +01:00
defrag.h btrfs: drop transaction parameter from btrfs_add_inode_defrag() 2024-09-10 16:51:19 +02:00
delalloc-space.c btrfs: constify pointer parameters where applicable 2024-07-11 15:33:22 +02:00
delalloc-space.h btrfs: constify pointer parameters where applicable 2024-07-11 15:33:22 +02:00
delayed-inode.c btrfs: pass a btrfs_inode to btrfs_readdir_get_delayed_items() 2024-07-11 15:33:28 +02:00
delayed-inode.h btrfs: pass a btrfs_inode to btrfs_readdir_get_delayed_items() 2024-07-11 15:33:28 +02:00
delayed-ref.c btrfs: fix incorrect comparison for delayed refs 2024-11-14 16:11:02 +01:00
delayed-ref.h btrfs: use sector numbers as keys for the dirty extents xarray 2024-10-11 18:33:35 +02:00
dev-replace.c btrfs: don't take dev_replace rwsem on task already holding it 2024-12-14 20:03:36 +01:00
dev-replace.h btrfs: add forward declarations and headers, part 1 2024-03-04 16:24:49 +01:00
dir-item.c btrfs: fix passing 0 to ERR_PTR in btrfs_search_dir_index_item() 2024-10-22 16:10:55 +02:00
dir-item.h btrfs: constify pointer parameters where applicable 2024-07-11 15:33:22 +02:00
direct-io.c btrfs: use unsigned types for constants defined as bit shifts 2025-07-06 11:01:37 +02:00
direct-io.h btrfs: move the direct IO code into its own file 2024-07-11 15:33:29 +02:00
discard.c btrfs: make btrfs_discard_workfn() block_group ref explicit 2025-05-29 11:02:12 +02:00
discard.h btrfs: unexport btrfs_run_discard_work and make it static 2023-06-19 13:59:25 +02:00
disk-io.c btrfs: fix missing fields in superblock backup with BLOCK_GROUP_TREE 2026-01-30 10:28:37 +01:00
disk-io.h btrfs: drop unused parameter options from open_ctree() 2024-12-14 20:04:12 +01:00
export.c btrfs: avoid potential out-of-bounds in btrfs_encode_fh() 2025-10-19 16:33:48 +02:00
export.h btrfs: add forward declarations and headers, part 1 2024-03-04 16:24:49 +01:00
extent-io-tree.c btrfs: exit after state split error at set_extent_bit() 2025-06-19 15:32:32 +02:00
extent-io-tree.h btrfs: introduce EXTENT_DIO_LOCKED 2024-09-10 16:51:20 +02:00
extent-tree.c btrfs: zoned: refine extent allocator hint selection 2025-11-02 22:15:21 +09:00
extent-tree.h btrfs: do not BUG_ON() when freeing tree block after error 2024-07-11 15:33:26 +02:00
extent_io.c btrfs: fix beyond-EOF write handling 2026-01-17 16:31:26 +01:00
extent_io.h btrfs: use unsigned types for constants defined as bit shifts 2025-07-06 11:01:37 +02:00
extent_map.c btrfs: fix use-after-free on inode when scanning root during em shrinking 2025-07-06 11:01:50 +02:00
extent_map.h btrfs: make the extent map shrinker run asynchronously as a work queue job 2025-07-06 11:01:49 +02:00
fiemap.c btrfs: initialize last_extent_end to fix -Wmaybe-uninitialized warning in extent_fiemap() 2024-08-26 16:58:13 +02:00
fiemap.h btrfs: move fiemap code into its own file 2024-07-11 15:33:20 +02:00
file-item.c btrfs: constify more pointer parameters 2024-09-10 16:51:22 +02:00
file-item.h btrfs: constify more pointer parameters 2024-09-10 16:51:22 +02:00
file.c btrfs: mark dirty extent range for out of bound prealloc extents 2025-11-13 15:34:33 -05:00
file.h btrfs: move the direct IO code into its own file 2024-07-11 15:33:29 +02:00
free-space-cache.c btrfs: add cancellation points to trim loops 2024-10-07 23:21:56 +02:00
free-space-cache.h btrfs: add cancellation points to trim loops 2024-10-07 23:21:56 +02:00
free-space-tree.c btrfs: do not assert we found block group item when creating free space tree 2025-10-23 16:20:20 +02:00
free-space-tree.h btrfs: add forward declarations and headers, part 2 2024-03-04 16:24:49 +01:00
fs.c btrfs: sysfs: update fs features directory asynchronously 2023-02-13 17:50:35 +01:00
fs.h btrfs: remove btrfs_fs_info::sectors_per_page 2026-01-17 16:31:26 +01:00
inode-item.c btrfs: constify more pointer parameters 2024-09-10 16:51:22 +02:00
inode-item.h btrfs: constify more pointer parameters 2024-09-10 16:51:22 +02:00
inode.c btrfs: add extra error messages for delalloc range related errors 2026-01-17 16:31:26 +01:00
ioctl.c btrfs: don't rewrite ret from inode_permission 2026-01-08 10:14:56 +01:00
ioctl.h btrfs: constify pointer parameters where applicable 2024-07-11 15:33:22 +02:00
Kconfig btrfs: check-integrity: remove CONFIG_BTRFS_FS_CHECK_INTEGRITY option 2023-10-12 16:44:05 +02:00
locking.c btrfs: change root->root_key.objectid to btrfs_root_id() 2024-05-07 21:31:06 +02:00
locking.h btrfs: cleanup recursive include of the same header 2024-07-11 15:33:22 +02:00
lru_cache.c btrfs: fix typos found by codespell 2023-12-15 23:00:04 +01:00
lru_cache.h btrfs: cleanup recursive include of the same header 2024-07-11 15:33:22 +02:00
lzo.c btrfs: convert lzo_decompress() to take a folio 2024-09-10 16:51:21 +02:00
Makefile btrfs: move the direct IO code into its own file 2024-07-11 15:33:29 +02:00
messages.c btrfs: disable rate limiting when debug enabled 2024-10-01 19:29:41 +02:00
messages.h btrfs: constify fs_info parameter in __btrfs_panic() 2023-12-15 20:27:02 +01:00
misc.h btrfs: constify pointer parameters where applicable 2024-07-11 15:33:22 +02:00
ordered-data.c btrfs: truncate ordered extent when skipping writeback past i_size 2026-01-17 16:31:26 +01:00
ordered-data.h btrfs: convert btrfs_mark_ordered_io_finished() to take a folio 2024-09-10 16:51:14 +02:00
orphan.c btrfs: BTRFS_PATH_AUTO_FREE in orphan.c 2024-09-10 16:51:22 +02:00
orphan.h btrfs: add forward declarations and headers, part 1 2024-03-04 16:24:49 +01:00
print-tree.c btrfs: avoid using fixed char array size for tree names 2024-08-02 22:44:27 +02:00
print-tree.h btrfs: add forward declarations and headers, part 1 2024-03-04 16:24:49 +01:00
props.c btrfs: pass a btrfs_inode to btrfs_set_prop() 2024-07-11 15:33:29 +02:00
props.h btrfs: pass a btrfs_inode to btrfs_set_prop() 2024-07-11 15:33:29 +02:00
qgroup.c btrfs: qgroup: update all parent qgroups when doing quick inherit 2026-01-17 16:31:20 +01:00
qgroup.h btrfs: qgroup: set a more sane default value for subtree drop threshold 2024-10-22 16:09:11 +02:00
raid-stripe-tree.c btrfs: change RST lookup error message level to debug 2024-09-10 16:51:17 +02:00
raid-stripe-tree.h btrfs: remove raid-stripe-tree encoding field from stripe_extent 2024-07-11 15:33:28 +02:00
raid56.c btrfs: use unsigned types for constants defined as bit shifts 2025-07-06 11:01:37 +02:00
raid56.h btrfs: add forward declarations and headers, part 2 2024-03-04 16:24:49 +01:00
rcu-string.h btrfs: add forward declarations and headers, part 1 2024-03-04 16:24:49 +01:00
ref-verify.c btrfs: ref-verify: handle damaged extent root tree 2025-10-12 12:57:17 +02:00
ref-verify.h btrfs: add forward declarations and headers, part 1 2024-03-04 16:24:49 +01:00
reflink.c btrfs: convert copy_inline_to_page() to use folio 2024-09-10 16:51:21 +02:00
reflink.h btrfs: add forward declarations and headers, part 1 2024-03-04 16:24:49 +01:00
relocation.c btrfs: prevent use-after-free on folio private data in btrfs_subpage_clear_uptodate() 2026-02-06 16:55:50 +01:00
relocation.h btrfs: add forward declarations and headers, part 1 2024-03-04 16:24:49 +01:00
root-tree.c btrfs: change root->root_key.objectid to btrfs_root_id() 2024-05-07 21:31:06 +02:00
root-tree.h btrfs: qgroup: fix qgroup prealloc rsv leak in subvolume operations 2024-04-02 19:18:23 +02:00
scrub.c btrfs: scrub: always update btrfs_scrub_progress::last_physical 2026-01-08 10:13:58 +01:00
scrub.h btrfs: add forward declarations and headers, part 1 2024-03-04 16:24:49 +01:00
send.c btrfs: send: check for inline extents in range_is_hole_in_parent() 2026-01-23 11:18:36 +01:00
send.h btrfs: pass a btrfs_inode to btrfs_ioctl_send() 2024-07-11 15:33:28 +02:00
space-info.c btrfs: fix racy bitfield write in btrfs_clear_space_info_full() 2026-01-30 10:28:48 +01:00
space-info.h btrfs: fix racy bitfield write in btrfs_clear_space_info_full() 2026-01-30 10:28:48 +01:00
subpage.c btrfs: remove btrfs_fs_info::sectors_per_page 2026-01-17 16:31:26 +01:00
subpage.h btrfs: rename btrfs_folio_(set|start|end)_writer_lock() 2025-02-27 04:30:14 -08:00
super.c btrfs: only enforce free space tree if v1 cache is required for bs < ps cases 2026-01-17 16:31:24 +01:00
super.h btrfs: change BTRFS_MOUNT_* flags to 64bit type 2024-07-19 17:20:23 +02:00
sysfs.c btrfs: introduce btrfs_space_info sub-group 2026-01-23 11:18:38 +01:00
sysfs.h btrfs: add forward declarations and headers, part 1 2024-03-04 16:24:49 +01:00
transaction.c btrfs: fix deadlock in wait_current_trans() due to ignored transaction type 2026-01-23 11:18:50 +01:00
transaction.h btrfs: fix race between direct IO write and fsync when using same fd 2024-09-03 20:29:55 +02:00
tree-checker.c btrfs: tree-checker: fix bounds check in check_inode_extref() 2025-11-02 22:15:23 +09:00
tree-checker.h btrfs: make sure that WRITTEN is set on all metadata blocks 2024-05-02 22:11:13 +02:00
tree-log.c btrfs: always detect conflicting inodes when logging inode refs 2026-01-17 16:31:16 +01:00
tree-log.h btrfs: avoid transaction commit on any fsync after subvolume creation 2024-07-11 15:33:24 +02:00
tree-mod-log.c btrfs: constify more pointer parameters 2024-09-10 16:51:22 +02:00
tree-mod-log.h btrfs: constify more pointer parameters 2024-09-10 16:51:22 +02:00
ulist.c btrfs: preallocate ulist memory for qgroup rsv 2024-07-11 15:33:26 +02:00
ulist.h btrfs: preallocate ulist memory for qgroup rsv 2024-07-11 15:33:26 +02:00
uuid-tree.c move asm/unaligned.h to linux/unaligned.h 2024-10-02 17:23:23 -04:00
uuid-tree.h btrfs: move uuid tree related code to uuid-tree.[ch] 2024-09-10 16:51:12 +02:00
verity.c btrfs: add and use helper to verify the calling task has locked the inode 2024-09-10 16:51:22 +02:00
verity.h btrfs: add forward declarations and headers, part 1 2024-03-04 16:24:49 +01:00
volumes.c btrfs: fix memory leak of fs_devices in degraded seed device path 2026-01-08 10:13:54 +01:00
volumes.h btrfs: split remaining space to discard in chunks 2024-10-07 23:21:53 +02:00
xattr.c btrfs: add and use helper to verify the calling task has locked the inode 2024-09-10 16:51:22 +02:00
xattr.h btrfs: constify pointer parameters where applicable 2024-07-11 15:33:22 +02:00
zlib.c btrfs: zlib: fix avail_in bytes for s390 zlib HW compression path 2025-01-17 13:40:48 +01:00
zoned.c btrfs: zoned: fix conventional zone capacity calculation 2025-11-24 10:36:03 +01:00
zoned.h btrfs: zoned: return error from btrfs_zone_finish_endio() 2025-11-02 22:15:21 +09:00
zstd.c btrfs: use unsigned types for constants defined as bit shifts 2025-07-06 11:01:37 +02:00