From: Chen Wandun 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 -EINVAL early when hstart > hend. 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. Signed-off-by: Chen Wandun --- v1 --> v2: - Rebase and resolve code conflict. - Return -EINVAL when hstart > hend, suggested by Lorenzo. - Drop Fixes tag, suggested by David and Lorenzo. - Updated commit message to be more explicit, suggested by Lorenzo. --- mm/khugepaged.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/mm/khugepaged.c b/mm/khugepaged.c index 28a843f30b32..36baab17f098 100644 --- a/mm/khugepaged.c +++ b/mm/khugepaged.c @@ -2837,6 +2837,15 @@ int madvise_collapse(struct vm_area_struct *vma, unsigned long start, if (!thp_vma_allowable_order(vma, vma->vm_flags, TVA_FORCED_COLLAPSE, PMD_ORDER)) return -EINVAL; + hstart = ALIGN(start, HPAGE_PMD_SIZE); + hend = ALIGN_DOWN(end, HPAGE_PMD_SIZE); + + if (hstart > hend) + return -EINVAL; + + if (hstart == hend) + return 0; + cc = kmalloc_obj(*cc); if (!cc) return -ENOMEM; @@ -2846,9 +2855,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; -- 2.43.0