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.

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;
+
        /* Returns with the map read-locked if successful */
        vm_map_pageable_scan(map, entry, end);
 
-- 
2.47.3


Reply via email to