From 99a3501ffffe62fc6041313a0ecfbbd5a0cf82aa Mon Sep 17 00:00:00 2001 From: Sofian Brabez Date: Thu, 26 Sep 2013 11:07:00 +0200 Subject: [PATCH] add kern.stackgap_random and bsd.security.mmap_random in order to bring randomization at linker and stack level Obtained from: OpenBSD --- sys/amd64/include/vmparam.h | 2 ++ sys/arm/include/vmparam.h | 2 ++ sys/i386/include/vmparam.h | 2 ++ sys/kern/kern_exec.c | 35 +++++++++++++++++++++++++++++++++-- sys/sparc64/include/vmparam.h | 2 ++ sys/sys/exec.h | 4 +++- sys/sys/sysctl.h | 1 + sys/vm/vm_mmap.c | 6 ++++++ 8 files changed, 51 insertions(+), 3 deletions(-) diff --git a/sys/amd64/include/vmparam.h b/sys/amd64/include/vmparam.h index 474ea4b..30ee421 100644 --- a/sys/amd64/include/vmparam.h +++ b/sys/amd64/include/vmparam.h @@ -69,6 +69,8 @@ #define SGROWSIZ (128UL*1024) /* amount to grow stack */ #endif +#define STACKGAP_RANDOM (256*1024) + /* * We provide a machine specific single page allocator through the use * of the direct mapped segment. This uses 2MB pages for reduced diff --git a/sys/arm/include/vmparam.h b/sys/arm/include/vmparam.h index 93d7587..18ba3db 100644 --- a/sys/arm/include/vmparam.h +++ b/sys/arm/include/vmparam.h @@ -60,6 +60,8 @@ #define SGROWSIZ (128UL*1024) /* amount to grow stack */ #endif +#define STACKGAP_RANDOM (256*1024) + /* * Address space constants */ diff --git a/sys/i386/include/vmparam.h b/sys/i386/include/vmparam.h index 19cdd8e..58ba98c 100644 --- a/sys/i386/include/vmparam.h +++ b/sys/i386/include/vmparam.h @@ -63,6 +63,8 @@ #define SGROWSIZ (128UL*1024) /* amount to grow stack */ #endif +#define STACKGAP_RANDOM (256*1024) + /* * The physical address space is densely populated. */ diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index 45f732b..8db1ecf 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -105,6 +105,7 @@ MALLOC_DEFINE(M_PARGS, "proc-args", "Process arguments"); static int sysctl_kern_ps_strings(SYSCTL_HANDLER_ARGS); static int sysctl_kern_usrstack(SYSCTL_HANDLER_ARGS); static int sysctl_kern_stackprot(SYSCTL_HANDLER_ARGS); +static int sysctl_kern_stackgap_random(SYSCTL_HANDLER_ARGS); static int do_execve(struct thread *td, struct image_args *args, struct mac *mac_p); @@ -119,8 +120,11 @@ SYSCTL_PROC(_kern, KERN_USRSTACK, usrstack, CTLTYPE_ULONG|CTLFLAG_RD| SYSCTL_PROC(_kern, OID_AUTO, stackprot, CTLTYPE_INT|CTLFLAG_RD, NULL, 0, sysctl_kern_stackprot, "I", ""); +SYSCTL_PROC(_kern, OID_AUTO, stackgap_random, CTLTYPE_INT|CTLFLAG_RW, + NULL, 0, sysctl_kern_stackgap_random, "I", "stackgap maximum offset"); + u_long ps_arg_cache_limit = PAGE_SIZE / 16; -SYSCTL_ULONG(_kern, OID_AUTO, ps_arg_cache_limit, CTLFLAG_RW, +SYSCTL_ULONG(_kern, OID_AUTO, ps_arg_cache_limit, CTLFLAG_RW, &ps_arg_cache_limit, 0, ""); static int map_at_zero = 0; @@ -128,6 +132,26 @@ TUNABLE_INT("security.bsd.map_at_zero", &map_at_zero); SYSCTL_INT(_security_bsd, OID_AUTO, map_at_zero, CTLFLAG_RW, &map_at_zero, 0, "Permit processes to map an object at virtual address 0."); +static int stackgap_random = STACKGAP_RANDOM; + +static int +sysctl_kern_stackgap_random(SYSCTL_HANDLER_ARGS) +{ + int error, stackgap; + + stackgap = stackgap_random; + error = sysctl_handle_int(oidp, &stackgap, sizeof(int), req); + if (error || !req->newptr) + return (error); + + if ((stackgap < ALIGNBYTES && stackgap != 0) || + !powerof2(stackgap) || stackgap >= MAXSSIZ) + return (EINVAL); + + stackgap_random = stackgap; + return (0); +} + static int sysctl_kern_ps_strings(SYSCTL_HANDLER_ARGS) { @@ -1224,6 +1248,7 @@ exec_copyout_strings(imgp) struct proc *p; size_t execpath_len; int szsigcode, szps; + int sgap; char canary[sizeof(long) * 8]; szps = sizeof(pagesizes[0]) * MAXPAGESIZES; @@ -1242,7 +1267,13 @@ exec_copyout_strings(imgp) if (p->p_sysent->sv_szsigcode != NULL) szsigcode = *(p->p_sysent->sv_szsigcode); } - destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE - + + sgap = STACKGAPLEN; + if (stackgap_random != 0) + sgap += (arc4random() * ALIGNBYTES) & (stackgap_random -1); + sgap = ALIGN(sgap); + + destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE - sgap - roundup(execpath_len, sizeof(char *)) - roundup(sizeof(canary), sizeof(char *)) - roundup(szps, sizeof(char *)) - diff --git a/sys/sparc64/include/vmparam.h b/sys/sparc64/include/vmparam.h index 3cd744c..b806501 100644 --- a/sys/sparc64/include/vmparam.h +++ b/sys/sparc64/include/vmparam.h @@ -61,6 +61,8 @@ #define SGROWSIZ (128*1024) /* amount to grow stack */ #endif +#define STACKGAP_RANDOM (256*1024) + /* * The physical address space is sparsely populated. */ diff --git a/sys/sys/exec.h b/sys/sys/exec.h index 140ab2e..d733d29 100644 --- a/sys/sys/exec.h +++ b/sys/sys/exec.h @@ -56,9 +56,11 @@ struct ps_strings { /* * Address of ps_strings structure (in user space). */ -#define PS_STRINGS (USRSTACK - sizeof(struct ps_strings)) +#define PS_STRINGS (USRSTACK - sizeof(struct ps_strings)) #define SPARE_USRSPACE 4096 +#define STACKGAPLEN (2*1024) + struct image_params; struct execsw { diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h index 64292ba..6ed63ee 100644 --- a/sys/sys/sysctl.h +++ b/sys/sys/sysctl.h @@ -497,6 +497,7 @@ SYSCTL_ALLOWED_TYPES(UINT64, uint64_t *a; unsigned long long *b; ); #define KERN_HOSTUUID 36 /* string: host UUID identifier */ #define KERN_ARND 37 /* int: from arc4rand() */ #define KERN_MAXID 38 /* number of valid kern ids */ +#define KERN_STACKGAPRANDOM 50 /* int: stackgap_random */ /* * KERN_PROC subtypes */ diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c index 17f8cad..459f3c1 100644 --- a/sys/vm/vm_mmap.c +++ b/sys/vm/vm_mmap.c @@ -96,6 +96,10 @@ SYSCTL_INT(_vm, OID_AUTO, old_mlock, CTLFLAG_RW | CTLFLAG_TUN, &old_mlock, 0, "Do not apply RLIMIT_MEMLOCK on mlockall"); TUNABLE_INT("vm.old_mlock", &old_mlock); +static int mmap_random = 1; +SYSCTL_INT(_security_bsd, OID_AUTO, mmap_random, CTLFLAG_RW, &mmap_random, 0, + "Randomize mmap offset"); + #ifdef MAP_32BIT #define MAP_32BIT_MAX_ADDR ((vm_offset_t)1 << 31) #endif @@ -312,6 +316,8 @@ sys_mmap(td, uap) lim_max(td->td_proc, RLIMIT_DATA)))) addr = round_page((vm_offset_t)vms->vm_daddr + lim_max(td->td_proc, RLIMIT_DATA)); + if (mmap_random) + addr += arc4random() & (256 * 1024 * 1024 - 1); PROC_UNLOCK(td->td_proc); } if (flags & MAP_ANON) { -- 1.8.3.4