summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_exec.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/kern_exec.c')
-rw-r--r--sys/kern/kern_exec.c23
1 files changed, 23 insertions, 0 deletions
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index 35aa228..900da01 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -63,6 +63,8 @@
#include <machine/reg.h>
+MALLOC_DEFINE(M_PARGS, "proc-args", "Process arguments");
+
static long *exec_copyout_strings __P((struct image_params *));
static long ps_strings = PS_STRINGS;
@@ -71,6 +73,10 @@ SYSCTL_LONG(_kern, KERN_PS_STRINGS, ps_strings, CTLFLAG_RD, &ps_strings, "");
static long usrstack = USRSTACK;
SYSCTL_LONG(_kern, KERN_USRSTACK, usrstack, CTLFLAG_RD, &usrstack, "");
+u_long ps_arg_cache_limit = PAGE_SIZE / 16;
+SYSCTL_LONG(_kern, OID_AUTO, ps_arg_cache_limit, CTLFLAG_RW,
+ &ps_arg_cache_limit, "");
+
/*
* Each of the items is a pointer to a `const struct execsw', hence the
* double pointer here.
@@ -316,6 +322,21 @@ interpret:
setregs(p, imgp->entry_addr, (u_long)(uintptr_t)stack_base,
imgp->ps_strings);
+ /* Free any previous argument cache */
+ if (p->p_args && --p->p_args->ar_ref == 0)
+ FREE(p->p_args, M_PARGS);
+ p->p_args = NULL;
+
+ /* Cache arguments if they fit inside our allowance */
+ i = imgp->endargs - imgp->stringbase;
+ if (ps_arg_cache_limit >= i + sizeof(struct pargs)) {
+ MALLOC(p->p_args, struct pargs *, sizeof(struct pargs) + i,
+ M_PARGS, M_WAITOK);
+ p->p_args->ar_ref = 1;
+ p->p_args->ar_length = i;
+ bcopy(imgp->stringbase, p->p_args->ar_args, i);
+ }
+
exec_fail_dealloc:
/*
@@ -511,6 +532,8 @@ exec_extract_strings(imgp)
}
}
+ imgp->endargs = imgp->stringp;
+
/*
* extract environment strings
*/
OpenPOWER on IntegriCloud