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) {