From 01c6a48b571bfaa2a4dcceed289d6b67cf7404f0 Mon Sep 17 00:00:00 2001 From: Shawn Webb Date: Wed, 21 Jun 2017 12:09:32 -0400 Subject: [PATCH] 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 Sponsored-by: SoldierX (cherry picked from commit 7e16dbbf12a5bc7908c10b0d66dfa0de5c4f5d32) --- sys/vm/vm_mmap.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c index 2b94ff642f5..09970295ac9 100644 --- a/sys/vm/vm_mmap.c +++ b/sys/vm/vm_mmap.c @@ -94,6 +94,8 @@ __FBSDID("$FreeBSD$"); #include #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) {