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);
