CVE-2025-39779
Fecha de publicación:
11/09/2025
*** Pendiente de traducción *** In the Linux kernel, the following vulnerability has been resolved:<br />
<br />
btrfs: subpage: keep TOWRITE tag until folio is cleaned<br />
<br />
btrfs_subpage_set_writeback() calls folio_start_writeback() the first time<br />
a folio is written back, and it also clears the PAGECACHE_TAG_TOWRITE tag<br />
even if there are still dirty blocks in the folio. This can break ordering<br />
guarantees, such as those required by btrfs_wait_ordered_extents().<br />
<br />
That ordering breakage leads to a real failure. For example, running<br />
generic/464 on a zoned setup will hit the following ASSERT. This happens<br />
because the broken ordering fails to flush existing dirty pages before the<br />
file size is truncated.<br />
<br />
assertion failed: !list_empty(&ordered->list) :: 0, in fs/btrfs/zoned.c:1899<br />
------------[ cut here ]------------<br />
kernel BUG at fs/btrfs/zoned.c:1899!<br />
Oops: invalid opcode: 0000 [#1] SMP NOPTI<br />
CPU: 2 UID: 0 PID: 1906169 Comm: kworker/u130:2 Kdump: loaded Not tainted 6.16.0-rc6-BTRFS-ZNS+ #554 PREEMPT(voluntary)<br />
Hardware name: Supermicro Super Server/H12SSL-NT, BIOS 2.0 02/22/2021<br />
Workqueue: btrfs-endio-write btrfs_work_helper [btrfs]<br />
RIP: 0010:btrfs_finish_ordered_zoned.cold+0x50/0x52 [btrfs]<br />
RSP: 0018:ffffc9002efdbd60 EFLAGS: 00010246<br />
RAX: 000000000000004c RBX: ffff88811923c4e0 RCX: 0000000000000000<br />
RDX: 0000000000000000 RSI: ffffffff827e38b1 RDI: 00000000ffffffff<br />
RBP: ffff88810005d000 R08: 00000000ffffdfff R09: ffffffff831051c8<br />
R10: ffffffff83055220 R11: 0000000000000000 R12: ffff8881c2458c00<br />
R13: ffff88811923c540 R14: ffff88811923c5e8 R15: ffff8881c1bd9680<br />
FS: 0000000000000000(0000) GS:ffff88a04acd0000(0000) knlGS:0000000000000000<br />
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033<br />
CR2: 00007f907c7a918c CR3: 0000000004024000 CR4: 0000000000350ef0<br />
Call Trace:<br />
<br />
? srso_return_thunk+0x5/0x5f<br />
btrfs_finish_ordered_io+0x4a/0x60 [btrfs]<br />
btrfs_work_helper+0xf9/0x490 [btrfs]<br />
process_one_work+0x204/0x590<br />
? srso_return_thunk+0x5/0x5f<br />
worker_thread+0x1d6/0x3d0<br />
? __pfx_worker_thread+0x10/0x10<br />
kthread+0x118/0x230<br />
? __pfx_kthread+0x10/0x10<br />
ret_from_fork+0x205/0x260<br />
? __pfx_kthread+0x10/0x10<br />
ret_from_fork_asm+0x1a/0x30<br />
<br />
<br />
Consider process A calling writepages() with WB_SYNC_NONE. In zoned mode or<br />
for compressed writes, it locks several folios for delalloc and starts<br />
writing them out. Let&#39;s call the last locked folio folio X. Suppose the<br />
write range only partially covers folio X, leaving some pages dirty.<br />
Process A calls btrfs_subpage_set_writeback() when building a bio. This<br />
function call clears the TOWRITE tag of folio X, whose size = 8K and<br />
the block size = 4K. It is following state.<br />
<br />
0 4K 8K<br />
|/////|/////| (flag: DIRTY, tag: DIRTY)<br />
Process A will write this range.<br />
<br />
Now suppose process B concurrently calls writepages() with WB_SYNC_ALL. It<br />
calls tag_pages_for_writeback() to tag dirty folios with<br />
PAGECACHE_TAG_TOWRITE. Since folio X is still dirty, it gets tagged. Then,<br />
B collects tagged folios using filemap_get_folios_tag() and must wait for<br />
folio X to be written before returning from writepages().<br />
<br />
0 4K 8K<br />
|/////|/////| (flag: DIRTY, tag: DIRTY|TOWRITE)<br />
<br />
However, between tagging and collecting, process A may call<br />
btrfs_subpage_set_writeback() and clear folio X&#39;s TOWRITE tag.<br />
0 4K 8K<br />
| |/////| (flag: DIRTY|WRITEBACK, tag: DIRTY)<br />
<br />
As a result, process B won&#39;t see folio X in its batch, and returns without<br />
waiting for it. This breaks the WB_SYNC_ALL ordering requirement.<br />
<br />
Fix this by using btrfs_subpage_set_writeback_keepwrite(), which retains<br />
the TOWRITE tag. We now manually clear the tag only after the folio becomes<br />
clean, via the xas operation.
Gravedad: Pendiente de análisis
Última modificación:
15/09/2025