HBSD: Do not allow non-stack mappings between bottom-most limit of stack and the top of the stack

The space between the bottom-most limit of the stack and the top of the
stack should not be able to be mapped via mmap(2). This should fully
mitigate Stack Clash in conjunction with the hardened stack guard.

Signed-off-by:	Shawn Webb <shawn.webb@hardenedbsd.org>
Sponsored-by:	SoldierX
(cherry picked from commit 7e16dbbf12)
This commit is contained in:
Shawn Webb 2017-06-21 12:09:32 -04:00 committed by Franco Fichtner
parent fd30a6ef8a
commit 01c6a48b57

View file

@ -94,6 +94,8 @@ __FBSDID("$FreeBSD$");
#include <sys/pmckern.h>
#endif
static int check_address_limit(struct thread *, vm_offset_t, bool);
int old_mlock = 0;
SYSCTL_INT(_vm, OID_AUTO, old_mlock, CTLFLAG_RWTUN, &old_mlock, 0,
"Do not apply RLIMIT_MEMLOCK on mlockall");
@ -108,6 +110,25 @@ struct sbrk_args {
};
#endif
static int
check_address_limit(struct thread *td, vm_offset_t addr, bool needlock)
{
rlim_t stacklim;
int error;
error = 0;
stacklim = lim_cur(td, RLIMIT_STACK);
if (needlock)
PROC_LOCK(td->td_proc);
if (addr >= td->td_proc->p_usrstack - stacklim)
error = EINVAL;
if (needlock)
PROC_UNLOCK(td->td_proc);
return (error);
}
/*
* MPSAFE
*/
@ -300,6 +321,11 @@ sys_mmap(td, uap)
return (EINVAL);
if (addr + size < addr)
return (EINVAL);
/* Address range must be below stack limits. */
error = check_address_limit(td, addr, true);
if (error)
return (error);
#ifdef MAP_32BIT
if (flags & MAP_32BIT && addr + size > MAP_32BIT_MAX_ADDR)
return (EINVAL);
@ -338,7 +364,10 @@ sys_mmap(td, uap)
PROC_LOCK(td->td_proc);
pax_aslr_mmap(td->td_proc, &addr, (vm_offset_t)uap->addr, flags);
pax_aslr_done = 1;
error = check_address_limit(td, addr, false);
PROC_UNLOCK(td->td_proc);
if (error)
return (error);
#endif
}
if (size == 0) {