В ядре Linux устранена следующая уязвимость:
mm/huge_memory: разблокируйте i_mmap_rwsem перед выпуском фолио после разделения.
__folio_split() продолжает разыменовывать сопоставление после разделения:
shmem_uncharge(mapping->host) и remap_page(), пока фолио все еще
заморожено/заблокировано, а i_mmap_unlock_read(отображение) в самом конце, после
фолианты после разделения были разблокированы и освобождены. Ничто не содержит ссылку на индексный дескриптор. Разделение зависит от @folio
-- который цикл отбрасывания за пределами EOF никогда не удаляет, поскольку он начинается с
folio_next(folio) — оставаться заблокированным и в кэше страниц, чтобы удерживаться
выселение.
Но цикл разблокировки разблокирует @folio до i_mmap_unlock_read().
бежит. Если @lock_at вызывающего абонента находится за пределами EOF, как и Memory_failure()
проходит при расщеплении отравленного хвоста шмема THP, достигающего прошлого
i_size во время усечения он тоже удаляется из кэша страниц; так однажды
@folio разблокирован, но не заблокирован, фолио в кеше закрепляет индексный дескриптор, а
одновременный окончательный iput() может выселить и освободить RCU раньше
i_mmap_unlock_read() касается i_mmap_rwsem:
ОШИБКА: KASAN: slab-use-after-free в __up_read+0x634/0x790
i_mmap_unlock_read include/linux/fs.h:537 [встроенный]
__folio_split+0x732/0x1640 мм/huge_memory.c:4100
try_to_split_thp_page+0xab/0x390 мм/memory-failure.c:1675
Memory_failure+0x1394/0x26e0 мм/memory-failure.c:2470
Освобожден заданием 4601:
shmem_free_in_core_inode+0x54/0xb0 мм/shmem.c:5177
выселение+0x57f/0xac0 фс/inode.c:870
Выполняйте каждое разыменование сопоставления, пока @folio все еще закрепляет индексный дескриптор: drop
i_mmap_rwsem сразу после remap_page(), перед циклом, который разблокирует и
освобождает фолио после разделения и очищает @mapping, чтобы путь выхода не
разблокируйте его снова. shmem_uncharge() и remap_page() уже выполнялись ранее
в этот момент, поэтому после этого ничто за пределами цикла разблокировки не касается индексного дескриптора
или картографирование. Теперь это правило, от которого зависит разделение, а также замораживание @folio.
до тех пор, пока кеш страниц не будет обновлен: не будет разыменования индексного дескриптора или сопоставления после
фолио после разделения начинают разблокироваться.
Показать оригинальное описание (EN)
In the Linux kernel, the following vulnerability has been resolved: mm/huge_memory: unlock i_mmap_rwsem before releasing after-split folios __folio_split() keeps dereferencing the mapping after the split: shmem_uncharge(mapping->host) and remap_page() while the folios are still frozen/locked, and i_mmap_unlock_read(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 folio_next(folio) -- staying locked and in the page cache to hold off eviction. But the unlock loop unlocks @folio before i_mmap_unlock_read() runs. If the caller's @lock_at is a tail beyond EOF, as memory_failure() passes when splitting a poisoned tail of a shmem THP that reaches past i_size 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 i_mmap_unlock_read() touches i_mmap_rwsem: BUG: KASAN: slab-use-after-free in __up_read+0x634/0x790 i_mmap_unlock_read include/linux/fs.h:537 [inline] __folio_split+0x732/0x1640 mm/huge_memory.c:4100 try_to_split_thp_page+0xab/0x390 mm/memory-failure.c:1675 memory_failure+0x1394/0x26e0 mm/memory-failure.c:2470 Freed by task 4601: shmem_free_in_core_inode+0x54/0xb0 mm/shmem.c:5177 evict+0x57f/0xac0 fs/inode.c:870 Do every mapping dereference while @folio still pins the inode: drop i_mmap_rwsem right after remap_page(), before the loop that unlocks and frees the after-split folios, and clear @mapping so the exit path does not unlock it again. shmem_uncharge() 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.
Характеристики атаки
Последствия
Строка CVSS v3.1