PT-2026-84932 · Linux · Linux
CVE-2026-80734
·
Published
2026-09-03
·
Updated
2026-09-03
CVSS v3.1
8.8
High
| Vector | AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H |
In the Linux kernel, the following vulnerability has been resolved:
btrfs: initialize inode mapping flags for cached inodes
[BUG]
When running generic/795 with 8K block size, 4K page size, the test
always fails, triggering some ASSERT()s related to folio size:
795 (241074): drop caches: 3
assertion failed: IS ALIGNED(start, blocksize) && IS ALIGNED(end + 1, blocksize), in extent io.c:1404 (blocksize=8192 root=262 ino=258 start=16826368 end=16830463 mapping min order=0)
------------[ cut here ]------------
kernel BUG at extent io.c:1404!
Oops: invalid opcode: 0000 [#1] SMP
CPU: 8 UID: 0 PID: 241105 Comm: fsstress Tainted: G OE 7.2.0-rc5-custom+ #442 PREEMPT(full) f4bfb352566f3949f29c233ce6f735050a03b245
Tainted: [O]=OOT MODULE, [E]=UNSIGNED MODULE
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS unknown 02/02/2022
RIP: 0010:assert folio range.cold+0x3d/0x3f [btrfs]
Call Trace:
btrfs read folio+0x9e/0x170 [btrfs 4cd1dd93b341b8ef766643f9512f4a86259567a3]
prepare one folio.constprop.0+0x104/0x2a0 [btrfs 4cd1dd93b341b8ef766643f9512f4a86259567a3]
btrfs buffered write+0x285/0xa50 [btrfs 4cd1dd93b341b8ef766643f9512f4a86259567a3]
btrfs do write iter+0x1aa/0x210 [btrfs 4cd1dd93b341b8ef766643f9512f4a86259567a3]
iter file splice write+0x31a/0x540
direct splice actor+0x53/0x170
splice direct to actor+0xe9/0x240
do splice direct+0x76/0xb0
vfs copy file range+0x1fd/0x630
x64 sys copy file range+0xf9/0x220
do syscall 64+0xe1/0x790
entry SYSCALL 64 after hwframe+0x4b/0x53
---[ end trace 0000000000000000 ]---
The ASSERT() itself is added by a later patch.
The crash is triggered with that new debug patch, and without this fix.
[CAUSE]
In the above case, the start 16826368 is properly 8K aligned, but the
end (16830463 + 1) is not 8K aligned.
Furthermore the mapping's minimal folio order is 0, not the expected 1
for 8K block size with 4K page size.
So this means some inodes do not have btrfs set inode mapping order()
called on it.
The missing btrfs set inode mapping order() call happens for cached
inodes, through the following events:
-
btrfs create new inode() called for inode X Which properly sets minimal folio order for the VFS inode.
-
btrfs update inode() called for inode X Which calls btrfs delayed update inode() to create a delayed node into root->delayed nodes xarray.
-
Drop cache/memory pressure, evicting in-memory inode X Which evicted the inode X, but delayed node is still in root->delayed nodes for future reuse.
-
btrfs iget() for inode X called again
btrfs iget()
|- btrfs iget locked()
| |- iget5 locked rcu()
| Which creates a new vfs inode for btrfs, whose mapping still
| has the minimal order as 0.
|
|- btrfs read locked inode()
|- btrfs fill inode()
| |- btrfs get delayed node()
| Which found out the previous node, and use that delayed
| node to initialize the new inode.
|
|- filled = true;
|- if (filled) goto cache index;
Which skips the btrfs update inode mapping flags() and
btrfs set inode mapping order() calls.
So the inode still has minimal folio order set as 0, not
the required 1.
Thus later page cache read will get a folio whose size is smaller than
block size, as the mapping has its minimal folio order set as 0 not 1,
then trigger the ASSERT().
[FIX]
Move the btrfs update inode mapping flags() and
btrfs set inode mapping order() calls under cache index label,
so that the mapping flags and minimal folio order is always set
no matter if we have a cached inode.
Fix
Found an issue in the description? Have something to add? Feel free to write us 👾
Related Identifiers
Affected Products
Linux