CVE-2024-46734
Severity CVSS v4.0:
Pending analysis
Type:
Unavailable / Other
Publication date:
18/09/2024
Last modified:
20/09/2024
Description
In the Linux kernel, the following vulnerability has been resolved:<br />
<br />
btrfs: fix race between direct IO write and fsync when using same fd<br />
<br />
If we have 2 threads that are using the same file descriptor and one of<br />
them is doing direct IO writes while the other is doing fsync, we have a<br />
race where we can end up either:<br />
<br />
1) Attempt a fsync without holding the inode&#39;s lock, triggering an<br />
assertion failures when assertions are enabled;<br />
<br />
2) Do an invalid memory access from the fsync task because the file private<br />
points to memory allocated on stack by the direct IO task and it may be<br />
used by the fsync task after the stack was destroyed.<br />
<br />
The race happens like this:<br />
<br />
1) A user space program opens a file descriptor with O_DIRECT;<br />
<br />
2) The program spawns 2 threads using libpthread for example;<br />
<br />
3) One of the threads uses the file descriptor to do direct IO writes,<br />
while the other calls fsync using the same file descriptor.<br />
<br />
4) Call task A the thread doing direct IO writes and task B the thread<br />
doing fsyncs;<br />
<br />
5) Task A does a direct IO write, and at btrfs_direct_write() sets the<br />
file&#39;s private to an on stack allocated private with the member<br />
&#39;fsync_skip_inode_lock&#39; set to true;<br />
<br />
6) Task B enters btrfs_sync_file() and sees that there&#39;s a private<br />
structure associated to the file which has &#39;fsync_skip_inode_lock&#39; set<br />
to true, so it skips locking the inode&#39;s VFS lock;<br />
<br />
7) Task A completes the direct IO write, and resets the file&#39;s private to<br />
NULL since it had no prior private and our private was stack allocated.<br />
Then it unlocks the inode&#39;s VFS lock;<br />
<br />
8) Task B enters btrfs_get_ordered_extents_for_logging(), then the<br />
assertion that checks the inode&#39;s VFS lock is held fails, since task B<br />
never locked it and task A has already unlocked it.<br />
<br />
The stack trace produced is the following:<br />
<br />
assertion failed: inode_is_locked(&inode->vfs_inode), in fs/btrfs/ordered-data.c:983<br />
------------[ cut here ]------------<br />
kernel BUG at fs/btrfs/ordered-data.c:983!<br />
Oops: invalid opcode: 0000 [#1] PREEMPT SMP PTI<br />
CPU: 9 PID: 5072 Comm: worker Tainted: G U OE 6.10.5-1-default #1 openSUSE Tumbleweed 69f48d427608e1c09e60ea24c6c55e2ca1b049e8<br />
Hardware name: Acer Predator PH315-52/Covini_CFS, BIOS V1.12 07/28/2020<br />
RIP: 0010:btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs]<br />
Code: 50 d6 86 c0 e8 (...)<br />
RSP: 0018:ffff9e4a03dcfc78 EFLAGS: 00010246<br />
RAX: 0000000000000054 RBX: ffff9078a9868e98 RCX: 0000000000000000<br />
RDX: 0000000000000000 RSI: ffff907dce4a7800 RDI: ffff907dce4a7800<br />
RBP: ffff907805518800 R08: 0000000000000000 R09: ffff9e4a03dcfb38<br />
R10: ffff9e4a03dcfb30 R11: 0000000000000003 R12: ffff907684ae7800<br />
R13: 0000000000000001 R14: ffff90774646b600 R15: 0000000000000000<br />
FS: 00007f04b96006c0(0000) GS:ffff907dce480000(0000) knlGS:0000000000000000<br />
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033<br />
CR2: 00007f32acbfc000 CR3: 00000001fd4fa005 CR4: 00000000003726f0<br />
Call Trace:<br />
<br />
? __die_body.cold+0x14/0x24<br />
? die+0x2e/0x50<br />
? do_trap+0xca/0x110<br />
? do_error_trap+0x6a/0x90<br />
? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a]<br />
? exc_invalid_op+0x50/0x70<br />
? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a]<br />
? asm_exc_invalid_op+0x1a/0x20<br />
? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a]<br />
? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a]<br />
btrfs_sync_file+0x21a/0x4d0 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a]<br />
? __seccomp_filter+0x31d/0x4f0<br />
__x64_sys_fdatasync+0x4f/0x90<br />
do_syscall_64+0x82/0x160<br />
? do_futex+0xcb/0x190<br />
? __x64_sys_futex+0x10e/0x1d0<br />
? switch_fpu_return+0x4f/0xd0<br />
? syscall_exit_to_user_mode+0x72/0x220<br />
? do_syscall_64+0x8e/0x160<br />
? syscall_exit_to_user_mod<br />
---truncated---
Impact
References to Advisories, Solutions, and Tools
- https://git.kernel.org/stable/c/01681aa609b5f110502f56c4e3b2938efcf4a5bc
- https://git.kernel.org/stable/c/7b5595f33c3c273613b590892a578d78186bb400
- https://git.kernel.org/stable/c/cd3087582e4fa36e89be4e6f859e75a4400292b4
- https://git.kernel.org/stable/c/cd9253c23aedd61eb5ff11f37a36247cd46faf86
- https://git.kernel.org/stable/c/d116a0b0e02f395cedfb8c725bd67480aa7c428c