Skip to content

Commit 592db83

Browse files
RichardWeiYanggregkh
authored andcommitted
mm/huge_memory: fix NULL pointer deference when splitting folio
[ Upstream commit cff47b9 ] Commit c010d47 ("mm: thp: split huge page to any lower order pages") introduced an early check on the folio's order via mapping->flags before proceeding with the split work. This check introduced a bug: for shmem folios in the swap cache and truncated folios, the mapping pointer can be NULL. Accessing mapping->flags in this state leads directly to a NULL pointer dereference. This commit fixes the issue by moving the check for mapping != NULL before any attempt to access mapping->flags. Link: https://lkml.kernel.org/r/20251119235302.24773-1-richard.weiyang@gmail.com Fixes: c010d47 ("mm: thp: split huge page to any lower order pages") Signed-off-by: Wei Yang <richard.weiyang@gmail.com> Reviewed-by: Zi Yan <ziy@nvidia.com> Acked-by: David Hildenbrand (Red Hat) <david@kernel.org> Reviewed-by: Baolin Wang <baolin.wang@linux.alibaba.com> Cc: <stable@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> [ applied fix to split_huge_page_to_list_to_order() instead of __folio_split() ] Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 1001431 commit 592db83

1 file changed

Lines changed: 10 additions & 7 deletions

File tree

mm/huge_memory.c

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3404,6 +3404,16 @@ int split_huge_page_to_list_to_order(struct page *page, struct list_head *list,
34043404
if (new_order >= folio_order(folio))
34053405
return -EINVAL;
34063406

3407+
/*
3408+
* Folios that just got truncated cannot get split. Signal to the
3409+
* caller that there was a race.
3410+
*
3411+
* TODO: this will also currently refuse shmem folios that are in the
3412+
* swapcache.
3413+
*/
3414+
if (!is_anon && !folio->mapping)
3415+
return -EBUSY;
3416+
34073417
if (is_anon) {
34083418
/* order-1 is not supported for anonymous THP. */
34093419
if (new_order == 1) {
@@ -3466,13 +3476,6 @@ int split_huge_page_to_list_to_order(struct page *page, struct list_head *list,
34663476
gfp_t gfp;
34673477

34683478
mapping = folio->mapping;
3469-
3470-
/* Truncated ? */
3471-
if (!mapping) {
3472-
ret = -EBUSY;
3473-
goto out;
3474-
}
3475-
34763479
min_order = mapping_min_folio_order(folio->mapping);
34773480
if (new_order < min_order) {
34783481
VM_WARN_ONCE(1, "Cannot split mapped folio below min-order: %u",

0 commit comments

Comments
 (0)