Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys Split sys_execve() and add execve1() that does most of t...
details: https://anonhg.NetBSD.org/src/rev/834d9b2a9f7c
branches: trunk
changeset: 582925:834d9b2a9f7c
user: cube <cube%NetBSD.org@localhost>
date: Mon Jul 11 20:15:26 2005 +0000
description:
Split sys_execve() and add execve1() that does most of the work, and takes
as an argument a function that will retrieve an element of the pointer
arrays in user space. This allows COMPAT_NETBSD32 to share the code for
the emulated version of execve(2), and fixes various issues that came from
the slow drift between the two implementations.
Note: when splitting up a syscall function, I'll use two different ways
of naming the resulting helper function. If it stills does
copyin/out operations, it will be named <syscall>1(). If it does
not (as it was the case for get/setitimer), it will be named
do<syscall>.
diffstat:
sys/compat/netbsd32/netbsd32_execve.c | 498 +--------------------------------
sys/kern/kern_exec.c | 44 ++-
sys/sys/exec.h | 6 +-
3 files changed, 54 insertions(+), 494 deletions(-)
diffs (truncated from 690 to 300 lines):
diff -r 0c81154f0a20 -r 834d9b2a9f7c sys/compat/netbsd32/netbsd32_execve.c
--- a/sys/compat/netbsd32/netbsd32_execve.c Mon Jul 11 19:50:42 2005 +0000
+++ b/sys/compat/netbsd32/netbsd32_execve.c Mon Jul 11 20:15:26 2005 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: netbsd32_execve.c,v 1.22 2005/05/31 00:41:09 christos Exp $ */
+/* $NetBSD: netbsd32_execve.c,v 1.23 2005/07/11 20:15:26 cube Exp $ */
/*
* Copyright (c) 1998, 2001 Matthew R. Green
@@ -29,508 +29,48 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: netbsd32_execve.c,v 1.22 2005/05/31 00:41:09 christos Exp $");
-
-#if defined(_KERNEL_OPT)
-#include "opt_ktrace.h"
-#endif
+__KERNEL_RCSID(0, "$NetBSD: netbsd32_execve.c,v 1.23 2005/07/11 20:15:26 cube Exp $");
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/malloc.h>
#include <sys/mount.h>
#include <sys/stat.h>
-#include <sys/wait.h>
-#include <sys/ktrace.h>
#include <sys/vnode.h>
#include <sys/file.h>
#include <sys/filedesc.h>
-#include <sys/namei.h>
-
-#include <uvm/uvm_extern.h>
-
#include <sys/sa.h>
#include <sys/syscallargs.h>
#include <sys/proc.h>
-#include <sys/acct.h>
#include <sys/exec.h>
#include <compat/netbsd32/netbsd32.h>
#include <compat/netbsd32/netbsd32_syscall.h>
#include <compat/netbsd32/netbsd32_syscallargs.h>
-#include <sys/verified_exec.h>
-
-/* this is provided by kern/kern_exec.c */
-extern u_int exec_maxhdrsz;
-#if defined(LKM) || defined(_LKM)
-extern struct lock exec_lock;
-#endif
+static int
+netbsd32_execve_fetch_element(char * const *array, size_t index, char **value)
+{
+ int error;
+ netbsd32_charp const *a32 = (void const *)array;
+ netbsd32_charp e;
-/*
- * Need to completly reimplement this syscall due to argument copying.
- */
-/* ARGSUSED */
+ error = copyin(a32 + index, &e, sizeof(e));
+ if (error)
+ return error;
+ *value = (char *)NETBSD32PTR64(e);
+ return 0;
+}
+
int
-netbsd32_execve(l, v, retval)
- struct lwp *l;
- void *v;
- register_t *retval;
+netbsd32_execve(struct lwp *l, void *v, register_t *retval)
{
struct netbsd32_execve_args /* {
syscallarg(const netbsd32_charp) path;
syscallarg(netbsd32_charpp) argp;
syscallarg(netbsd32_charpp) envp;
} */ *uap = v;
- struct sys_execve_args ua;
- caddr_t sg;
- struct proc *p = l->l_proc;
- NETBSD32TOP_UAP(path, const char);
- NETBSD32TOP_UAP(argp, char *);
- NETBSD32TOP_UAP(envp, char *);
- sg = stackgap_init(p, 0);
- CHECK_ALT_EXIST(p, &sg, SCARG(&ua, path));
-
- return netbsd32_execve2(l, &ua, retval);
+ return execve1(l, NETBSD32PTR64(SCARG(uap, path)),
+ NETBSD32PTR64(SCARG(uap, argp)), NETBSD32PTR64(SCARG(uap, envp)),
+ netbsd32_execve_fetch_element);
}
-
-int
-netbsd32_execve2(l, uap, retval)
- struct lwp *l;
- struct sys_execve_args *uap;
- register_t *retval;
-{
- /* Function args */
- struct proc *p = l->l_proc;
- int error, i;
- struct exec_package pack;
- struct nameidata nid;
- struct vattr attr;
- struct ucred *cred = p->p_ucred;
- char *argp;
- netbsd32_charp const *cpp;
- char *dp;
- netbsd32_charp sp;
- long argc, envc;
- size_t len;
- char *stack;
- struct ps_strings arginfo;
- struct vmspace *vm;
- char **tmpfap;
- int szsigcode;
- struct exec_vmcmd *base_vcp = NULL;
-
- /*
- * Init the namei data to point the file user's program name.
- * This is done here rather than in check_exec(), so that it's
- * possible to override this settings if any of makecmd/probe
- * functions call check_exec() recursively - for example,
- * see exec_script_makecmds().
- */
- NDINIT(&nid, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
-
- /*
- * initialize the fields of the exec package.
- */
- pack.ep_name = SCARG(uap, path);
- pack.ep_hdr = malloc(exec_maxhdrsz, M_EXEC, M_WAITOK);
- pack.ep_hdrlen = exec_maxhdrsz;
- pack.ep_hdrvalid = 0;
- pack.ep_ndp = &nid;
- pack.ep_emul_arg = NULL;
- pack.ep_vmcmds.evs_cnt = 0;
- pack.ep_vmcmds.evs_used = 0;
- pack.ep_vap = &attr;
- pack.ep_flags = 0;
-
-#if defined(LKM) || defined(_LKM)
- lockmgr(&exec_lock, LK_SHARED, NULL);
-#endif
-
- /* see if we can run it. */
-#ifdef VERIFIED_EXEC
- if ((error = check_exec(p, &pack, VERIEXEC_DIRECT)) != 0)
-#else
- if ((error = check_exec(p, &pack)) != 0)
-#endif
- goto freehdr;
-
- /* XXX -- THE FOLLOWING SECTION NEEDS MAJOR CLEANUP */
-
- /* allocate an argument buffer */
- argp = (char *) uvm_km_alloc(exec_map, NCARGS, 0,
- UVM_KMF_PAGEABLE|UVM_KMF_WAITVA);
-#ifdef DIAGNOSTIC
- if (argp == (vaddr_t) 0)
- panic("netbsd32_execve: argp == NULL");
-#endif
- dp = argp;
- argc = 0;
-
- /* copy the fake args list, if there's one, freeing it as we go */
- if (pack.ep_flags & EXEC_HASARGL) {
- tmpfap = pack.ep_fa;
- while (*tmpfap != NULL) {
- char *cp;
-
- cp = *tmpfap;
- while (*cp)
- *dp++ = *cp++;
- dp++;
-
- FREE(*tmpfap, M_EXEC);
- tmpfap++; argc++;
- }
- FREE(pack.ep_fa, M_EXEC);
- pack.ep_flags &= ~EXEC_HASARGL;
- }
-
- /* Now get argv & environment */
- if (!(cpp = (const netbsd32_charp *)SCARG(uap, argp))) {
- error = EINVAL;
- goto bad;
- }
-
- if (pack.ep_flags & EXEC_SKIPARG)
- cpp++;
-
- while (1) {
- len = argp + ARG_MAX - dp;
- if ((error = copyin(cpp, &sp, sizeof(sp))) != 0)
- goto bad;
- if (!sp)
- break;
- if ((error = copyinstr((char *)(u_long)sp, dp,
- len, &len)) != 0) {
- if (error == ENAMETOOLONG)
- error = E2BIG;
- goto bad;
- }
- dp += len;
- cpp++;
- argc++;
- }
-
- envc = 0;
- /* environment need not be there */
- if ((cpp = (const netbsd32_charp *)SCARG(uap, envp)) != NULL ) {
- while (1) {
- len = argp + ARG_MAX - dp;
- if ((error = copyin(cpp, &sp, sizeof(sp))) != 0)
- goto bad;
- if (!sp)
- break;
- if ((error = copyinstr((char *)(u_long)sp,
- dp, len, &len)) != 0) {
- if (error == ENAMETOOLONG)
- error = E2BIG;
- goto bad;
- }
- dp += len;
- cpp++;
- envc++;
- }
- }
-
- dp = (char *) ALIGN(dp);
-
- szsigcode = pack.ep_es->es_emul->e_esigcode -
- pack.ep_es->es_emul->e_sigcode;
-
- /* Now check if args & environ fit into new stack */
- if (pack.ep_flags & EXEC_32)
- len = ((argc + envc + 2 + pack.ep_es->es_arglen) *
- sizeof(int) + sizeof(int) + dp + STACKGAPLEN +
- szsigcode + sizeof(struct ps_strings)) - argp;
- else
- len = ((argc + envc + 2 + pack.ep_es->es_arglen) *
- sizeof(char *) + sizeof(int) + dp + STACKGAPLEN +
- szsigcode + sizeof(struct ps_strings)) - argp;
-
- len = ALIGN(len); /* make the stack "safely" aligned */
-
- if (len > pack.ep_ssize) { /* in effect, compare to initial limit */
- error = ENOMEM;
- goto bad;
- }
-
- /* adjust "active stack depth" for process VSZ */
- pack.ep_ssize = len; /* maybe should go elsewhere, but... */
-
- /*
- * Do whatever is necessary to prepare the address space
- * for remapping. Note that this might replace the current
- * vmspace with another!
- */
- uvmspace_exec(l, VM_MIN_ADDRESS, (vaddr_t)pack.ep_minsaddr);
-
- /* Now map address space */
- vm = p->p_vmspace;
- vm->vm_taddr = (char *) pack.ep_taddr;
- vm->vm_tsize = btoc(pack.ep_tsize);
- vm->vm_daddr = (char *) pack.ep_daddr;
- vm->vm_dsize = btoc(pack.ep_dsize);
- vm->vm_ssize = btoc(pack.ep_ssize);
- vm->vm_maxsaddr = (char *) pack.ep_maxsaddr;
- vm->vm_minsaddr = (char *) pack.ep_minsaddr;
-
- /* create the new process's VM space by running the vmcmds */
-#ifdef DIAGNOSTIC
- if (pack.ep_vmcmds.evs_used == 0)
- panic("netbsd32_execve: no vmcmds");
-#endif
- for (i = 0; i < pack.ep_vmcmds.evs_used && !error; i++) {
- struct exec_vmcmd *vcp;
-
- vcp = &pack.ep_vmcmds.evs_cmds[i];
- if (vcp->ev_flags & VMCMD_RELATIVE) {
-#ifdef DIAGNOSTIC
- if (base_vcp == NULL)
- panic("netbsd32_execve: relative vmcmd with no base");
- if (vcp->ev_flags & VMCMD_BASE)
- panic("netbsd32_execve: illegal base & relative vmcmd");
-#endif
- vcp->ev_addr += base_vcp->ev_addr;
- }
- error = (*vcp->ev_proc)(p, vcp);
-#ifdef DEBUG
- if (error) {
- int j;
-
Home |
Main Index |
Thread Index |
Old Index