CVE-2025-39779

Source
https://nvd.nist.gov/vuln/detail/CVE-2025-39779
Import Source
https://storage.googleapis.com/cve-osv-conversion/osv-output/CVE-2025-39779.json
JSON Data
https://api.osv.dev/v1/vulns/CVE-2025-39779
Downstream
Published
2025-09-11T16:56:30Z
Modified
2025-10-22T16:08:26.226567Z
Summary
btrfs: subpage: keep TOWRITE tag until folio is cleaned
Details

In the Linux kernel, the following vulnerability has been resolved:

btrfs: subpage: keep TOWRITE tag until folio is cleaned

btrfssubpagesetwriteback() calls foliostartwriteback() the first time a folio is written back, and it also clears the PAGECACHETAGTOWRITE tag even if there are still dirty blocks in the folio. This can break ordering guarantees, such as those required by btrfswaitorderedextents().

That ordering breakage leads to a real failure. For example, running generic/464 on a zoned setup will hit the following ASSERT. This happens because the broken ordering fails to flush existing dirty pages before the file size is truncated.

assertion failed: !listempty(&ordered->list) :: 0, in fs/btrfs/zoned.c:1899 ------------[ cut here ]------------ kernel BUG at fs/btrfs/zoned.c:1899! Oops: invalid opcode: 0000 [#1] SMP NOPTI CPU: 2 UID: 0 PID: 1906169 Comm: kworker/u130:2 Kdump: loaded Not tainted 6.16.0-rc6-BTRFS-ZNS+ #554 PREEMPT(voluntary) Hardware name: Supermicro Super Server/H12SSL-NT, BIOS 2.0 02/22/2021 Workqueue: btrfs-endio-write btrfsworkhelper [btrfs] RIP: 0010:btrfsfinishorderedzoned.cold+0x50/0x52 [btrfs] RSP: 0018:ffffc9002efdbd60 EFLAGS: 00010246 RAX: 000000000000004c RBX: ffff88811923c4e0 RCX: 0000000000000000 RDX: 0000000000000000 RSI: ffffffff827e38b1 RDI: 00000000ffffffff RBP: ffff88810005d000 R08: 00000000ffffdfff R09: ffffffff831051c8 R10: ffffffff83055220 R11: 0000000000000000 R12: ffff8881c2458c00 R13: ffff88811923c540 R14: ffff88811923c5e8 R15: ffff8881c1bd9680 FS: 0000000000000000(0000) GS:ffff88a04acd0000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f907c7a918c CR3: 0000000004024000 CR4: 0000000000350ef0 Call Trace: <TASK> ? srsoreturnthunk+0x5/0x5f btrfsfinishorderedio+0x4a/0x60 [btrfs] btrfsworkhelper+0xf9/0x490 [btrfs] processonework+0x204/0x590 ? srsoreturnthunk+0x5/0x5f workerthread+0x1d6/0x3d0 ? _pfxworkerthread+0x10/0x10 kthread+0x118/0x230 ? _pfxkthread+0x10/0x10 retfromfork+0x205/0x260 ? _pfxkthread+0x10/0x10 retfromforkasm+0x1a/0x30 </TASK>

Consider process A calling writepages() with WBSYNCNONE. In zoned mode or for compressed writes, it locks several folios for delalloc and starts writing them out. Let's call the last locked folio folio X. Suppose the write range only partially covers folio X, leaving some pages dirty. Process A calls btrfssubpageset_writeback() when building a bio. This function call clears the TOWRITE tag of folio X, whose size = 8K and the block size = 4K. It is following state.

0 4K 8K |/////|/////| (flag: DIRTY, tag: DIRTY) <-----> Process A will write this range.

Now suppose process B concurrently calls writepages() with WBSYNCALL. It calls tagpagesforwriteback() to tag dirty folios with PAGECACHETAGTOWRITE. Since folio X is still dirty, it gets tagged. Then, B collects tagged folios using filemapgetfoliostag() and must wait for folio X to be written before returning from writepages().

0 4K 8K |/////|/////| (flag: DIRTY, tag: DIRTY|TOWRITE)

However, between tagging and collecting, process A may call btrfssubpageset_writeback() and clear folio X's TOWRITE tag. 0 4K 8K | |/////| (flag: DIRTY|WRITEBACK, tag: DIRTY)

As a result, process B won't see folio X in its batch, and returns without waiting for it. This breaks the WBSYNCALL ordering requirement.

Fix this by using btrfssubpagesetwritebackkeepwrite(), which retains the TOWRITE tag. We now manually clear the tag only after the folio becomes clean, via the xas operation.

References

Affected packages

Git / git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git

Affected ranges

Type
GIT
Repo
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
Events
Introduced
3470da3b7d87fde4b9729d4e29c2dc074cd59c10
Fixed
3d61136945a7008fc90d013c3c67007ce0c96131
Type
GIT
Repo
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
Events
Introduced
3470da3b7d87fde4b9729d4e29c2dc074cd59c10
Fixed
bce7a5c77a1e7a759e227b7713dde18c52da4759
Type
GIT
Repo
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
Events
Introduced
3470da3b7d87fde4b9729d4e29c2dc074cd59c10
Fixed
b1511360c8ac882b0c52caa263620538e8d73220

Affected versions

v5.*

v5.12
v5.13
v5.13-rc1
v5.13-rc2
v5.13-rc3
v5.13-rc4
v5.13-rc5
v5.13-rc6
v5.13-rc7
v5.14
v5.14-rc1
v5.14-rc2
v5.14-rc3
v5.14-rc4
v5.14-rc5
v5.14-rc6
v5.14-rc7
v5.15
v5.15-rc1
v5.15-rc2
v5.15-rc3
v5.15-rc4
v5.15-rc5
v5.15-rc6
v5.15-rc7
v5.16
v5.16-rc1
v5.16-rc2
v5.16-rc3
v5.16-rc4
v5.16-rc5
v5.16-rc6
v5.16-rc7
v5.16-rc8
v5.17
v5.17-rc1
v5.17-rc2
v5.17-rc3
v5.17-rc4
v5.17-rc5
v5.17-rc6
v5.17-rc7
v5.17-rc8
v5.18
v5.18-rc1
v5.18-rc2
v5.18-rc3
v5.18-rc4
v5.18-rc5
v5.18-rc6
v5.18-rc7
v5.19
v5.19-rc1
v5.19-rc2
v5.19-rc3
v5.19-rc4
v5.19-rc5
v5.19-rc6
v5.19-rc7
v5.19-rc8

v6.*

v6.0
v6.0-rc1
v6.0-rc2
v6.0-rc3
v6.0-rc4
v6.0-rc5
v6.0-rc6
v6.0-rc7
v6.1
v6.1-rc1
v6.1-rc2
v6.1-rc3
v6.1-rc4
v6.1-rc5
v6.1-rc6
v6.1-rc7
v6.1-rc8
v6.10
v6.10-rc1
v6.10-rc2
v6.10-rc3
v6.10-rc4
v6.10-rc5
v6.10-rc6
v6.10-rc7
v6.11
v6.11-rc1
v6.11-rc2
v6.11-rc3
v6.11-rc4
v6.11-rc5
v6.11-rc6
v6.11-rc7
v6.12
v6.12-rc1
v6.12-rc2
v6.12-rc3
v6.12-rc4
v6.12-rc5
v6.12-rc6
v6.12-rc7
v6.12.1
v6.12.10
v6.12.11
v6.12.12
v6.12.13
v6.12.14
v6.12.15
v6.12.16
v6.12.17
v6.12.18
v6.12.19
v6.12.2
v6.12.20
v6.12.21
v6.12.22
v6.12.23
v6.12.24
v6.12.25
v6.12.26
v6.12.27
v6.12.28
v6.12.29
v6.12.3
v6.12.30
v6.12.31
v6.12.32
v6.12.33
v6.12.34
v6.12.35
v6.12.36
v6.12.37
v6.12.38
v6.12.39
v6.12.4
v6.12.40
v6.12.41
v6.12.42
v6.12.43
v6.12.5
v6.12.6
v6.12.7
v6.12.8
v6.12.9
v6.13
v6.13-rc1
v6.13-rc2
v6.13-rc3
v6.13-rc4
v6.13-rc5
v6.13-rc6
v6.13-rc7
v6.14
v6.14-rc1
v6.14-rc2
v6.14-rc3
v6.14-rc4
v6.14-rc5
v6.14-rc6
v6.14-rc7
v6.15
v6.15-rc1
v6.15-rc2
v6.15-rc3
v6.15-rc4
v6.15-rc5
v6.15-rc6
v6.15-rc7
v6.16
v6.16-rc1
v6.16-rc2
v6.16-rc3
v6.16-rc4
v6.16-rc5
v6.16-rc6
v6.16-rc7
v6.16.1
v6.16.2
v6.16.3
v6.2
v6.2-rc1
v6.2-rc2
v6.2-rc3
v6.2-rc4
v6.2-rc5
v6.2-rc6
v6.2-rc7
v6.2-rc8
v6.3
v6.3-rc1
v6.3-rc2
v6.3-rc3
v6.3-rc4
v6.3-rc5
v6.3-rc6
v6.3-rc7
v6.4
v6.4-rc1
v6.4-rc2
v6.4-rc3
v6.4-rc4
v6.4-rc5
v6.4-rc6
v6.4-rc7
v6.5
v6.5-rc1
v6.5-rc2
v6.5-rc3
v6.5-rc4
v6.5-rc5
v6.5-rc6
v6.5-rc7
v6.6
v6.6-rc1
v6.6-rc2
v6.6-rc3
v6.6-rc4
v6.6-rc5
v6.6-rc6
v6.6-rc7
v6.7
v6.7-rc1
v6.7-rc2
v6.7-rc3
v6.7-rc4
v6.7-rc5
v6.7-rc6
v6.7-rc7
v6.7-rc8
v6.8
v6.8-rc1
v6.8-rc2
v6.8-rc3
v6.8-rc4
v6.8-rc5
v6.8-rc6
v6.8-rc7
v6.9
v6.9-rc1
v6.9-rc2
v6.9-rc3
v6.9-rc4
v6.9-rc5
v6.9-rc6
v6.9-rc7

Linux / Kernel

Package

Name
Kernel

Affected ranges

Type
ECOSYSTEM
Events
Introduced
5.13.0
Fixed
6.12.44
Type
ECOSYSTEM
Events
Introduced
6.13.0
Fixed
6.16.4