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