linux/fs/btrfs
Filipe Manana 7ee85f5515 btrfs: fix race setting file private on concurrent lseek using same fd
When doing concurrent lseek(2) system calls against the same file
descriptor, using multiple threads belonging to the same process, we have
a short time window where a race happens and can result in a memory leak.

The race happens like this:

1) A program opens a file descriptor for a file and then spawns two
   threads (with the pthreads library for example), lets call them
   task A and task B;

2) Task A calls lseek with SEEK_DATA or SEEK_HOLE and ends up at
   file.c:find_desired_extent() while holding a read lock on the inode;

3) At the start of find_desired_extent(), it extracts the file's
   private_data pointer into a local variable named 'private', which has
   a value of NULL;

4) Task B also calls lseek with SEEK_DATA or SEEK_HOLE, locks the inode
   in shared mode and enters file.c:find_desired_extent(), where it also
   extracts file->private_data into its local variable 'private', which
   has a NULL value;

5) Because it saw a NULL file private, task A allocates a private
   structure and assigns to the file structure;

6) Task B also saw a NULL file private so it also allocates its own file
   private and then assigns it to the same file structure, since both
   tasks are using the same file descriptor.

   At this point we leak the private structure allocated by task A.

Besides the memory leak, there's also the detail that both tasks end up
using the same cached state record in the private structure (struct
btrfs_file_private::llseek_cached_state), which can result in a
use-after-free problem since one task can free it while the other is
still using it (only one task took a reference count on it). Also, sharing
the cached state is not a good idea since it could result in incorrect
results in the future - right now it should not be a problem because it
end ups being used only in extent-io-tree.c:count_range_bits() where we do
range validation before using the cached state.

Fix this by protecting the private assignment and check of a file while
holding the inode's spinlock and keep track of the task that allocated
the private, so that it's used only by that task in order to prevent
user-after-free issues with the cached state record as well as potentially
using it incorrectly in the future.

