In the Linux kernel, the following vulnerability has been resolved:
mm/hugememory: unlock immap_rwsem before releasing after-split folios
__foliosplit() keeps dereferencing the mapping after the split: shmemuncharge(mapping->host) and remappage() while the folios are still frozen/locked, and immapunlockread(mapping) at the very end, after the after-split folios have been unlocked and freed.
Nothing holds an inode reference across that. The split relies on @folio -- which the beyond-EOF drop loop never removes, as it starts at folionext(folio) -- staying locked and in the page cache to hold off eviction. But the unlock loop unlocks @folio before immapunlockread() runs. If the caller's @lockat is a tail beyond EOF, as memoryfailure() passes when splitting a poisoned tail of a shmem THP that reaches past isize during truncation, it too is gone from the page cache; so once @folio is unlocked no locked, in-cache folio pins the inode, and a concurrent final iput() can evict and RCU-free it before immapunlockread() touches immaprwsem:
BUG: KASAN: slab-use-after-free in __upread+0x634/0x790 immapunlockread include/linux/fs.h:537 [inline] _foliosplit+0x732/0x1640 mm/hugememory.c:4100 trytosplitthppage+0xab/0x390 mm/memory-failure.c:1675 memoryfailure+0x1394/0x26e0 mm/memory-failure.c:2470
Freed by task 4601: shmemfreeincoreinode+0x54/0xb0 mm/shmem.c:5177 evict+0x57f/0xac0 fs/inode.c:870
Do every mapping dereference while @folio still pins the inode: drop immaprwsem right after remappage(), before the loop that unlocks and frees the after-split folios, and clear @mapping so the exit path does not unlock it again. shmemuncharge() and remap_page() already run before that point, so after this nothing past the unlock loop touches the inode or the mapping.
This is now a rule the split depends on, alongside keeping @folio frozen until the page cache is updated: no inode or mapping dereference once the after-split folios start being unlocked.