diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c --- a/sys/vm/vm_map.c +++ b/sys/vm/vm_map.c @@ -1978,7 +1978,8 @@ static int cluster_anon = 1; SYSCTL_INT(_vm, OID_AUTO, cluster_anon, CTLFLAG_RW, &cluster_anon, 0, - "Cluster anonymous mappings: 0 = no, 1 = yes if no hint, 2 = always"); + "Cluster anonymous mappings: " + "0 = no, 1 = yes if no hint, 2 = always, 3 = keep anon_loc const"); static bool clustering_anon_allowed(vm_offset_t addr) @@ -1995,6 +1996,12 @@ } } +static bool +clustering_anon_loc_const(void) +{ + return (cluster_anon == 3); +} + static long aslr_restarts; SYSCTL_LONG(_vm, OID_AUTO, aslr_restarts, CTLFLAG_RD, &aslr_restarts, 0, @@ -2093,6 +2100,7 @@ vm_size_t length, vm_offset_t max_addr, int find_space, vm_prot_t prot, vm_prot_t max, int cow) { + vm_map_entry_t entry; vm_offset_t alignment, curr_min_addr, min_addr; int gap, pidx, rv, try; bool cluster, en_aslr, update_anon; @@ -2127,6 +2135,8 @@ curr_min_addr = map->anon_loc; if (curr_min_addr == 0) cluster = false; + else if (!vm_map_lookup_entry(map, curr_min_addr, &entry)) + curr_min_addr = entry->end; } if (find_space != VMFS_NO_SPACE) { KASSERT(find_space == VMFS_ANY_SPACE || @@ -2226,7 +2236,7 @@ rv = vm_map_insert(map, object, offset, *addr, *addr + length, prot, max, cow); } - if (rv == KERN_SUCCESS && update_anon) + if (rv == KERN_SUCCESS && update_anon && !clustering_anon_loc_const()) map->anon_loc = *addr + length; done: vm_map_unlock(map); @@ -3966,7 +3976,7 @@ entry->object.vm_object != NULL) pmap_map_delete(map->pmap, entry->start, entry->end); - if (entry->end == map->anon_loc) + if (entry->end == map->anon_loc&& !clustering_anon_loc_const()) map->anon_loc = entry->start; /*