Hello,

David Bidner, le lun. 21 sept. 2026 17:44:17 +0200, a ecrit:
> vm_map_protect() calls vm_map_coalesce_entry() for the start entry too.
> Coalescing can merge that entry into its predecessor and free it, but the
> old pointer is still passed to vm_map_pageable_scan(), which then walks the
> freed entry's recycled vme_next list.
> 
> Re-find the entry containing start, with the map write lock still held,
> before calling vm_map_pageable_scan().  This is the same lookup done before
> the loop, so the non-coalescing path is unchanged.

Thanks for spotting it!

> Applies to GNU Mach master c5701c1c.
> ---
>  vm/vm_map.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/vm/vm_map.c b/vm/vm_map.c
> index a3e57f66..a0f98702 100644
> --- a/vm/vm_map.c
> +++ b/vm/vm_map.c
> @@ -1814,6 +1814,9 @@ kern_return_t vm_map_protect(
>       if (vm_map_coalesce_entry(map, current))
>               current = next;
>  
> +     if (!vm_map_lookup_entry(map, start, &entry))
> +             entry = entry->vme_next;
> +

Since entry is released, you need to read the vme_next field before
calling vm_map_coalesce_entry, just like we do for current->vme_next.

Also, I guess we can avoid doing this when vm_map_coalesce_entry
returned false?

Samuel

>       /* Returns with the map read-locked if successful */
>       vm_map_pageable_scan(map, entry, end);

Reply via email to