vm: Fix address hints of 0 with MAP_32BIT
Also, rename min_addr to default_addr, which better reflects what it
represents. The min_addr is not a minimum address in the same way that
max_addr is actually a maximum address that can be allocated. For
example, a non-zero hint can be less than min_addr and be allocated.
Reported by: dchagin
Reviewed by: dchagin, kib, markj
Fixes: d8e6f4946c
"vm: Fix anonymous memory clustering under ASLR"
Differential Revision: https://reviews.freebsd.org/D41397
This commit is contained in:
parent
9b65fa6940
commit
37e5d49e1e
@ -2255,19 +2255,19 @@ vm_map_find(vm_map_t map, vm_object_t object, vm_ooffset_t offset,
|
||||
|
||||
/*
|
||||
* vm_map_find_min() is a variant of vm_map_find() that takes an
|
||||
* additional parameter (min_addr) and treats the given address
|
||||
* (*addr) differently. Specifically, it treats *addr as a hint
|
||||
* additional parameter ("default_addr") and treats the given address
|
||||
* ("*addr") differently. Specifically, it treats "*addr" as a hint
|
||||
* and not as the minimum address where the mapping is created.
|
||||
*
|
||||
* This function works in two phases. First, it tries to
|
||||
* allocate above the hint. If that fails and the hint is
|
||||
* greater than min_addr, it performs a second pass, replacing
|
||||
* the hint with min_addr as the minimum address for the
|
||||
* greater than "default_addr", it performs a second pass, replacing
|
||||
* the hint with "default_addr" as the minimum address for the
|
||||
* allocation.
|
||||
*/
|
||||
int
|
||||
vm_map_find_min(vm_map_t map, vm_object_t object, vm_ooffset_t offset,
|
||||
vm_offset_t *addr, vm_size_t length, vm_offset_t min_addr,
|
||||
vm_offset_t *addr, vm_size_t length, vm_offset_t default_addr,
|
||||
vm_offset_t max_addr, int find_space, vm_prot_t prot, vm_prot_t max,
|
||||
int cow)
|
||||
{
|
||||
@ -2277,14 +2277,14 @@ vm_map_find_min(vm_map_t map, vm_object_t object, vm_ooffset_t offset,
|
||||
hint = *addr;
|
||||
if (hint == 0) {
|
||||
cow |= MAP_NO_HINT;
|
||||
*addr = hint = min_addr;
|
||||
*addr = hint = default_addr;
|
||||
}
|
||||
for (;;) {
|
||||
rv = vm_map_find(map, object, offset, addr, length, max_addr,
|
||||
find_space, prot, max, cow);
|
||||
if (rv == KERN_SUCCESS || min_addr >= hint)
|
||||
if (rv == KERN_SUCCESS || default_addr >= hint)
|
||||
return (rv);
|
||||
*addr = hint = min_addr;
|
||||
*addr = hint = default_addr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1555,7 +1555,7 @@ vm_mmap_object(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot,
|
||||
vm_prot_t maxprot, int flags, vm_object_t object, vm_ooffset_t foff,
|
||||
boolean_t writecounted, struct thread *td)
|
||||
{
|
||||
vm_offset_t max_addr;
|
||||
vm_offset_t default_addr, max_addr;
|
||||
int docow, error, findspace, rv;
|
||||
bool curmap, fitit;
|
||||
|
||||
@ -1630,10 +1630,16 @@ vm_mmap_object(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot,
|
||||
max_addr = MAP_32BIT_MAX_ADDR;
|
||||
#endif
|
||||
if (curmap) {
|
||||
rv = vm_map_find_min(map, object, foff, addr, size,
|
||||
default_addr =
|
||||
round_page((vm_offset_t)td->td_proc->p_vmspace->
|
||||
vm_daddr + lim_max(td, RLIMIT_DATA)), max_addr,
|
||||
findspace, prot, maxprot, docow);
|
||||
vm_daddr + lim_max(td, RLIMIT_DATA));
|
||||
#ifdef MAP_32BIT
|
||||
if ((flags & MAP_32BIT) != 0)
|
||||
default_addr = 0;
|
||||
#endif
|
||||
rv = vm_map_find_min(map, object, foff, addr, size,
|
||||
default_addr, max_addr, findspace, prot, maxprot,
|
||||
docow);
|
||||
} else {
|
||||
rv = vm_map_find(map, object, foff, addr, size,
|
||||
max_addr, findspace, prot, maxprot, docow);
|
||||
|
Loading…
Reference in New Issue
Block a user