Re: [PATCH 3/3] mm/mremap: check map count under mmap write lock and abstract
From: Pedro Falcato
Date: Fri Mar 27 2026 - 05:27:37 EST
On Wed, Mar 11, 2026 at 05:24:38PM +0000, Lorenzo Stoakes (Oracle) wrote:
> We are checking the mmap count in check_mremap_params(), prior to obtaining
> an mmap write lock, which means that accesses to current->mm->map_count
> might race with this field being updated.
>
> Resolve this by only checking this field after the mmap write lock is held.
>
> Additionally, abstract this check into a helper function with extensive
> ASCII documentation of what's going on.
>
> Reported-by: Jianzhou Zhao <luckd0g@xxxxxxx>
> Closes: https://lore.kernel.org/all/1a7d4c26.6b46.19cdbe7eaf0.Coremail.luckd0g@xxxxxxx/
> Signed-off-by: Lorenzo Stoakes (Oracle) <ljs@xxxxxxxxxx>
Reviewed-by: Pedro Falcato <pfalcato@xxxxxxx>
Shouldn't this have a Fixes: and go to stable?
> ---
> mm/mremap.c | 88 +++++++++++++++++++++++++++++++++++++++++++++--------
> 1 file changed, 75 insertions(+), 13 deletions(-)
>
> diff --git a/mm/mremap.c b/mm/mremap.c
> index ba6c690f6c1b..ee46bbb031e6 100644
> --- a/mm/mremap.c
> +++ b/mm/mremap.c
> @@ -1028,6 +1028,75 @@ static void vrm_stat_account(struct vma_remap_struct *vrm,
> mm->locked_vm += pages;
> }
>
> +static bool __check_map_count_against_split(struct mm_struct *mm,
> + bool before_unmaps)
> +{
> + const int sys_map_count = get_sysctl_max_map_count();
> + int map_count = mm->map_count;
> +
> + mmap_assert_write_locked(mm);
> +
> + /*
> + * At the point of shrinking the VMA, if new_len < old_len, we unmap
> + * thusly in the worst case:
> + *
> + * old_addr+old_len old_addr+old_len
> + * |---------------.----.---------| |---------------| |---------|
> + * | . . | -> | +1 | -1 | +1 |
> + * |---------------.----.---------| |---------------| |---------|
> + * old_addr+new_len old_addr+new_len
> + *
> + * At the point of removing the portion of an existing VMA to make space
> + * for the moved VMA if MREMAP_FIXED, we unmap thusly in the worst case:
> + *
> + * new_addr new_addr+new_len new_addr new_addr+new_len
> + * |----.---------------.---------| |----| |---------|
> + * | . . | -> | +1 | -1 | +1 |
> + * |----.---------------.---------| |----| |---------|
> + *
> + * Therefore, before we consider the move anything, we have to account
> + * for 2 additional VMAs possibly being created upon these unmappings.
> + */
> + if (before_unmaps)
> + map_count += 2;
oooh, shiny shiny diagrams.
--
Pedro