summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authorsobomax <sobomax@FreeBSD.org>2005-01-29 23:12:00 +0000
committersobomax <sobomax@FreeBSD.org>2005-01-29 23:12:00 +0000
commitf489acaf0f5bae70444702cdcc02ab81d3b6b51a (patch)
treec697d47092272c8c6973b42ba0a424e9763f7ce5 /sys/kern
parent1c7b5012657233c6ea65df68e8223e60b6f822a0 (diff)
downloadFreeBSD-src-f489acaf0f5bae70444702cdcc02ab81d3b6b51a.zip
FreeBSD-src-f489acaf0f5bae70444702cdcc02ab81d3b6b51a.tar.gz
o Split out kernel part of execve(2) syscall into two parts: one that
copies arguments into the kernel space and one that operates completely in the kernel space; o use kernel-only version of execve(2) to kill another stackgap in linuxlator/i386. Obtained from: DragonFlyBSD (partially) MFC after: 2 weeks
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/imgact_aout.c7
-rw-r--r--sys/kern/imgact_elf.c11
-rw-r--r--sys/kern/imgact_gzip.c6
-rw-r--r--sys/kern/imgact_shell.c138
-rw-r--r--sys/kern/kern_exec.c208
-rw-r--r--sys/kern/kern_kse.c8
6 files changed, 215 insertions, 163 deletions
diff --git a/sys/kern/imgact_aout.c b/sys/kern/imgact_aout.c
index 9263384..12086fa 100644
--- a/sys/kern/imgact_aout.c
+++ b/sys/kern/imgact_aout.c
@@ -90,7 +90,7 @@ aout_fixup(stack_base, imgp)
struct image_params *imgp;
{
- return (suword(--(*stack_base), imgp->argc));
+ return (suword(--(*stack_base), imgp->args->argc));
}
static int
@@ -187,11 +187,6 @@ exec_aout_imgact(imgp)
}
PROC_UNLOCK(imgp->proc);
- /* copy in arguments and/or environment from old process */
- error = exec_extract_strings(imgp);
- if (error)
- return (error);
-
/*
* Destroy old process VM and create a new one (with a new stack)
*/
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
index ee723e9..03e7f90 100644
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -528,8 +528,6 @@ __elfN(load_file)(struct proc *p, const char *file, u_long *addr,
* Initialize part of the common data
*/
imgp->proc = p;
- imgp->userspace_argv = NULL;
- imgp->userspace_envv = NULL;
imgp->attr = attr;
imgp->firstpage = NULL;
imgp->image_header = NULL;
@@ -647,7 +645,7 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
u_long text_addr = 0, data_addr = 0;
u_long seg_size, seg_addr;
u_long addr, entry = 0, proghdr = 0;
- int error, i;
+ int error = 0, i;
const char *interp = NULL;
Elf_Brandinfo *brand_info;
char *path;
@@ -706,9 +704,6 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
if (interp != NULL && brand_info->interp_newpath != NULL)
interp = brand_info->interp_newpath;
- if ((error = exec_extract_strings(imgp)) != 0)
- goto fail;
-
exec_new_vmspace(imgp, sv);
vmspace = imgp->proc->p_vmspace;
@@ -879,7 +874,7 @@ __elfN(freebsd_fixup)(register_t **stack_base, struct image_params *imgp)
Elf_Addr *pos;
base = (Elf_Addr *)*stack_base;
- pos = base + (imgp->argc + imgp->envc + 2);
+ pos = base + (imgp->args->argc + imgp->args->envc + 2);
if (args->trace) {
AUXARGS_ENTRY(pos, AT_DEBUG, 1);
@@ -900,7 +895,7 @@ __elfN(freebsd_fixup)(register_t **stack_base, struct image_params *imgp)
imgp->auxargs = NULL;
base--;
- suword(base, (long)imgp->argc);
+ suword(base, (long)imgp->args->argc);
*stack_base = (register_t *)base;
return (0);
}
diff --git a/sys/kern/imgact_gzip.c b/sys/kern/imgact_gzip.c
index 0885976..d44d49d 100644
--- a/sys/kern/imgact_gzip.c
+++ b/sys/kern/imgact_gzip.c
@@ -225,12 +225,6 @@ do_aout_hdr(struct imgact_gzip * gz)
/* Find out how far we should go */
gz->file_end = gz->file_offset + gz->a_out.a_text + gz->a_out.a_data;
- /* copy in arguments and/or environment from old process */
- error = exec_extract_strings(gz->ip);
- if (error) {
- gz->where = __LINE__;
- return (error);
- }
/*
* Destroy old process VM and create a new one (with a new stack)
*/
diff --git a/sys/kern/imgact_shell.c b/sys/kern/imgact_shell.c
index b34e0c1..07bcd57 100644
--- a/sys/kern/imgact_shell.c
+++ b/sys/kern/imgact_shell.c
@@ -42,15 +42,15 @@ __FBSDID("$FreeBSD$");
/*
* Shell interpreter image activator. An interpreter name beginning
- * at imgp->stringbase is the minimal successful exit requirement.
+ * at imgp->args->begin_argv is the minimal successful exit requirement.
*/
int
exec_shell_imgact(imgp)
struct image_params *imgp;
{
const char *image_header = imgp->image_header;
- const char *ihp, *line_endp;
- char *interp;
+ const char *ihp;
+ int error, length, offset;
/* a shell script? */
if (((const short *) image_header)[0] != SHELLMAGIC)
@@ -66,64 +66,110 @@ exec_shell_imgact(imgp)
imgp->interpreted = 1;
/*
- * Copy shell name and arguments from image_header into string
- * buffer.
+ * Figure out the number of bytes that need to be reserved in the
+ * argument string to copy the contents of the interpreter's command
+ * line into the argument string.
*/
+ ihp = &image_header[2];
+ offset = 0;
+ while (ihp < &image_header[MAXSHELLCMDLEN]) {
+ /* Skip any whitespace */
+ while ((*ihp == ' ') || (*ihp == '\t')) {
+ ihp++;
+ continue;
+ }
+
+ /* End of line? */
+ if ((*ihp == '\n') || (*ihp == '#'))
+ break;
+
+ /* Found a token */
+ while ((*ihp != ' ') && (*ihp != '\t') && (*ihp != '\n') &&
+ (*ihp != '#')) {
+ offset++;
+ ihp++;
+ }
+ /* Include terminating nulls in the offset */
+ offset++;
+ }
+
+ /* If the script gives a null line as the interpreter, we bail */
+ if (offset == 0)
+ return (ENOEXEC);
+
+ /* Check that we aren't too big */
+ if (offset > MAXSHELLCMDLEN)
+ return (ENAMETOOLONG);
/*
- * Find end of line; return if the line > MAXSHELLCMDLEN long.
+ * The full path name of the original script file must be tagged
+ * onto the end, adjust the offset to deal with it.
+ *
+ * The original argv[0] is being replaced, set 'length' to the number
+ * of bytes being removed. So 'offset' is the number of bytes being
+ * added and 'length' is the number of bytes being removed.
*/
- for (ihp = &image_header[2]; *ihp != '\n'; ++ihp) {
- if (ihp >= &image_header[MAXSHELLCMDLEN])
- return(ENAMETOOLONG);
- }
- line_endp = ihp;
+ offset += strlen(imgp->args->fname) + 1; /* add fname */
+ length = (imgp->args->argc == 0) ? 0 :
+ strlen(imgp->args->begin_argv) + 1; /* bytes to delete */
- /* reset for another pass */
- ihp = &image_header[2];
+ if (offset - length > imgp->args->stringspace)
+ return (E2BIG);
- /* Skip over leading spaces - until the interpreter name */
- while ((*ihp == ' ') || (*ihp == '\t')) ihp++;
+ bcopy(imgp->args->begin_argv + length, imgp->args->begin_argv + offset,
+ imgp->args->endp - (imgp->args->begin_argv + length));
- /* copy the interpreter name */
- interp = imgp->interpreter_name;
- while ((ihp < line_endp) && (*ihp != ' ') && (*ihp != '\t'))
- *interp++ = *ihp++;
- *interp = '\0';
+ offset -= length; /* calculate actual adjustment */
+ imgp->args->begin_envv += offset;
+ imgp->args->endp += offset;
+ imgp->args->stringspace -= offset;
- /* Disallow a null interpreter filename */
- if (*imgp->interpreter_name == '\0')
- return(ENOEXEC);
+ /*
+ * If there were no arguments then we've added one, otherwise
+ * decr argc remove old argv[0], incr argc for fname add, net 0
+ */
+ if (imgp->args->argc == 0)
+ imgp->args->argc = 1;
- /* reset for another pass */
+ /*
+ * Loop through the interpreter name yet again, copying as
+ * we go.
+ */
ihp = &image_header[2];
+ offset = 0;
+ while (ihp < &image_header[MAXSHELLCMDLEN]) {
+ /* Skip whitespace */
+ while ((*ihp == ' ' || *ihp == '\t')) {
+ ihp++;
+ continue;
+ }
+
+ /* End of line? */
+ if ((*ihp == '\n') || (*ihp == '#'))
+ break;
- /* copy the interpreter name and arguments */
- while (ihp < line_endp) {
- /* Skip over leading spaces */
- while ((*ihp == ' ') || (*ihp == '\t')) ihp++;
-
- if (ihp < line_endp) {
- /*
- * Copy to end of token. No need to watch stringspace
- * because this is at the front of the string buffer
- * and the maximum shell command length is tiny.
- */
- while ((ihp < line_endp) && (*ihp != ' ') && (*ihp != '\t')) {
- *imgp->stringp++ = *ihp++;
- imgp->stringspace--;
- }
-
- *imgp->stringp++ = 0;
- imgp->stringspace--;
-
- imgp->argc++;
+ /* Found a token, copy it */
+ while ((*ihp != ' ') && (*ihp != '\t') &&
+ (*ihp != '\n') && (*ihp != '#')) {
+ imgp->args->begin_argv[offset++] = *ihp++;
}
+ imgp->args->begin_argv[offset++] = '\0';
+ imgp->args->argc++;
}
- imgp->argv0 = imgp->fname;
+ /*
+ * Finally, add the filename onto the end for the interpreter to
+ * use and copy the interpreter's name to imgp->interpreter_name
+ * for exec to use.
+ */
+ error = copystr(imgp->args->fname, imgp->args->buf + offset,
+ imgp->args->stringspace, &length);
+
+ if (error == 0)
+ error = copystr(imgp->args->begin_argv, imgp->interpreter_name,
+ MAXSHELLCMDLEN, &length);
- return(0);
+ return (error);
}
/*
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index 50fea85..3998726 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -79,8 +79,8 @@ 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 do_execve(struct thread *td, char *fname, char **argv,
- char **envv, struct mac *mac_p);
+static int do_execve(struct thread *td, struct image_args *args,
+ struct mac *mac_p);
/* XXX This should be vm_size_t. */
SYSCTL_PROC(_kern, KERN_PS_STRINGS, ps_strings, CTLTYPE_ULONG|CTLFLAG_RD,
@@ -171,8 +171,18 @@ execve(td, uap)
char **envv;
} */ *uap;
{
+ int error;
+ struct image_args args;
+
+ error = exec_copyin_args(&args, uap->fname, UIO_USERSPACE,
+ uap->argv, uap->envv);
+
+ if (error == 0)
+ error = kern_execve(td, &args, NULL);
+
+ exec_free_args(&args);
- return (kern_execve(td, uap->fname, uap->argv, uap->envv, NULL));
+ return (error);
}
#ifndef _SYS_SYSPROTO_H_
@@ -197,21 +207,28 @@ __mac_execve(td, uap)
struct mac *mac_p;
} */ *uap;
{
-
#ifdef MAC
- return (kern_execve(td, uap->fname, uap->argv, uap->envv,
- uap->mac_p));
+ int error;
+ struct image_args args;
+
+ error = exec_copyin_args(&args, uap->fname, UIO_USERSPACE,
+ uap->argv, uap->envv);
+
+ if (error == 0)
+ error = kern_execve(td, &args, uap->mac_p);
+
+ exec_free_args(&args);
+
+ return (error);
#else
return (ENOSYS);
#endif
}
int
-kern_execve(td, fname, argv, envv, mac_p)
+kern_execve(td, args, mac_p)
struct thread *td;
- char *fname;
- char **argv;
- char **envv;
+ struct image_args *args;
struct mac *mac_p;
{
struct proc *p = td->td_proc;
@@ -226,7 +243,7 @@ kern_execve(td, fname, argv, envv, mac_p)
PROC_UNLOCK(p);
}
- error = do_execve(td, fname, argv, envv, mac_p);
+ error = do_execve(td, args, mac_p);
if (p->p_flag & P_HADTHREADS) {
PROC_LOCK(p);
@@ -235,7 +252,7 @@ kern_execve(td, fname, argv, envv, mac_p)
* force other threads to suicide.
*/
if (error == 0)
- thread_single(SINGLE_EXIT);
+ thread_single(SINGLE_EXIT);
else
thread_single_end();
PROC_UNLOCK(p);
@@ -251,11 +268,9 @@ kern_execve(td, fname, argv, envv, mac_p)
* MPSAFE
*/
static int
-do_execve(td, fname, argv, envv, mac_p)
+do_execve(td, args, mac_p)
struct thread *td;
- char *fname;
- char **argv;
- char **envv;
+ struct image_args *args;
struct mac *mac_p;
{
struct proc *p = td->td_proc;
@@ -300,12 +315,8 @@ do_execve(td, fname, argv, envv, mac_p)
* Initialize part of the common data
*/
imgp->proc = p;
- imgp->userspace_argv = argv;
- imgp->userspace_envv = envv;
imgp->execlabel = NULL;
imgp->attr = &attr;
- imgp->argc = imgp->envc = 0;
- imgp->argv0 = NULL;
imgp->entry_addr = 0;
imgp->vmspace_destroyed = 0;
imgp->interpreted = 0;
@@ -316,6 +327,7 @@ do_execve(td, fname, argv, envv, mac_p)
imgp->firstpage = NULL;
imgp->ps_strings = 0;
imgp->auxarg_size = 0;
+ imgp->args = args;
#ifdef MAC
error = mac_execve_enter(imgp, mac_p);
@@ -325,18 +337,6 @@ do_execve(td, fname, argv, envv, mac_p)
}
#endif
- /*
- * Allocate temporary demand zeroed space for argument and
- * environment strings
- */
- imgp->stringbase = (char *)kmem_alloc_wait(exec_map, ARG_MAX);
- if (imgp->stringbase == NULL) {
- error = ENOMEM;
- mtx_lock(&Giant);
- goto exec_fail;
- }
- imgp->stringp = imgp->stringbase;
- imgp->stringspace = ARG_MAX;
imgp->image_header = NULL;
/*
@@ -345,20 +345,16 @@ do_execve(td, fname, argv, envv, mac_p)
*/
ndp = &nd;
NDINIT(ndp, LOOKUP, LOCKLEAF | FOLLOW | SAVENAME,
- UIO_USERSPACE, fname, td);
+ UIO_SYSSPACE, args->fname, td);
mtx_lock(&Giant);
interpret:
error = namei(ndp);
- if (error) {
- kmem_free_wakeup(exec_map, (vm_offset_t)imgp->stringbase,
- ARG_MAX);
+ if (error)
goto exec_fail;
- }
imgp->vp = ndp->ni_vp;
- imgp->fname = fname;
/*
* Check file permissions (also 'opens' file)
@@ -387,7 +383,7 @@ interpret:
/*
* If the current process has a special image activator it
- * wants to try first, call it. For example, emulating shell
+ * wants to try first, call it. For example, emulating shell
* scripts differently.
*/
error = -1;
@@ -460,7 +456,7 @@ interpret:
if (p->p_sysent->sv_fixup != NULL)
(*p->p_sysent->sv_fixup)(&stack_base, imgp);
else
- suword(--stack_base, imgp->argc);
+ suword(--stack_base, imgp->args->argc);
/*
* For security and other reasons, the file descriptor table cannot
@@ -473,7 +469,7 @@ interpret:
*/
newcred = crget();
euip = uifind(attr.va_uid);
- i = imgp->endargs - imgp->stringbase;
+ i = imgp->args->begin_envv - imgp->args->begin_argv;
if (ps_arg_cache_limit >= i + sizeof(struct pargs))
newargs = pargs_alloc(i);
@@ -662,7 +658,7 @@ interpret:
/* Cache arguments if they fit inside our allowance */
if (ps_arg_cache_limit >= i + sizeof(struct pargs)) {
- bcopy(imgp->stringbase, newargs->ar_args, i);
+ bcopy(imgp->args->begin_argv, newargs->ar_args, i);
p->p_args = newargs;
newargs = NULL;
}
@@ -718,10 +714,6 @@ exec_fail_dealloc:
vput(imgp->vp);
}
- if (imgp->stringbase != NULL)
- kmem_free_wakeup(exec_map, (vm_offset_t)imgp->stringbase,
- ARG_MAX);
-
if (imgp->object != NULL)
vm_object_deallocate(imgp->object);
@@ -739,7 +731,7 @@ exec_fail:
PROC_LOCK(p);
p->p_flag &= ~P_INEXEC;
PROC_UNLOCK(p);
-
+
if (imgp->vmspace_destroyed) {
/* sorry, no more process anymore. exit gracefully */
#ifdef MAC
@@ -925,73 +917,95 @@ exec_new_vmspace(imgp, sv)
* address space into the temporary string buffer.
*/
int
-exec_extract_strings(imgp)
- struct image_params *imgp;
+exec_copyin_args(struct image_args *args, char *fname,
+ enum uio_seg segflg, char **argv, char **envv)
{
- char **argv, **envv;
- char *argp, *envp;
- int error;
- size_t length;
+ char *argp, *envp;
+ int error;
+ size_t length;
+
+ error = 0;
+ bzero(args, sizeof(*args));
+ if (argv == NULL)
+ return (EFAULT);
/*
- * extract arguments first
+ * Allocate temporary demand zeroed space for argument and
+ * environment strings
*/
+ args->buf = (char *) kmem_alloc_wait(exec_map, PATH_MAX + ARG_MAX);
+ if (args->buf == NULL)
+ return (ENOMEM);
+ args->begin_argv = args->buf;
+ args->endp = args->begin_argv;
+ args->stringspace = ARG_MAX;
+
+ args->fname = args->buf + ARG_MAX;
- argv = imgp->userspace_argv;
+ /*
+ * Copy the file name.
+ */
+ error = (segflg == UIO_SYSSPACE) ?
+ copystr(fname, args->fname, PATH_MAX, &length) :
+ copyinstr(fname, args->fname, PATH_MAX, &length);
+ if (error != 0) {
+ if (error == ENAMETOOLONG)
+ return (E2BIG);
+ return (error);
+ }
- if (argv) {
- argp = (caddr_t)(intptr_t)fuword(argv);
- if (argp == (caddr_t)-1)
+ /*
+ * extract arguments first
+ */
+ while ((argp = (caddr_t) (intptr_t) fuword(argv++))) {
+ if (argp == (caddr_t) -1)
return (EFAULT);
- if (argp)
- argv++;
- if (imgp->argv0)
- argp = imgp->argv0;
- if (argp) {
- do {
- if (argp == (caddr_t)-1)
- return (EFAULT);
- if ((error = copyinstr(argp, imgp->stringp,
- imgp->stringspace, &length))) {
- if (error == ENAMETOOLONG)
- return (E2BIG);
- return (error);
- }
- imgp->stringspace -= length;
- imgp->stringp += length;
- imgp->argc++;
- } while ((argp = (caddr_t)(intptr_t)fuword(argv++)));
+ if ((error = copyinstr(argp, args->endp,
+ args->stringspace, &length))) {
+ if (error == ENAMETOOLONG)
+ return (E2BIG);
+ return (error);
}
- } else
- return (EFAULT);
+ args->stringspace -= length;
+ args->endp += length;
+ args->argc++;
+ }
- imgp->endargs = imgp->stringp;
+ args->begin_envv = args->endp;
/*
* extract environment strings
*/
-
- envv = imgp->userspace_envv;
-
if (envv) {
while ((envp = (caddr_t)(intptr_t)fuword(envv++))) {
if (envp == (caddr_t)-1)
return (EFAULT);
- if ((error = copyinstr(envp, imgp->stringp,
- imgp->stringspace, &length))) {
+ if ((error = copyinstr(envp, args->endp,
+ args->stringspace, &length))) {
if (error == ENAMETOOLONG)
return (E2BIG);
return (error);
}
- imgp->stringspace -= length;
- imgp->stringp += length;
- imgp->envc++;
+ args->stringspace -= length;
+ args->endp += length;
+ args->envc++;
}
}
return (0);
}
+void
+exec_free_args(struct image_args *args)
+{
+
+ if (args->buf) {
+ kmem_free_wakeup(exec_map,
+ (vm_offset_t)args->buf, PATH_MAX + ARG_MAX);
+ args->buf = NULL;
+ }
+}
+
/*
* Copy strings out to the new process address space, constructing
* new arg and env vector tables. Return a pointer to the base
@@ -1019,7 +1033,7 @@ exec_copyout_strings(imgp)
if (p->p_sysent->sv_szsigcode != NULL)
szsigcode = *(p->p_sysent->sv_szsigcode);
destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE -
- roundup((ARG_MAX - imgp->stringspace), sizeof(char *));
+ roundup((ARG_MAX - imgp->args->stringspace), sizeof(char *));
/*
* install sigcode
@@ -1044,30 +1058,32 @@ exec_copyout_strings(imgp)
* the arg and env vector sets,and imgp->auxarg_size is room
* for argument of Runtime loader.
*/
- vectp = (char **)(destp - (imgp->argc + imgp->envc + 2 +
- imgp->auxarg_size) * sizeof(char *));
+ vectp = (char **)(destp - (imgp->args->argc +
+ imgp->args->envc + 2 + imgp->auxarg_size) *
+ sizeof(char *));
- } else
+ } else {
/*
* The '+ 2' is for the null pointers at the end of each of
* the arg and env vector sets
*/
- vectp = (char **)(destp - (imgp->argc + imgp->envc + 2) *
+ vectp = (char **)(destp - (imgp->args->argc + imgp->args->envc + 2) *
sizeof(char *));
+ }
/*
* vectp also becomes our initial stack base
*/
stack_base = (register_t *)vectp;
- stringp = imgp->stringbase;
- argc = imgp->argc;
- envc = imgp->envc;
+ stringp = imgp->args->begin_argv;
+ argc = imgp->args->argc;
+ envc = imgp->args->envc;
/*
* Copy out strings - arguments and environment.
*/
- copyout(stringp, destp, ARG_MAX - imgp->stringspace);
+ copyout(stringp, destp, ARG_MAX - imgp->args->stringspace);
/*
* Fill in "ps_strings" struct for ps, w, etc.
diff --git a/sys/kern/kern_kse.c b/sys/kern/kern_kse.c
index d0e03ec..4e648f5 100644
--- a/sys/kern/kern_kse.c
+++ b/sys/kern/kern_kse.c
@@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/imgact.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/proc.h>
@@ -176,6 +177,7 @@ int
kse_thr_interrupt(struct thread *td, struct kse_thr_interrupt_args *uap)
{
struct kse_execve_args args;
+ struct image_args iargs;
struct proc *p;
struct thread *td2;
struct kse_upcall *ku;
@@ -261,7 +263,11 @@ kse_thr_interrupt(struct thread *td, struct kse_thr_interrupt_args *uap)
error = copyin((void *)uap->data, &args, sizeof(args));
if (error)
return (error);
- error = kern_execve(td, args.path, args.argv, args.envp, NULL);
+ error = exec_copyin_args(&iargs, args.path, UIO_USERSPACE,
+ args.argv, args.envp);
+ if (error == 0)
+ error = kern_execve(td, &iargs, NULL);
+ exec_free_args(&iargs);
if (error == 0) {
PROC_LOCK(p);
SIGSETOR(td->td_siglist, args.sigpend);
OpenPOWER on IntegriCloud