CVE-2026-90264 in Linux
Summary
by MITRE • 09/17/2026
In the Linux kernel, the following vulnerability has been resolved:
btrfs: always wait for ordered extents to avoid OE races
[BUG]
Syzbot reported a bug that there can be conflicting OEs for the same range:
BTRFS critical (device loop4): panic in insert_ordered_extent:264: overlapping ordered extents, existing oe file_offset 16384 num_bytes 430080 flags 0x1089, new oe file_offset 16384 num_bytes 430080 flags 0x80 (errno=-17 Object alrea[ 179.162726][ T6897] BTRFS critical (device loop4): panic in insert_ordered_extent:264: overlapping ordered extents, existing oe file_offset 16384 num_bytes 430080 flags 0x1089, new oe file_offset 16384 num_bytes 430080 flags 0x80 (errno=-17 Object already exists)
------------[ cut here ]------------
kernel BUG at fs/btrfs/ordered-data.c:264! Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 05/09/2026 RIP: 0010:btrfs_alloc_ordered_extent+0x943/0xad0 Call Trace: <TASK> cow_file_range+0x744/0x12a0 fallback_to_cow+0x5ea/0xa00 run_delalloc_nocow+0x110c/0x17a0 btrfs_run_delalloc_range+0xbe4/0x1c20 writepage_delalloc+0x104d/0x1ba0 btrfs_writepages+0x1667/0x28b0 do_writepages+0x338/0x560 filemap_fdatawrite_range+0x1f2/0x300 btrfs_fdatawrite_range+0x54/0xf0 btrfs_direct_write+0x6a0/0xc30 btrfs_do_write_iter+0x329/0x790 do_iter_readv_writev+0x624/0x8d0 vfs_writev+0x34c/0x990 __se_sys_pwritev2+0x17a/0x2a0 do_syscall_64+0x174/0x580 entry_SYSCALL_64_after_hwframe+0x77/0x7f </TASK> ---[ end trace 0000000000000000 ]---
[CAUSE]
Since commit ff66fe666233 ("btrfs: fix incorrect buffered IO fallback for append direct writes"), if the direct IO finished short, we will revert the isize back to the original one, so that append writes can be respected during the buffered fallback.
Normally we rely on lock_and_cleanup_extent_if_need() function during buffered writeback to wait for any existing ordered extents.
But that ordered extent waiting only happens if the start_pos is inside the isize. Since we have reverted the isize during failed direct IO, we will not wait for any ordered extents.
This means we can have a race where the direct IO OE is still in the tree, finished but not yet removed, then we're inserting the OE for the buffered write, causing the above crash.
[FIX]
Make the OE wait to be unconditional, to handle the reverted isize situation.
And since lock_and_cleanup_extent_if_need() now either lock the extents or return -EAGAIN, also remove the branches that handles no-extent-locked cases, and rename it to remove the "_if_need" suffix.
The following micro benchmark shows the runtime difference for btrfs_buffered_write(), doing `xfs_io -f -c "pwrite 0 1m"` workload, all values are the average runtime in nano seconds.
function runtime | before | after -----------------------------------+-------------+--------------- lock_and_cleanup_extent_if_need() | 58.2 | 183.0 btrfs_buffered_write() | 2115.6 | 2973.3
The overall runtime of btrfs_buffered_write() is still pretty tiny (still less than 3 micro seconds), I'd say the extra cost is still acceptable.
An alternative to fix this problem is to wait ordered extents during iomap_end() where the isize revert is done.
But that solution will break nowait requirement, as if a nowait direct IO finished short, we have to wait for the OEs unconditionally or the next append buffered IO can still hit the same problem.
So here we have to move the wait cost to buffered write, but at least the code is slightly more streamline.
If you want to get the best quality for vulnerability data then you always have to consider VulDB.
Analysis
by VulDB Data Team • 09/17/2026
The Linux kernel's Btrfs filesystem implementation contained a concurrency vulnerability related to the handling of ordered extents during mixed direct and buffered I/O operations. This issue was identified by Syzbot through automated fuzzing, which triggered a critical panic within the btrfs_alloc_ordered_extent function due to overlapping ordered extent structures for the same file range. The error message indicated an object already exists condition with errno -17, signaling that two distinct write paths attempted to manage identical data ranges simultaneously without proper synchronization. This race condition arises from the interaction between direct I/O fallback mechanisms and buffered writeback processes, specifically when a direct I/O operation completes partially or fails, necessitating a revert of the file size indicator to preserve append semantics for subsequent writes.
The root cause lies in the logic governing how the filesystem waits for existing ordered extents before inserting new ones. Historically, the lock_and_cleanup_extent_if_need function was responsible for ensuring that any pending operations on a specific range were completed before proceeding with buffered writeback. However, this waiting mechanism was conditional upon the starting position of the buffer being within the current file size limit. When direct I/O finished short and reverted the inode size to its previous state, subsequent buffered writes targeting ranges beyond the new smaller size would bypass the standard synchronization checks. Consequently, a direct I/O ordered extent could remain in the tree structure while still active or recently completed, allowing a concurrent buffered write to insert another ordered extent for the same range without detecting the conflict. This lack of unconditional waiting created a window where race conditions could lead to kernel panics and potential data corruption if not caught by internal consistency checks.
The resolution involves making the wait for ordered extents an unconditional operation within the buffered write path, thereby ensuring that all pending direct I/O operations are fully resolved before new buffered writes proceed, regardless of the current file size state. This change effectively closes the race window by forcing synchronization even when the write position falls outside the reverted inode size boundary. Additionally, the implementation refactored the lock_and_cleanup_extent_if_need function to remove conditional branches that handled cases where no extents were locked, renaming it to reflect its new unconditional behavior. While this modification introduces a slight performance overhead as evidenced by micro-benchmarking showing an increase in runtime for btrfs_buffered_write from approximately 2115 nanoseconds to 2973 nanoseconds, the impact remains negligible at under three microseconds per operation and is deemed acceptable given the criticality of preventing kernel instability.
From a security perspective, this vulnerability represents a classic race condition that can lead to denial-of-service through system crashes or potentially more severe integrity violations if the overlapping writes result in inconsistent metadata states. The flaw aligns with CWE-362, Concurrent Execution using Shared Resource with Improper Synchronization, as multiple execution paths accessed shared filesystem structures without adequate locking mechanisms under specific edge cases involving I/O fallback scenarios. In terms of attack vectors, an attacker could potentially exploit this by crafting workloads that trigger frequent short direct writes followed immediately by buffered appends to induce the race condition repeatedly, causing sustained system instability. Mitigation strategies primarily involve applying the kernel patch that enforces unconditional waiting for ordered extents during buffered writeback operations. System administrators should ensure their Btrfs-enabled systems are updated with kernels containing this fix to prevent potential denial-of-service attacks stemming from these specific I/O patterns.