Linux-mm Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] mm: thp: unlock i_mmap before releasing split folios
@ 2026-07-10  7:13 Hao Zhang
  2026-07-10 11:16 ` Kiryl Shutsemau
  0 siblings, 1 reply; 5+ messages in thread
From: Hao Zhang @ 2026-07-10  7:13 UTC (permalink / raw)
  To: Andrew Morton; +Cc: David Hildenbrand, Lorenzo Stoakes, linux-mm

From: Hao Zhang <zhanghao1@kylinos.cn>
Date: Thu, 9 Jul 2026 16:30:00 +0800

__folio_split() takes mapping->i_mmap_rwsem while unmapping and
splitting a file-backed large folio. The lock is currently released
only after the split folios that are not returned locked to the caller
have been unlocked and put.

That leaves a lifetime hole. Once the split folios are unlocked and
their references are dropped, inode eviction can make progress through
the final page-cache truncation path. After the folios are removed from
the page cache and the last inode reference is dropped, the inode that
embeds the address_space can be freed after an RCU grace period. A later
i_mmap_unlock_read(mapping) then dereferences mapping->i_mmap_rwsem
from freed memory.

A possible race is:

  CPU0                                    CPU1
  __folio_split()
    i_mmap_lock_read(mapping)
    ...
    remap_page()
    folio_unlock(new_folio)
    free_folio_and_swap_cache(new_folio)
                                          evict inode
                                          truncate_inode_pages_final()
                                          destroy_inode()
                                          call_rcu()
                                          RCU callback frees inode
    i_mmap_unlock_read(mapping)

Release mapping->i_mmap_rwsem after the page-cache and reverse-mapping
work has completed, but before unlocking and putting any of the split
folios. Clear the local mapping pointer after the early unlock so the
common exit path does not unlock it a second time.

Tested with syz-repro on the two available crash logs; neither reproduced
the __folio_split KASAN report on the patched kernel.

Fixes: baa355fd3314 ("thp: file pages support for split_huge_page()")
Signed-off-by: Hao Zhang <zhanghao1@kylinos.cn>
---
 mm/huge_memory.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 2bccb0a53a0a..fadc067df179 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -4109,6 +4109,11 @@ static int __folio_split(struct folio *folio, unsigned int new_order,
 
 	remap_page(folio, 1 << old_order, ttu_flags);
 
+	if (mapping) {
+		i_mmap_unlock_read(mapping);
+		mapping = NULL;
+	}
+
 	/*
 	 * Unlock all after-split folios except the one containing
 	 * @lock_at page. If @folio is not split, it will be kept locked.

base-commit: 0e35b9b6ec0ffcc5e23cbdec09f5c622ad532b53
-- 
2.15.0



^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-07-10 17:17 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-10  7:13 [PATCH] mm: thp: unlock i_mmap before releasing split folios Hao Zhang
2026-07-10 11:16 ` Kiryl Shutsemau
2026-07-10 15:56   ` Hao Zhang
2026-07-10 17:04     ` Lorenzo Stoakes
2026-07-10 17:17     ` Kiryl Shutsemau

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox