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:
Alan Cox 2023-08-03 02:07:14 -05:00
parent 9b65fa6940
commit 37e5d49e1e
2 changed files with 18 additions and 12 deletions

View File

@ -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;
}
}

View File

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