In the Linux kernel, the following vulnerability has been resolved:
btrfs: setpageextentmapped after readfolio in btrfscontexpand
While trying to get the subpage blocksize tests running, I hit the following panic on generic/476
assertion failed: PagePrivate(page) && page->private, in fs/btrfs/subpage.c:229 kernel BUG at fs/btrfs/subpage.c:229! Internal error: Oops - BUG: 00000000f2000800 [#1] SMP CPU: 1 PID: 1453 Comm: fsstress Not tainted 6.4.0-rc7+ #12 Hardware name: QEMU KVM Virtual Machine, BIOS edk2-20230301gitf80f052277c8-26.fc38 03/01/2023 pstate: 61400005 (nZCv daif +PAN -UAO -TCO +DIT -SSBS BTYPE=--) pc : btrfssubpageassert+0xbc/0xf0 lr : btrfssubpageassert+0xbc/0xf0 Call trace: btrfssubpageassert+0xbc/0xf0 btrfssubpageclearchecked+0x38/0xc0 btrfspageclearchecked+0x48/0x98 btrfstruncateblock+0x5d0/0x6a8 btrfscontexpand+0x5c/0x528 btrfswritecheck.isra.0+0xf8/0x150 btrfsbufferedwrite+0xb4/0x760 btrfsdowriteiter+0x2f8/0x4b0 btrfsfilewriteiter+0x1c/0x30 doiterreadvwritev+0xc8/0x158 doiterwrite+0x9c/0x210 vfsiterwrite+0x24/0x40 iterfilesplicewrite+0x224/0x390 directspliceactor+0x38/0x68 splicedirecttoactor+0x12c/0x260 dosplicedirect+0x90/0xe8 genericcopyfilerange+0x50/0x90 vfscopyfilerange+0x29c/0x470 _arm64syscopyfilerange+0xcc/0x498 invokesyscall.constprop.0+0x80/0xd8 doel0svc+0x6c/0x168 el0svc+0x50/0x1b0 el0t64synchandler+0x114/0x120 el0t64_sync+0x194/0x198
This happens because during btrfscontexpand we'll get a page, set it as mapped, and if it's not Uptodate we'll read it. However between the read and re-locking the page we could have called releasefolio() on the page, but left the page in the file mapping. releasefolio() can clear the page private, and thus further down we blow up when we go to modify the subpage bits.
Fix this by putting the setpageextentmapped() after the read. This is safe because readfolio() will call setpageextentmapped() before it does the read, and then if we clear page private but leave it on the mapping we're completely safe re-setting setpageextentmapped(). With this patch I can now run generic/476 without panicing.