Fixes: 3c32c7212f ("btrfs: use cached state when looking for delalloc ranges with lseek")
CC: stable@vger.kernel.org # 6.6+
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2024-09-17 17:31:48 +02:00
..
tests btrfs: convert find_lock_delalloc_range() to use a folio 2024-09-10 16:51:14 +02:00
accessors.c btrfs: remove unused included headers 2024-03-04 16:24:46 +01:00
accessors.h btrfs: remove raid-stripe-tree encoding field from stripe_extent 2024-07-11 15:33:28 +02: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: constify more pointer parameters 2024-09-10 16:51:22 +02:00
backref.h btrfs: uninline some static inline helpers from backref.h 2024-03-04 16:24:53 +01:00
bio.c btrfs: merge btrfs_orig_bbio_end_io() into btrfs_bio_end_io() 2024-09-10 16:51:20 +02:00
bio.h btrfs: rename btrfs_submit_bio() to btrfs_submit_bbio() 2024-09-10 16:51:19 +02:00
block-group.c btrfs: constify more pointer parameters 2024-09-10 16:51:22 +02: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 setting file private on concurrent lseek using same fd 2024-09-17 17:31:48 +02:00
compression.c btrfs: convert btrfs_decompress() to take a folio 2024-09-10 16:51:21 +02:00
compression.h btrfs: convert btrfs_decompress() to take a folio 2024-09-10 16:51:21 +02:00
ctree.c btrfs: constify more pointer parameters 2024-09-10 16:51:22 +02:00
ctree.h btrfs: fix race setting file private on concurrent lseek using same fd 2024-09-17 17:31:48 +02:00
defrag.c btrfs: always pass readahead state to defrag 2024-09-10 16:51:20 +02: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: qgroup: use xarray to track dirty extents in transaction 2024-09-10 16:51:18 +02:00
delayed-ref.h btrfs: qgroup: use xarray to track dirty extents in transaction 2024-09-10 16:51:18 +02:00
dev-replace.c btrfs: more efficient chunk map iteration when device replace finishes 2024-09-10 16:51:17 +02:00
dev-replace.h btrfs: add forward declarations and headers, part 1 2024-03-04 16:24:49 +01:00
dir-item.c btrfs: constify pointer parameters where applicable 2024-07-11 15:33:22 +02:00
dir-item.h btrfs: constify pointer parameters where applicable 2024-07-11 15:33:22 +02:00
direct-io.c btrfs: do not hold the extent lock for entire read 2024-09-10 16:51:20 +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: constify more pointer parameters 2024-09-10 16:51:22 +02:00
discard.h
disk-io.c btrfs: convert try_release_extent_buffer() to take a folio 2024-09-10 16:51:20 +02:00
disk-io.h btrfs: constify pointer parameters where applicable 2024-07-11 15:33:22 +02:00
export.c btrfs: remove super block argument from btrfs_iget() 2024-07-11 15:33:25 +02:00
export.h btrfs: add forward declarations and headers, part 1 2024-03-04 16:24:49 +01:00
extent_io.c btrfs: only unlock the to-be-submitted ranges inside a folio 2024-09-10 16:51:22 +02:00
extent_io.h btrfs: convert try_release_extent_mapping() to take a folio 2024-09-10 16:51:21 +02:00
extent_map.c btrfs: reduce size and overhead of extent_map_block_end() 2024-09-10 16:51:12 +02:00
extent_map.h btrfs: do not directly include rwlock_types.h 2024-07-11 15:33:22 +02:00
extent-io-tree.c btrfs: introduce EXTENT_DIO_LOCKED 2024-09-10 16:51:20 +02:00
extent-io-tree.h btrfs: introduce EXTENT_DIO_LOCKED 2024-09-10 16:51:20 +02:00
extent-tree.c btrfs: always update fstrim_range on failure in FITRIM ioctl 2024-09-10 16:51:21 +02:00
extent-tree.h btrfs: do not BUG_ON() when freeing tree block after error 2024-07-11 15:33:26 +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: fix race setting file private on concurrent lseek using same fd 2024-09-17 17:31:48 +02: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: zoned: properly take lock to read/update block group's zoned variables 2024-08-15 20:35:56 +02:00
free-space-cache.h btrfs: add forward declarations and headers, part 2 2024-03-04 16:24:49 +01:00
free-space-tree.c btrfs: do not BUG_ON() when freeing tree block after error 2024-07-11 15:33:26 +02:00
free-space-tree.h btrfs: add forward declarations and headers, part 2 2024-03-04 16:24:49 +01:00
fs.c
fs.h btrfs: subpage: remove btrfs_fs_info::subpage_info member 2024-09-10 16:51:18 +02: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: convert btrfs_decompress() to take a folio 2024-09-10 16:51:21 +02:00
ioctl.c btrfs: always update fstrim_range on failure in FITRIM ioctl 2024-09-10 16:51:21 +02: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: introduce new "rescue=ignoremetacsums" mount option 2024-07-11 15:33:29 +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: add and use helper to verify the calling task has locked the inode 2024-09-10 16:51:22 +02: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: use xarray to track dirty extents in transaction 2024-09-10 16:51:18 +02:00
qgroup.h btrfs: qgroup: use xarray to track dirty extents in transaction 2024-09-10 16:51:18 +02:00
raid56.c btrfs: rename the extra_gfp parameter of btrfs_alloc_page_array() 2024-07-11 15:33:30 +02:00
raid56.h btrfs: add forward declarations and headers, part 2 2024-03-04 16:24:49 +01: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
rcu-string.h btrfs: add forward declarations and headers, part 1 2024-03-04 16:24:49 +01:00
ref-verify.c btrfs: fix uninitialized return value in the ref-verify tool 2024-07-02 19:14:57 +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: don't readahead the relocation inode on RST 2024-09-10 16:51:17 +02: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: rename btrfs_submit_bio() to btrfs_submit_bbio() 2024-09-10 16:51:19 +02:00
scrub.h btrfs: add forward declarations and headers, part 1 2024-03-04 16:24:49 +01:00
send.c btrfs: send: fix grammar in comments 2024-09-10 16:51:18 +02:00
send.h btrfs: pass a btrfs_inode to btrfs_ioctl_send() 2024-07-11 15:33:28 +02:00
space-info.c btrfs: constify more pointer parameters 2024-09-10 16:51:22 +02:00
space-info.h btrfs: constify more pointer parameters 2024-09-10 16:51:22 +02:00
subpage.c btrfs: only unlock the to-be-submitted ranges inside a folio 2024-09-10 16:51:22 +02:00
subpage.h btrfs: only unlock the to-be-submitted ranges inside a folio 2024-09-10 16:51:22 +02:00
super.c btrfs: only enable extent map shrinker for DEBUG builds 2024-08-16 21:22:39 +02:00
super.h btrfs: change BTRFS_MOUNT_* flags to 64bit type 2024-07-19 17:20:23 +02:00
sysfs.c btrfs: introduce new "rescue=ignoresuperflags" mount option 2024-07-11 15:33:30 +02:00
sysfs.h btrfs: add forward declarations and headers, part 1 2024-03-04 16:24:49 +01:00
transaction.c btrfs: qgroup: use xarray to track dirty extents in transaction 2024-09-10 16:51:18 +02: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: add dev extent item checks 2024-08-15 20:35:52 +02: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: add and use helper to verify the calling task has locked the inode 2024-09-10 16:51:22 +02: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 btrfs: move uuid tree related code to uuid-tree.[ch] 2024-09-10 16:51:12 +02: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: reduce chunk_map lookups in btrfs_map_block() 2024-09-10 16:51:18 +02:00
volumes.h btrfs: rename btrfs_io_stripe::is_scrub to rst_search_commit_root 2024-09-10 16:51:17 +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: convert zlib_decompress() to take a folio 2024-09-10 16:51:21 +02:00
zoned.c btrfs: use btrfs_path auto free in zoned.c 2024-09-10 16:51:22 +02:00
zoned.h btrfs: constify more pointer parameters 2024-09-10 16:51:22 +02:00
zstd.c btrfs: convert zstd_decompress() to take a folio 2024-09-10 16:51:21 +02:00