On 26/10/26 1:33 pm, Hao Ge wrote:
> commit a739e6b557af ("mm: vmalloc: WARN_ON if mapping size is not
> PAGE_SIZE aligned") made vmap_pte_range() warn and bail out when the
> size is not a multiple of PAGE_SIZE. That loop steps in page

Why are we checking the alignment so late into vmap_pte_range? Why not
simply do

if (!IS_ALIGNED(addr, PAGE_SIZE) || !IS_ALIGNED(end, PAGE_SIZE))
        return; (or return -EINVAL);

at the start of vmap_range_noflush and vunmap_range_noflush?


> multiples and stops only at addr == end; with an unaligned size addr
> never lands on end, so the loop cannot terminate and walks off the
> end of the page table.
> 
> vunmap_pte_range() has the same loop without any guard, so an
> unaligned range would clear PTEs past end without ever stopping,
> walking off the end of the page table.
> 
> Add the check there too. The range is clamped down to the last full
> page rather than dropped, and the loop is skipped when nothing is
> left, so a buggy caller still gets its PTEs cleared as far as they
> go.
> 
> Reported-by: Sashiko <[email protected]>
> Signed-off-by: Hao Ge <[email protected]>
> ---
>  mm/vmalloc.c | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/mm/vmalloc.c b/mm/vmalloc.c
> index 44e0eb32708f..7131f60d1a8e 100644
> --- a/mm/vmalloc.c
> +++ b/mm/vmalloc.c
> @@ -393,6 +393,11 @@ static void vunmap_pte_range(pmd_t *pmd, unsigned long 
> addr, unsigned long end,
>       pte_t ptent;
>       unsigned long size = PAGE_SIZE;
>  
> +     if (WARN_ON_ONCE(!PAGE_ALIGNED(end - addr)))
> +             end = addr + PAGE_ALIGN_DOWN(end - addr);
> +     if (end == addr)
> +             return;
> +
>       pte = pte_offset_kernel(pmd, addr);
>       lazy_mmu_mode_enable();
>  


Reply via email to