CVE-2025-21942
Severity CVSS v4.0:
Pending analysis
Type:
Unavailable / Other
Publication date:
01/04/2025
Last modified:
06/07/2025
Description
In the Linux kernel, the following vulnerability has been resolved:<br />
<br />
btrfs: zoned: fix extent range end unlock in cow_file_range()<br />
<br />
Running generic/751 on the for-next branch often results in a hang like<br />
below. They are both stack by locking an extent. This suggests someone<br />
forget to unlock an extent.<br />
<br />
INFO: task kworker/u128:1:12 blocked for more than 323 seconds.<br />
Not tainted 6.13.0-BTRFS-ZNS+ #503<br />
"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.<br />
task:kworker/u128:1 state:D stack:0 pid:12 tgid:12 ppid:2 flags:0x00004000<br />
Workqueue: btrfs-fixup btrfs_work_helper [btrfs]<br />
Call Trace:<br />
<br />
__schedule+0x534/0xdd0<br />
schedule+0x39/0x140<br />
__lock_extent+0x31b/0x380 [btrfs]<br />
? __pfx_autoremove_wake_function+0x10/0x10<br />
btrfs_writepage_fixup_worker+0xf1/0x3a0 [btrfs]<br />
btrfs_work_helper+0xff/0x480 [btrfs]<br />
? lock_release+0x178/0x2c0<br />
process_one_work+0x1ee/0x570<br />
? srso_return_thunk+0x5/0x5f<br />
worker_thread+0x1d1/0x3b0<br />
? __pfx_worker_thread+0x10/0x10<br />
kthread+0x10b/0x230<br />
? __pfx_kthread+0x10/0x10<br />
ret_from_fork+0x30/0x50<br />
? __pfx_kthread+0x10/0x10<br />
ret_from_fork_asm+0x1a/0x30<br />
<br />
INFO: task kworker/u134:0:184 blocked for more than 323 seconds.<br />
Not tainted 6.13.0-BTRFS-ZNS+ #503<br />
"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.<br />
task:kworker/u134:0 state:D stack:0 pid:184 tgid:184 ppid:2 flags:0x00004000<br />
Workqueue: writeback wb_workfn (flush-btrfs-4)<br />
Call Trace:<br />
<br />
__schedule+0x534/0xdd0<br />
schedule+0x39/0x140<br />
__lock_extent+0x31b/0x380 [btrfs]<br />
? __pfx_autoremove_wake_function+0x10/0x10<br />
find_lock_delalloc_range+0xdb/0x260 [btrfs]<br />
writepage_delalloc+0x12f/0x500 [btrfs]<br />
? srso_return_thunk+0x5/0x5f<br />
extent_write_cache_pages+0x232/0x840 [btrfs]<br />
btrfs_writepages+0x72/0x130 [btrfs]<br />
do_writepages+0xe7/0x260<br />
? srso_return_thunk+0x5/0x5f<br />
? lock_acquire+0xd2/0x300<br />
? srso_return_thunk+0x5/0x5f<br />
? find_held_lock+0x2b/0x80<br />
? wbc_attach_and_unlock_inode.part.0+0x102/0x250<br />
? wbc_attach_and_unlock_inode.part.0+0x102/0x250<br />
__writeback_single_inode+0x5c/0x4b0<br />
writeback_sb_inodes+0x22d/0x550<br />
__writeback_inodes_wb+0x4c/0xe0<br />
wb_writeback+0x2f6/0x3f0<br />
wb_workfn+0x32a/0x510<br />
process_one_work+0x1ee/0x570<br />
? srso_return_thunk+0x5/0x5f<br />
worker_thread+0x1d1/0x3b0<br />
? __pfx_worker_thread+0x10/0x10<br />
kthread+0x10b/0x230<br />
? __pfx_kthread+0x10/0x10<br />
ret_from_fork+0x30/0x50<br />
? __pfx_kthread+0x10/0x10<br />
ret_from_fork_asm+0x1a/0x30<br />
<br />
<br />
This happens because we have another success path for the zoned mode. When<br />
there is no active zone available, btrfs_reserve_extent() returns<br />
-EAGAIN. In this case, we have two reactions.<br />
<br />
(1) If the given range is never allocated, we can only wait for someone<br />
to finish a zone, so wait on BTRFS_FS_NEED_ZONE_FINISH bit and retry<br />
afterward.<br />
<br />
(2) Or, if some allocations are already done, we must bail out and let<br />
the caller to send IOs for the allocation. This is because these IOs<br />
may be necessary to finish a zone.<br />
<br />
The commit 06f364284794 ("btrfs: do proper folio cleanup when<br />
cow_file_range() failed") moved the unlock code from the inside of the<br />
loop to the outside. So, previously, the allocated extents are unlocked<br />
just after the allocation and so before returning from the function.<br />
However, they are no longer unlocked on the case (2) above. That caused<br />
the hang issue.<br />
<br />
Fix the issue by modifying the &#39;end&#39; to the end of the allocated<br />
range. Then, we can exit the loop and the same unlock code can properly<br />
handle the case.