Correctly handle small MAP_STACK requests.

If mmap(2) is called with the MAP_STACK flag and the size which is
less or equal to the initial stack mapping size plus guard,
calculation of the mapping layout created zero-sized guard.  Attempt
to create such entry failed in vm_map_insert(), causing the whole
mmap(2) call to fail.

Fix it by adjusting the initial mapping size to have space for
non-empty guard.  Reject MAP_STACK requests which are shorter or equal
to the configured guard pages size.

Reported and tested by:	Manfred Antar <null@pozo.com>
Reviewed by:	alc, markj
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
This commit is contained in:
Konstantin Belousov 2017-06-25 20:06:05 +00:00
parent ae5bb0cac8
commit 19f49ad30f

View File

@ -3567,13 +3567,18 @@ out:
return (rv);
}
static int stack_guard_page = 1;
SYSCTL_INT(_security_bsd, OID_AUTO, stack_guard_page, CTLFLAG_RWTUN,
&stack_guard_page, 0,
"Specifies the number of guard pages for a stack that grows");
static int
vm_map_stack_locked(vm_map_t map, vm_offset_t addrbos, vm_size_t max_ssize,
vm_size_t growsize, vm_prot_t prot, vm_prot_t max, int cow)
{
vm_map_entry_t new_entry, prev_entry;
vm_offset_t bot, gap_bot, gap_top, top;
vm_size_t init_ssize;
vm_size_t init_ssize, sgp;
int orient, rv;
/*
@ -3586,12 +3591,16 @@ vm_map_stack_locked(vm_map_t map, vm_offset_t addrbos, vm_size_t max_ssize,
KASSERT(orient != (MAP_STACK_GROWS_DOWN | MAP_STACK_GROWS_UP),
("bi-dir stack"));
sgp = (vm_size_t)stack_guard_page * PAGE_SIZE;
if (addrbos < vm_map_min(map) ||
addrbos > vm_map_max(map) ||
addrbos + max_ssize < addrbos)
addrbos + max_ssize < addrbos ||
sgp >= max_ssize)
return (KERN_NO_SPACE);
init_ssize = (max_ssize < growsize) ? max_ssize : growsize;
init_ssize = growsize;
if (max_ssize < init_ssize + sgp)
init_ssize = max_ssize - sgp;
/* If addr is already mapped, no go */
if (vm_map_lookup_entry(map, addrbos, &prev_entry))
@ -3645,11 +3654,6 @@ vm_map_stack_locked(vm_map_t map, vm_offset_t addrbos, vm_size_t max_ssize,
return (rv);
}
static int stack_guard_page = 1;
SYSCTL_INT(_security_bsd, OID_AUTO, stack_guard_page, CTLFLAG_RWTUN,
&stack_guard_page, 0,
"Specifies the number of guard pages for a stack that grows.");
/*
* Attempts to grow a vm stack entry. Returns KERN_SUCCESS if we
* successfully grow the stack.