Index: src/sys/kern/kern_exec.c =================================================================== --- src/sys/kern/kern_exec.c (revision 171) +++ src/sys/kern/kern_exec.c (working copy) @@ -83,6 +83,7 @@ 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); @@ -97,6 +98,9 @@ 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, &ps_arg_cache_limit, 0, ""); @@ -149,6 +153,26 @@ sizeof(p->p_sysent->sv_stackprot))); } +static int stackgap_random = 64 * 1024; + +static int +sysctl_kern_stackgap_random(SYSCTL_HANDLER_ARGS) +{ + int error, val; + + val = stackgap_random; + error = sysctl_handle_int(oidp, &val, sizeof(int), req); + if (error || !req->newptr) + return (error); + + if ((val < ALIGNBYTES && (val != 0)) || + !powerof2(val) || val > 64 * 1024 * 1024) + return (EINVAL); + + stackgap_random = val; + return (0); +} + /* * Each of the items is a pointer to a `const struct execsw', hence the * double pointer here. @@ -1044,6 +1068,7 @@ struct ps_strings *arginfo; struct proc *p; int szsigcode; + int sgap; /* * Calculate string base and vector table pointers. @@ -1054,7 +1079,10 @@ arginfo = (struct ps_strings *)p->p_sysent->sv_psstrings; if (p->p_sysent->sv_szsigcode != NULL) szsigcode = *(p->p_sysent->sv_szsigcode); - destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE - + sgap = 0; + if (stackgap_random != 0) + sgap = ALIGN(arc4random() & (stackgap_random - 1)); + destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE - sgap - roundup((ARG_MAX - imgp->args->stringspace), sizeof(char *)); /*