From: Chen Wandun Date: Wed, 13 May 2026 05:54:28 +0000 (+0800) Subject: mm/khugepaged: avoid underflow in madvise_collapse for sub-PMD MADV_COLLAPSE X-Git-Tag: v7.2-rc1~59^2~28 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b89a641056227403bf54847caf228b8a607c5fc4;p=thirdparty%2Fkernel%2Flinux.git mm/khugepaged: avoid underflow in madvise_collapse for sub-PMD MADV_COLLAPSE madvise_collapse() computes the THP-aligned window: hstart = ALIGN(start, HPAGE_PMD_SIZE); /* round up */ hend = ALIGN_DOWN(end, HPAGE_PMD_SIZE); /* round down */ The following case will cause hstart > hend, and result in underflow in the return statement, avoid it by returning zero early when hstart > hend. The return value is due to input is valid to madvise(), and there is nothing to collapse. madvise(PMD-aligned + PAGE_SIZE, PAGE_SIZE, MADV_COLLAPSE); In addition, kmalloc_obj(), mmgrab() and lru_add_drain_all() are unnecessary when hstart == hend, so skip these operations by returning early too. Link: https://lore.kernel.org/20260513055428.1664898-1-chenwandun@lixiang.com Signed-off-by: Chen Wandun Acked-by: David Hildenbrand (Arm) Reviewed-by: Lorenzo Stoakes Cc: Baolin Wang Cc: Barry Song Cc: Dev Jain Cc: Lance Yang Cc: Liam R. Howlett Cc: Nico Pache Cc: Ryan Roberts Cc: Zi Yan Signed-off-by: Andrew Morton --- diff --git a/mm/khugepaged.c b/mm/khugepaged.c index e69a0fb4c7ccc..617bca76db49b 100644 --- a/mm/khugepaged.c +++ b/mm/khugepaged.c @@ -3198,6 +3198,12 @@ int madvise_collapse(struct vm_area_struct *vma, unsigned long start, if (!collapse_possible(vma, vma->vm_flags, TVA_FORCED_COLLAPSE)) return -EINVAL; + hstart = ALIGN(start, HPAGE_PMD_SIZE); + hend = ALIGN_DOWN(end, HPAGE_PMD_SIZE); + + if (hstart >= hend) + return 0; + cc = kmalloc_obj(*cc); if (!cc) return -ENOMEM; @@ -3207,9 +3213,6 @@ int madvise_collapse(struct vm_area_struct *vma, unsigned long start, mmgrab(mm); lru_add_drain_all(); - hstart = ALIGN(start, HPAGE_PMD_SIZE); - hend = ALIGN_DOWN(end, HPAGE_PMD_SIZE); - for (addr = hstart; addr < hend; addr += HPAGE_PMD_SIZE) { enum scan_result result = SCAN_FAIL;