Home | History | Annotate | Line # | Download | only in kern
kern_exec.c revision 1.170
      1  1.170       dsl /*	$NetBSD: kern_exec.c,v 1.170 2003/07/16 22:42:48 dsl Exp $	*/
      2   1.55       cgd 
      3   1.55       cgd /*-
      4   1.77       cgd  * Copyright (C) 1993, 1994, 1996 Christopher G. Demetriou
      5   1.55       cgd  * Copyright (C) 1992 Wolfgang Solfrank.
      6   1.55       cgd  * Copyright (C) 1992 TooLs GmbH.
      7   1.55       cgd  * All rights reserved.
      8   1.55       cgd  *
      9   1.55       cgd  * Redistribution and use in source and binary forms, with or without
     10   1.55       cgd  * modification, are permitted provided that the following conditions
     11   1.55       cgd  * are met:
     12   1.55       cgd  * 1. Redistributions of source code must retain the above copyright
     13   1.55       cgd  *    notice, this list of conditions and the following disclaimer.
     14   1.55       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     15   1.55       cgd  *    notice, this list of conditions and the following disclaimer in the
     16   1.55       cgd  *    documentation and/or other materials provided with the distribution.
     17   1.55       cgd  * 3. All advertising materials mentioning features or use of this software
     18   1.55       cgd  *    must display the following acknowledgement:
     19   1.55       cgd  *	This product includes software developed by TooLs GmbH.
     20   1.55       cgd  * 4. The name of TooLs GmbH may not be used to endorse or promote products
     21   1.55       cgd  *    derived from this software without specific prior written permission.
     22   1.55       cgd  *
     23   1.55       cgd  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
     24   1.55       cgd  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     25   1.55       cgd  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     26   1.55       cgd  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     27   1.55       cgd  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     28   1.55       cgd  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     29   1.55       cgd  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     30   1.55       cgd  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     31   1.55       cgd  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     32   1.55       cgd  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     33   1.55       cgd  */
     34  1.146     lukem 
     35  1.146     lukem #include <sys/cdefs.h>
     36  1.170       dsl __KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.170 2003/07/16 22:42:48 dsl Exp $");
     37   1.89       mrg 
     38   1.92   thorpej #include "opt_ktrace.h"
     39  1.124  jdolecek #include "opt_syscall_debug.h"
     40   1.55       cgd 
     41   1.55       cgd #include <sys/param.h>
     42   1.55       cgd #include <sys/systm.h>
     43   1.55       cgd #include <sys/filedesc.h>
     44   1.55       cgd #include <sys/kernel.h>
     45   1.55       cgd #include <sys/proc.h>
     46   1.55       cgd #include <sys/mount.h>
     47   1.55       cgd #include <sys/malloc.h>
     48   1.55       cgd #include <sys/namei.h>
     49   1.55       cgd #include <sys/vnode.h>
     50   1.55       cgd #include <sys/file.h>
     51   1.55       cgd #include <sys/acct.h>
     52   1.55       cgd #include <sys/exec.h>
     53   1.55       cgd #include <sys/ktrace.h>
     54   1.55       cgd #include <sys/resourcevar.h>
     55   1.55       cgd #include <sys/wait.h>
     56   1.55       cgd #include <sys/mman.h>
     57  1.155  gmcgarry #include <sys/ras.h>
     58   1.55       cgd #include <sys/signalvar.h>
     59   1.55       cgd #include <sys/stat.h>
     60  1.124  jdolecek #include <sys/syscall.h>
     61   1.55       cgd 
     62  1.164   thorpej #include <sys/sa.h>
     63  1.164   thorpej #include <sys/savar.h>
     64   1.56       cgd #include <sys/syscallargs.h>
     65   1.55       cgd 
     66   1.88       mrg #include <uvm/uvm_extern.h>
     67   1.88       mrg 
     68   1.55       cgd #include <machine/cpu.h>
     69   1.55       cgd #include <machine/reg.h>
     70   1.55       cgd 
     71  1.143  christos #ifdef DEBUG_EXEC
     72  1.143  christos #define DPRINTF(a) uprintf a
     73  1.143  christos #else
     74  1.143  christos #define DPRINTF(a)
     75  1.143  christos #endif /* DEBUG_EXEC */
     76  1.165   thorpej 
     77  1.165   thorpej MALLOC_DEFINE(M_EXEC, "exec", "argument lists & other mem used by exec");
     78  1.143  christos 
     79  1.130  jdolecek /*
     80  1.130  jdolecek  * Exec function switch:
     81  1.130  jdolecek  *
     82  1.130  jdolecek  * Note that each makecmds function is responsible for loading the
     83  1.130  jdolecek  * exec package with the necessary functions for any exec-type-specific
     84  1.130  jdolecek  * handling.
     85  1.130  jdolecek  *
     86  1.130  jdolecek  * Functions for specific exec types should be defined in their own
     87  1.130  jdolecek  * header file.
     88  1.130  jdolecek  */
     89  1.138     lukem extern const struct execsw	execsw_builtin[];
     90  1.138     lukem extern int			nexecs_builtin;
     91  1.138     lukem static const struct execsw	**execsw = NULL;
     92  1.138     lukem static int			nexecs;
     93  1.138     lukem 
     94  1.153   thorpej u_int	exec_maxhdrsz;		/* must not be static - netbsd32 needs it */
     95  1.130  jdolecek 
     96  1.130  jdolecek #ifdef LKM
     97  1.130  jdolecek /* list of supported emulations */
     98  1.130  jdolecek static
     99  1.130  jdolecek LIST_HEAD(emlist_head, emul_entry) el_head = LIST_HEAD_INITIALIZER(el_head);
    100  1.130  jdolecek struct emul_entry {
    101  1.138     lukem 	LIST_ENTRY(emul_entry)	el_list;
    102  1.138     lukem 	const struct emul	*el_emul;
    103  1.138     lukem 	int			ro_entry;
    104  1.130  jdolecek };
    105  1.130  jdolecek 
    106  1.130  jdolecek /* list of dynamically loaded execsw entries */
    107  1.130  jdolecek static
    108  1.130  jdolecek LIST_HEAD(execlist_head, exec_entry) ex_head = LIST_HEAD_INITIALIZER(ex_head);
    109  1.130  jdolecek struct exec_entry {
    110  1.138     lukem 	LIST_ENTRY(exec_entry)	ex_list;
    111  1.138     lukem 	const struct execsw	*es;
    112  1.130  jdolecek };
    113  1.130  jdolecek 
    114  1.130  jdolecek /* structure used for building execw[] */
    115  1.130  jdolecek struct execsw_entry {
    116  1.138     lukem 	struct execsw_entry	*next;
    117  1.138     lukem 	const struct execsw	*es;
    118  1.130  jdolecek };
    119  1.130  jdolecek #endif /* LKM */
    120  1.130  jdolecek 
    121  1.130  jdolecek /* NetBSD emul struct */
    122  1.138     lukem extern char	sigcode[], esigcode[];
    123  1.124  jdolecek #ifdef SYSCALL_DEBUG
    124  1.124  jdolecek extern const char * const syscallnames[];
    125  1.124  jdolecek #endif
    126  1.133   mycroft #ifdef __HAVE_SYSCALL_INTERN
    127  1.138     lukem void syscall_intern(struct proc *);
    128  1.133   mycroft #else
    129  1.138     lukem void syscall(void);
    130  1.133   mycroft #endif
    131  1.124  jdolecek 
    132  1.124  jdolecek const struct emul emul_netbsd = {
    133  1.124  jdolecek 	"netbsd",
    134  1.127  jdolecek 	NULL,		/* emulation path */
    135  1.133   mycroft #ifndef __HAVE_MINIMAL_EMUL
    136  1.140      manu 	EMUL_HAS_SYS___syscall,
    137  1.124  jdolecek 	NULL,
    138  1.124  jdolecek 	SYS_syscall,
    139  1.161  jdolecek 	SYS_NSYSENT,
    140  1.133   mycroft #endif
    141  1.124  jdolecek 	sysent,
    142  1.124  jdolecek #ifdef SYSCALL_DEBUG
    143  1.124  jdolecek 	syscallnames,
    144  1.124  jdolecek #else
    145  1.124  jdolecek 	NULL,
    146  1.124  jdolecek #endif
    147  1.133   mycroft 	sendsig,
    148  1.142  christos 	trapsignal,
    149  1.124  jdolecek 	sigcode,
    150  1.124  jdolecek 	esigcode,
    151  1.145  jdolecek 	setregs,
    152  1.128  jdolecek 	NULL,
    153  1.128  jdolecek 	NULL,
    154  1.128  jdolecek 	NULL,
    155  1.133   mycroft #ifdef __HAVE_SYSCALL_INTERN
    156  1.133   mycroft 	syscall_intern,
    157  1.133   mycroft #else
    158  1.133   mycroft 	syscall,
    159  1.133   mycroft #endif
    160  1.156      manu 	NULL,
    161  1.156      manu 	NULL,
    162  1.124  jdolecek };
    163  1.124  jdolecek 
    164  1.147  jdolecek #ifdef LKM
    165   1.55       cgd /*
    166  1.130  jdolecek  * Exec lock. Used to control access to execsw[] structures.
    167  1.130  jdolecek  * This must not be static so that netbsd32 can access it, too.
    168  1.130  jdolecek  */
    169  1.130  jdolecek struct lock exec_lock;
    170  1.130  jdolecek 
    171  1.138     lukem static void link_es(struct execsw_entry **, const struct execsw *);
    172  1.130  jdolecek #endif /* LKM */
    173  1.130  jdolecek 
    174  1.130  jdolecek /*
    175   1.55       cgd  * check exec:
    176   1.55       cgd  * given an "executable" described in the exec package's namei info,
    177   1.55       cgd  * see what we can do with it.
    178   1.55       cgd  *
    179   1.55       cgd  * ON ENTRY:
    180   1.55       cgd  *	exec package with appropriate namei info
    181   1.55       cgd  *	proc pointer of exec'ing proc
    182  1.160     blymn  *      iff verified exec enabled then flag indicating a direct exec or
    183  1.160     blymn  *        an indirect exec (i.e. for a shell script interpreter)
    184   1.55       cgd  *	NO SELF-LOCKED VNODES
    185   1.55       cgd  *
    186   1.55       cgd  * ON EXIT:
    187   1.55       cgd  *	error:	nothing held, etc.  exec header still allocated.
    188   1.77       cgd  *	ok:	filled exec package, executable's vnode (unlocked).
    189   1.55       cgd  *
    190   1.55       cgd  * EXEC SWITCH ENTRY:
    191   1.55       cgd  * 	Locked vnode to check, exec package, proc.
    192   1.55       cgd  *
    193   1.55       cgd  * EXEC SWITCH EXIT:
    194   1.77       cgd  *	ok:	return 0, filled exec package, executable's vnode (unlocked).
    195   1.55       cgd  *	error:	destructive:
    196   1.55       cgd  *			everything deallocated execept exec header.
    197   1.76       cgd  *		non-destructive:
    198   1.77       cgd  *			error code, executable's vnode (unlocked),
    199   1.76       cgd  *			exec header unmodified.
    200   1.55       cgd  */
    201   1.55       cgd int
    202  1.160     blymn #ifdef VERIFIED_EXEC
    203  1.169      fvdl check_exec(struct proc *p, struct exec_package *epp, int direct_exec)
    204  1.160     blymn #else
    205  1.169      fvdl check_exec(struct proc *p, struct exec_package *epp)
    206  1.160     blymn #endif
    207   1.55       cgd {
    208  1.138     lukem 	int		error, i;
    209  1.138     lukem 	struct vnode	*vp;
    210   1.55       cgd 	struct nameidata *ndp;
    211  1.138     lukem 	size_t		resid;
    212   1.55       cgd 
    213   1.55       cgd 	ndp = epp->ep_ndp;
    214   1.55       cgd 	ndp->ni_cnd.cn_nameiop = LOOKUP;
    215   1.55       cgd 	ndp->ni_cnd.cn_flags = FOLLOW | LOCKLEAF | SAVENAME;
    216   1.55       cgd 	/* first get the vnode */
    217   1.74  christos 	if ((error = namei(ndp)) != 0)
    218   1.55       cgd 		return error;
    219   1.55       cgd 	epp->ep_vp = vp = ndp->ni_vp;
    220   1.55       cgd 
    221   1.84   mycroft 	/* check access and type */
    222   1.55       cgd 	if (vp->v_type != VREG) {
    223   1.81    kleink 		error = EACCES;
    224   1.55       cgd 		goto bad1;
    225   1.55       cgd 	}
    226  1.169      fvdl 	if ((error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p)) != 0)
    227   1.84   mycroft 		goto bad1;
    228   1.55       cgd 
    229   1.55       cgd 	/* get attributes */
    230  1.169      fvdl 	if ((error = VOP_GETATTR(vp, epp->ep_vap, p->p_ucred, p)) != 0)
    231   1.55       cgd 		goto bad1;
    232   1.55       cgd 
    233   1.55       cgd 	/* Check mount point */
    234   1.55       cgd 	if (vp->v_mount->mnt_flag & MNT_NOEXEC) {
    235   1.55       cgd 		error = EACCES;
    236   1.55       cgd 		goto bad1;
    237   1.55       cgd 	}
    238  1.141   thorpej 	if (vp->v_mount->mnt_flag & MNT_NOSUID)
    239   1.83   mycroft 		epp->ep_vap->va_mode &= ~(S_ISUID | S_ISGID);
    240   1.55       cgd 
    241   1.55       cgd 	/* try to open it */
    242  1.169      fvdl 	if ((error = VOP_OPEN(vp, FREAD, p->p_ucred, p)) != 0)
    243   1.55       cgd 		goto bad1;
    244   1.55       cgd 
    245   1.99  wrstuden 	/* unlock vp, since we need it unlocked from here on out. */
    246   1.90      fvdl 	VOP_UNLOCK(vp, 0);
    247   1.77       cgd 
    248  1.160     blymn 
    249  1.160     blymn #ifdef VERIFIED_EXEC
    250  1.160     blymn         /* Evaluate signature for file... */
    251  1.160     blymn         if ((error = check_veriexec(p, vp, epp, direct_exec)) != 0)
    252  1.160     blymn                 goto bad2;
    253  1.160     blymn #endif
    254  1.160     blymn 
    255   1.55       cgd 	/* now we have the file, get the exec header */
    256  1.125       chs 	uvn_attach(vp, VM_PROT_READ);
    257   1.74  christos 	error = vn_rdwr(UIO_READ, vp, epp->ep_hdr, epp->ep_hdrlen, 0,
    258  1.169      fvdl 			UIO_SYSSPACE, 0, p->p_ucred, &resid, p);
    259   1.74  christos 	if (error)
    260   1.55       cgd 		goto bad2;
    261   1.55       cgd 	epp->ep_hdrvalid = epp->ep_hdrlen - resid;
    262   1.55       cgd 
    263   1.55       cgd 	/*
    264  1.136       eeh 	 * Set up default address space limits.  Can be overridden
    265  1.136       eeh 	 * by individual exec packages.
    266  1.136       eeh 	 *
    267  1.167      manu 	 * XXX probably should be all done in the exec pakages.
    268  1.136       eeh 	 */
    269  1.136       eeh 	epp->ep_vm_minaddr = VM_MIN_ADDRESS;
    270  1.136       eeh 	epp->ep_vm_maxaddr = VM_MAXUSER_ADDRESS;
    271  1.136       eeh 	/*
    272   1.55       cgd 	 * set up the vmcmds for creation of the process
    273   1.55       cgd 	 * address space
    274   1.55       cgd 	 */
    275   1.55       cgd 	error = ENOEXEC;
    276   1.55       cgd 	for (i = 0; i < nexecs && error != 0; i++) {
    277   1.68       cgd 		int newerror;
    278   1.68       cgd 
    279  1.130  jdolecek 		epp->ep_esch = execsw[i];
    280  1.169      fvdl 		newerror = (*execsw[i]->es_check)(p, epp);
    281   1.68       cgd 		/* make sure the first "interesting" error code is saved. */
    282   1.68       cgd 		if (!newerror || error == ENOEXEC)
    283   1.68       cgd 			error = newerror;
    284  1.124  jdolecek 
    285  1.124  jdolecek 		/* if es_check call was successful, update epp->ep_es */
    286  1.124  jdolecek 		if (!newerror && (epp->ep_flags & EXEC_HASES) == 0)
    287  1.130  jdolecek 			epp->ep_es = execsw[i];
    288  1.124  jdolecek 
    289   1.55       cgd 		if (epp->ep_flags & EXEC_DESTR && error != 0)
    290   1.55       cgd 			return error;
    291   1.55       cgd 	}
    292   1.55       cgd 	if (!error) {
    293   1.55       cgd 		/* check that entry point is sane */
    294   1.55       cgd 		if (epp->ep_entry > VM_MAXUSER_ADDRESS)
    295   1.55       cgd 			error = ENOEXEC;
    296   1.55       cgd 
    297   1.55       cgd 		/* check limits */
    298   1.55       cgd 		if ((epp->ep_tsize > MAXTSIZ) ||
    299  1.153   thorpej 		    (epp->ep_dsize >
    300  1.153   thorpej 		     (u_quad_t)p->p_rlimit[RLIMIT_DATA].rlim_cur))
    301   1.55       cgd 			error = ENOMEM;
    302   1.55       cgd 
    303   1.55       cgd 		if (!error)
    304   1.55       cgd 			return (0);
    305   1.55       cgd 	}
    306   1.55       cgd 
    307   1.55       cgd 	/*
    308   1.55       cgd 	 * free any vmspace-creation commands,
    309   1.55       cgd 	 * and release their references
    310   1.55       cgd 	 */
    311   1.55       cgd 	kill_vmcmds(&epp->ep_vmcmds);
    312   1.55       cgd 
    313   1.55       cgd bad2:
    314   1.55       cgd 	/*
    315   1.99  wrstuden 	 * close and release the vnode, restore the old one, free the
    316   1.55       cgd 	 * pathname buf, and punt.
    317   1.55       cgd 	 */
    318   1.99  wrstuden 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
    319  1.169      fvdl 	VOP_CLOSE(vp, FREAD, p->p_ucred, p);
    320   1.99  wrstuden 	vput(vp);
    321  1.120   thorpej 	PNBUF_PUT(ndp->ni_cnd.cn_pnbuf);
    322   1.55       cgd 	return error;
    323   1.55       cgd 
    324   1.55       cgd bad1:
    325   1.55       cgd 	/*
    326   1.55       cgd 	 * free the namei pathname buffer, and put the vnode
    327   1.55       cgd 	 * (which we don't yet have open).
    328   1.55       cgd 	 */
    329   1.77       cgd 	vput(vp);				/* was still locked */
    330  1.120   thorpej 	PNBUF_PUT(ndp->ni_cnd.cn_pnbuf);
    331   1.55       cgd 	return error;
    332   1.55       cgd }
    333   1.55       cgd 
    334   1.55       cgd /*
    335   1.55       cgd  * exec system call
    336   1.55       cgd  */
    337   1.55       cgd /* ARGSUSED */
    338   1.75  christos int
    339  1.164   thorpej sys_execve(struct lwp *l, void *v, register_t *retval)
    340   1.71   thorpej {
    341  1.108  augustss 	struct sys_execve_args /* {
    342  1.138     lukem 		syscallarg(const char *)	path;
    343  1.138     lukem 		syscallarg(char * const *)	argp;
    344  1.138     lukem 		syscallarg(char * const *)	envp;
    345   1.71   thorpej 	} */ *uap = v;
    346  1.153   thorpej 	int			error;
    347  1.153   thorpej 	u_int			i;
    348  1.138     lukem 	struct exec_package	pack;
    349  1.138     lukem 	struct nameidata	nid;
    350  1.138     lukem 	struct vattr		attr;
    351  1.164   thorpej 	struct proc		*p;
    352  1.138     lukem 	struct ucred		*cred;
    353  1.138     lukem 	char			*argp;
    354  1.138     lukem 	char * const		*cpp;
    355  1.138     lukem 	char			*dp, *sp;
    356  1.138     lukem 	long			argc, envc;
    357  1.138     lukem 	size_t			len;
    358  1.138     lukem 	char			*stack;
    359  1.138     lukem 	struct ps_strings	arginfo;
    360  1.138     lukem 	struct vmspace		*vm;
    361  1.138     lukem 	char			**tmpfap;
    362  1.138     lukem 	int			szsigcode;
    363  1.138     lukem 	struct exec_vmcmd	*base_vcp;
    364  1.164   thorpej 	int			oldlwpflags;
    365   1.55       cgd 
    366  1.164   thorpej 	/* Disable scheduler activation upcalls. */
    367  1.164   thorpej 	oldlwpflags = l->l_flag & (L_SA | L_SA_UPCALL);
    368  1.164   thorpej 	if (l->l_flag & L_SA)
    369  1.164   thorpej 		l->l_flag &= ~(L_SA | L_SA_UPCALL);
    370  1.164   thorpej 
    371  1.164   thorpej 	p = l->l_proc;
    372  1.149  christos 	/*
    373  1.149  christos 	 * Lock the process and set the P_INEXEC flag to indicate that
    374  1.149  christos 	 * it should be left alone until we're done here.  This is
    375  1.149  christos 	 * necessary to avoid race conditions - e.g. in ptrace() -
    376  1.149  christos 	 * that might allow a local user to illicitly obtain elevated
    377  1.149  christos 	 * privileges.
    378  1.149  christos 	 */
    379  1.149  christos 	p->p_flag |= P_INEXEC;
    380  1.149  christos 
    381  1.138     lukem 	cred = p->p_ucred;
    382  1.138     lukem 	base_vcp = NULL;
    383   1.55       cgd 	/*
    384  1.129  jdolecek 	 * Init the namei data to point the file user's program name.
    385  1.129  jdolecek 	 * This is done here rather than in check_exec(), so that it's
    386  1.129  jdolecek 	 * possible to override this settings if any of makecmd/probe
    387  1.129  jdolecek 	 * functions call check_exec() recursively - for example,
    388  1.129  jdolecek 	 * see exec_script_makecmds().
    389  1.129  jdolecek 	 */
    390  1.169      fvdl 	NDINIT(&nid, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
    391   1.55       cgd 
    392   1.55       cgd 	/*
    393   1.55       cgd 	 * initialize the fields of the exec package.
    394   1.55       cgd 	 */
    395   1.56       cgd 	pack.ep_name = SCARG(uap, path);
    396  1.119   thorpej 	pack.ep_hdr = malloc(exec_maxhdrsz, M_EXEC, M_WAITOK);
    397   1.55       cgd 	pack.ep_hdrlen = exec_maxhdrsz;
    398   1.55       cgd 	pack.ep_hdrvalid = 0;
    399   1.55       cgd 	pack.ep_ndp = &nid;
    400   1.67  christos 	pack.ep_emul_arg = NULL;
    401   1.55       cgd 	pack.ep_vmcmds.evs_cnt = 0;
    402   1.55       cgd 	pack.ep_vmcmds.evs_used = 0;
    403   1.55       cgd 	pack.ep_vap = &attr;
    404   1.55       cgd 	pack.ep_flags = 0;
    405   1.55       cgd 
    406  1.147  jdolecek #ifdef LKM
    407  1.130  jdolecek 	lockmgr(&exec_lock, LK_SHARED, NULL);
    408  1.147  jdolecek #endif
    409  1.130  jdolecek 
    410   1.55       cgd 	/* see if we can run it. */
    411  1.160     blymn #ifdef VERIFIED_EXEC
    412  1.169      fvdl         if ((error = check_exec(p, &pack, 1)) != 0)
    413  1.169      fvdl         /* if ((error = check_exec(p, &pack, 0)) != 0) */
    414  1.160     blymn #else
    415  1.169      fvdl         if ((error = check_exec(p, &pack)) != 0)
    416  1.160     blymn #endif
    417   1.55       cgd 		goto freehdr;
    418   1.55       cgd 
    419   1.55       cgd 	/* XXX -- THE FOLLOWING SECTION NEEDS MAJOR CLEANUP */
    420   1.55       cgd 
    421   1.55       cgd 	/* allocate an argument buffer */
    422   1.88       mrg 	argp = (char *) uvm_km_valloc_wait(exec_map, NCARGS);
    423   1.55       cgd #ifdef DIAGNOSTIC
    424   1.95       eeh 	if (argp == (vaddr_t) 0)
    425   1.55       cgd 		panic("execve: argp == NULL");
    426   1.55       cgd #endif
    427   1.55       cgd 	dp = argp;
    428   1.55       cgd 	argc = 0;
    429   1.55       cgd 
    430   1.55       cgd 	/* copy the fake args list, if there's one, freeing it as we go */
    431   1.55       cgd 	if (pack.ep_flags & EXEC_HASARGL) {
    432   1.55       cgd 		tmpfap = pack.ep_fa;
    433   1.55       cgd 		while (*tmpfap != NULL) {
    434   1.55       cgd 			char *cp;
    435   1.55       cgd 
    436   1.55       cgd 			cp = *tmpfap;
    437   1.55       cgd 			while (*cp)
    438   1.55       cgd 				*dp++ = *cp++;
    439   1.74  christos 			dp++;
    440   1.55       cgd 
    441   1.55       cgd 			FREE(*tmpfap, M_EXEC);
    442   1.55       cgd 			tmpfap++; argc++;
    443   1.55       cgd 		}
    444   1.55       cgd 		FREE(pack.ep_fa, M_EXEC);
    445   1.55       cgd 		pack.ep_flags &= ~EXEC_HASARGL;
    446   1.55       cgd 	}
    447   1.55       cgd 
    448   1.55       cgd 	/* Now get argv & environment */
    449   1.56       cgd 	if (!(cpp = SCARG(uap, argp))) {
    450   1.55       cgd 		error = EINVAL;
    451   1.55       cgd 		goto bad;
    452   1.55       cgd 	}
    453   1.55       cgd 
    454   1.55       cgd 	if (pack.ep_flags & EXEC_SKIPARG)
    455   1.55       cgd 		cpp++;
    456   1.55       cgd 
    457   1.55       cgd 	while (1) {
    458   1.55       cgd 		len = argp + ARG_MAX - dp;
    459   1.74  christos 		if ((error = copyin(cpp, &sp, sizeof(sp))) != 0)
    460   1.55       cgd 			goto bad;
    461   1.55       cgd 		if (!sp)
    462   1.55       cgd 			break;
    463   1.74  christos 		if ((error = copyinstr(sp, dp, len, &len)) != 0) {
    464   1.55       cgd 			if (error == ENAMETOOLONG)
    465   1.55       cgd 				error = E2BIG;
    466   1.55       cgd 			goto bad;
    467   1.55       cgd 		}
    468  1.170       dsl #ifdef KTRACE
    469  1.170       dsl 		if (KTRPOINT(p, KTR_EXEC_ARG))
    470  1.170       dsl 			ktrkmem(p, KTR_EXEC_ARG, dp, len - 1);
    471  1.170       dsl #endif
    472   1.55       cgd 		dp += len;
    473   1.55       cgd 		cpp++;
    474   1.55       cgd 		argc++;
    475   1.55       cgd 	}
    476   1.55       cgd 
    477   1.55       cgd 	envc = 0;
    478   1.74  christos 	/* environment need not be there */
    479   1.74  christos 	if ((cpp = SCARG(uap, envp)) != NULL ) {
    480   1.55       cgd 		while (1) {
    481   1.55       cgd 			len = argp + ARG_MAX - dp;
    482   1.74  christos 			if ((error = copyin(cpp, &sp, sizeof(sp))) != 0)
    483   1.55       cgd 				goto bad;
    484   1.55       cgd 			if (!sp)
    485   1.55       cgd 				break;
    486   1.74  christos 			if ((error = copyinstr(sp, dp, len, &len)) != 0) {
    487   1.55       cgd 				if (error == ENAMETOOLONG)
    488   1.55       cgd 					error = E2BIG;
    489   1.55       cgd 				goto bad;
    490   1.55       cgd 			}
    491  1.170       dsl #ifdef KTRACE
    492  1.170       dsl 			if (KTRPOINT(p, KTR_EXEC_ENV))
    493  1.170       dsl 				ktrkmem(p, KTR_EXEC_ENV, dp, len - 1);
    494  1.170       dsl #endif
    495   1.55       cgd 			dp += len;
    496   1.55       cgd 			cpp++;
    497   1.55       cgd 			envc++;
    498   1.55       cgd 		}
    499   1.55       cgd 	}
    500   1.61   mycroft 
    501   1.61   mycroft 	dp = (char *) ALIGN(dp);
    502   1.55       cgd 
    503  1.126       mrg 	szsigcode = pack.ep_es->es_emul->e_esigcode -
    504  1.126       mrg 	    pack.ep_es->es_emul->e_sigcode;
    505   1.65      fvdl 
    506   1.55       cgd 	/* Now check if args & environ fit into new stack */
    507  1.105       eeh 	if (pack.ep_flags & EXEC_32)
    508  1.126       mrg 		len = ((argc + envc + 2 + pack.ep_es->es_arglen) *
    509  1.126       mrg 		    sizeof(int) + sizeof(int) + dp + STACKGAPLEN +
    510  1.126       mrg 		    szsigcode + sizeof(struct ps_strings)) - argp;
    511  1.105       eeh 	else
    512  1.126       mrg 		len = ((argc + envc + 2 + pack.ep_es->es_arglen) *
    513  1.126       mrg 		    sizeof(char *) + sizeof(int) + dp + STACKGAPLEN +
    514  1.126       mrg 		    szsigcode + sizeof(struct ps_strings)) - argp;
    515   1.67  christos 
    516   1.55       cgd 	len = ALIGN(len);	/* make the stack "safely" aligned */
    517   1.55       cgd 
    518   1.55       cgd 	if (len > pack.ep_ssize) { /* in effect, compare to initial limit */
    519   1.55       cgd 		error = ENOMEM;
    520   1.55       cgd 		goto bad;
    521   1.55       cgd 	}
    522   1.55       cgd 
    523  1.164   thorpej 	/* Get rid of other LWPs/ */
    524  1.164   thorpej 	p->p_flag |= P_WEXIT; /* XXX hack. lwp-exit stuff wants to see it. */
    525  1.164   thorpej 	exit_lwps(l);
    526  1.164   thorpej 	p->p_flag &= ~P_WEXIT;
    527  1.164   thorpej 	KDASSERT(p->p_nlwps == 1);
    528  1.164   thorpej 
    529  1.164   thorpej 	/* This is now LWP 1 */
    530  1.164   thorpej 	l->l_lid = 1;
    531  1.164   thorpej 	p->p_nlwpid = 1;
    532  1.164   thorpej 
    533  1.164   thorpej 	/* Release any SA state. */
    534  1.164   thorpej 	if (p->p_sa) {
    535  1.164   thorpej 		p->p_flag &= ~P_SA;
    536  1.164   thorpej 		free(p->p_sa->sa_stacks, M_SA);
    537  1.164   thorpej 		pool_put(&sadata_pool, p->p_sa);
    538  1.164   thorpej 		p->p_sa = NULL;
    539  1.164   thorpej 	}
    540  1.164   thorpej 
    541  1.164   thorpej 	/* Remove POSIX timers */
    542  1.164   thorpej 	timers_free(p, TIMERS_POSIX);
    543  1.164   thorpej 
    544   1.55       cgd 	/* adjust "active stack depth" for process VSZ */
    545   1.55       cgd 	pack.ep_ssize = len;	/* maybe should go elsewhere, but... */
    546   1.55       cgd 
    547   1.86   thorpej 	/*
    548   1.86   thorpej 	 * Do whatever is necessary to prepare the address space
    549   1.86   thorpej 	 * for remapping.  Note that this might replace the current
    550   1.86   thorpej 	 * vmspace with another!
    551   1.86   thorpej 	 */
    552  1.164   thorpej 	uvmspace_exec(l, pack.ep_vm_minaddr, pack.ep_vm_maxaddr);
    553   1.55       cgd 
    554   1.55       cgd 	/* Now map address space */
    555   1.86   thorpej 	vm = p->p_vmspace;
    556  1.158  junyoung 	vm->vm_taddr = (caddr_t) pack.ep_taddr;
    557   1.55       cgd 	vm->vm_tsize = btoc(pack.ep_tsize);
    558  1.158  junyoung 	vm->vm_daddr = (caddr_t) pack.ep_daddr;
    559   1.55       cgd 	vm->vm_dsize = btoc(pack.ep_dsize);
    560   1.55       cgd 	vm->vm_ssize = btoc(pack.ep_ssize);
    561  1.158  junyoung 	vm->vm_maxsaddr = (caddr_t) pack.ep_maxsaddr;
    562  1.158  junyoung 	vm->vm_minsaddr = (caddr_t) pack.ep_minsaddr;
    563   1.55       cgd 
    564   1.55       cgd 	/* create the new process's VM space by running the vmcmds */
    565   1.55       cgd #ifdef DIAGNOSTIC
    566   1.55       cgd 	if (pack.ep_vmcmds.evs_used == 0)
    567   1.55       cgd 		panic("execve: no vmcmds");
    568   1.55       cgd #endif
    569   1.55       cgd 	for (i = 0; i < pack.ep_vmcmds.evs_used && !error; i++) {
    570   1.55       cgd 		struct exec_vmcmd *vcp;
    571   1.55       cgd 
    572   1.55       cgd 		vcp = &pack.ep_vmcmds.evs_cmds[i];
    573  1.114      matt 		if (vcp->ev_flags & VMCMD_RELATIVE) {
    574  1.114      matt #ifdef DIAGNOSTIC
    575  1.114      matt 			if (base_vcp == NULL)
    576  1.114      matt 				panic("execve: relative vmcmd with no base");
    577  1.114      matt 			if (vcp->ev_flags & VMCMD_BASE)
    578  1.114      matt 				panic("execve: illegal base & relative vmcmd");
    579  1.114      matt #endif
    580  1.114      matt 			vcp->ev_addr += base_vcp->ev_addr;
    581  1.114      matt 		}
    582  1.169      fvdl 		error = (*vcp->ev_proc)(p, vcp);
    583  1.143  christos #ifdef DEBUG_EXEC
    584  1.111      matt 		if (error) {
    585  1.143  christos 			int j;
    586  1.143  christos 			struct exec_vmcmd *vp = &pack.ep_vmcmds.evs_cmds[0];
    587  1.143  christos 			for (j = 0; j <= i; j++)
    588  1.143  christos 				uprintf(
    589  1.143  christos 			    "vmcmd[%d] = %#lx/%#lx fd@%#lx prot=0%o flags=%d\n",
    590  1.143  christos 				    j, vp[j].ev_addr, vp[j].ev_len,
    591  1.143  christos 				    vp[j].ev_offset, vp[j].ev_prot,
    592  1.143  christos 				    vp[j].ev_flags);
    593  1.111      matt 		}
    594  1.143  christos #endif /* DEBUG_EXEC */
    595  1.114      matt 		if (vcp->ev_flags & VMCMD_BASE)
    596  1.114      matt 			base_vcp = vcp;
    597   1.55       cgd 	}
    598   1.55       cgd 
    599   1.55       cgd 	/* free the vmspace-creation commands, and release their references */
    600   1.55       cgd 	kill_vmcmds(&pack.ep_vmcmds);
    601   1.55       cgd 
    602   1.55       cgd 	/* if an error happened, deallocate and punt */
    603  1.111      matt 	if (error) {
    604  1.143  christos 		DPRINTF(("execve: vmcmd %i failed: %d\n", i - 1, error));
    605   1.55       cgd 		goto exec_abort;
    606  1.111      matt 	}
    607   1.55       cgd 
    608   1.55       cgd 	/* remember information about the process */
    609   1.55       cgd 	arginfo.ps_nargvstr = argc;
    610   1.55       cgd 	arginfo.ps_nenvstr = envc;
    611   1.55       cgd 
    612  1.163       chs 	stack = (char *)STACK_ALLOC(STACK_GROW(vm->vm_minsaddr,
    613  1.163       chs 		sizeof(struct ps_strings) + szsigcode),
    614  1.163       chs 		len - (sizeof(struct ps_strings) + szsigcode));
    615  1.163       chs #ifdef __MACHINE_STACK_GROWS_UP
    616  1.163       chs 	/*
    617  1.163       chs 	 * The copyargs call always copies into lower addresses
    618  1.163       chs 	 * first, moving towards higher addresses, starting with
    619  1.163       chs 	 * the stack pointer that we give.  When the stack grows
    620  1.163       chs 	 * down, this puts argc/argv/envp very shallow on the
    621  1.163       chs 	 * stack, right at the first user stack pointer, and puts
    622  1.163       chs 	 * STACKGAPLEN very deep in the stack.  When the stack
    623  1.163       chs 	 * grows up, the situation is reversed.
    624  1.163       chs 	 *
    625  1.163       chs 	 * Normally, this is no big deal.  But the ld_elf.so _rtld()
    626  1.163       chs 	 * function expects to be called with a single pointer to
    627  1.163       chs 	 * a region that has a few words it can stash values into,
    628  1.163       chs 	 * followed by argc/argv/envp.  When the stack grows down,
    629  1.163       chs 	 * it's easy to decrement the stack pointer a little bit to
    630  1.163       chs 	 * allocate the space for these few words and pass the new
    631  1.163       chs 	 * stack pointer to _rtld.  When the stack grows up, however,
    632  1.163       chs 	 * a few words before argc is part of the signal trampoline,
    633  1.163       chs 	 * so we have a problem.
    634  1.163       chs 	 *
    635  1.163       chs 	 * Instead of changing how _rtld works, we take the easy way
    636  1.163       chs 	 * out and steal 32 bytes before we call copyargs.  This
    637  1.163       chs 	 * space is effectively stolen from STACKGAPLEN.
    638  1.163       chs 	 */
    639  1.163       chs 	stack += 32;
    640  1.163       chs #endif /* __MACHINE_STACK_GROWS_UP */
    641  1.163       chs 
    642   1.55       cgd 	/* Now copy argc, args & environ to new stack */
    643  1.169      fvdl 	error = (*pack.ep_es->es_copyargs)(p, &pack, &arginfo, &stack, argp);
    644  1.144  christos 	if (error) {
    645  1.144  christos 		DPRINTF(("execve: copyargs failed %d\n", error));
    646   1.55       cgd 		goto exec_abort;
    647  1.111      matt 	}
    648  1.144  christos 	/* Move the stack back to original point */
    649  1.163       chs 	stack = (char *)STACK_GROW(vm->vm_minsaddr, len);
    650   1.55       cgd 
    651  1.121       eeh 	/* fill process ps_strings info */
    652  1.163       chs 	p->p_psstr = (struct ps_strings *)STACK_ALLOC(vm->vm_minsaddr,
    653  1.163       chs 	    sizeof(struct ps_strings));
    654  1.121       eeh 	p->p_psargv = offsetof(struct ps_strings, ps_argvstr);
    655  1.121       eeh 	p->p_psnargv = offsetof(struct ps_strings, ps_nargvstr);
    656  1.121       eeh 	p->p_psenv = offsetof(struct ps_strings, ps_envstr);
    657  1.121       eeh 	p->p_psnenv = offsetof(struct ps_strings, ps_nenvstr);
    658  1.121       eeh 
    659   1.55       cgd 	/* copy out the process's ps_strings structure */
    660  1.144  christos 	if ((error = copyout(&arginfo, (char *)p->p_psstr,
    661  1.144  christos 	    sizeof(arginfo))) != 0) {
    662  1.143  christos 		DPRINTF(("execve: ps_strings copyout %p->%p size %ld failed\n",
    663  1.143  christos 		       &arginfo, (char *)p->p_psstr, (long)sizeof(arginfo)));
    664   1.55       cgd 		goto exec_abort;
    665  1.111      matt 	}
    666  1.109    simonb 
    667  1.158  junyoung 	/* copy out the process's signal trampoline code */
    668   1.96   mycroft 	if (szsigcode) {
    669  1.163       chs 		p->p_sigctx.ps_sigcode = STACK_ALLOC(STACK_MAX(p->p_psstr,
    670  1.163       chs 		    sizeof(struct ps_strings)), szsigcode);
    671  1.144  christos 		if ((error = copyout((char *)pack.ep_es->es_emul->e_sigcode,
    672  1.163       chs 		    p->p_sigctx.ps_sigcode, szsigcode)) != 0) {
    673  1.143  christos 			DPRINTF(("execve: sig trampoline copyout failed\n"));
    674   1.97    kleink 			goto exec_abort;
    675  1.111      matt 		}
    676  1.104        is #ifdef PMAP_NEED_PROCWR
    677  1.104        is 		/* This is code. Let the pmap do what is needed. */
    678  1.134  jdolecek 		pmap_procwr(p, (vaddr_t)p->p_sigctx.ps_sigcode, szsigcode);
    679  1.104        is #endif
    680   1.96   mycroft 	}
    681   1.55       cgd 
    682  1.102      ross 	stopprofclock(p);	/* stop profiling */
    683  1.169      fvdl 	fdcloseexec(p);		/* handle close on exec */
    684   1.55       cgd 	execsigs(p);		/* reset catched signals */
    685  1.164   thorpej 
    686  1.164   thorpej 	l->l_ctxlink = NULL;	/* reset ucontext link */
    687   1.55       cgd 
    688   1.55       cgd 	/* set command name & other accounting info */
    689   1.55       cgd 	len = min(nid.ni_cnd.cn_namelen, MAXCOMLEN);
    690   1.94     perry 	memcpy(p->p_comm, nid.ni_cnd.cn_nameptr, len);
    691   1.55       cgd 	p->p_comm[len] = 0;
    692   1.55       cgd 	p->p_acflag &= ~AFORK;
    693   1.55       cgd 
    694   1.55       cgd 	/* record proc's vnode, for use by procfs and others */
    695   1.55       cgd         if (p->p_textvp)
    696   1.55       cgd                 vrele(p->p_textvp);
    697   1.55       cgd 	VREF(pack.ep_vp);
    698   1.55       cgd 	p->p_textvp = pack.ep_vp;
    699   1.55       cgd 
    700   1.55       cgd 	p->p_flag |= P_EXEC;
    701   1.55       cgd 	if (p->p_flag & P_PPWAIT) {
    702   1.55       cgd 		p->p_flag &= ~P_PPWAIT;
    703   1.55       cgd 		wakeup((caddr_t) p->p_pptr);
    704   1.55       cgd 	}
    705   1.55       cgd 
    706   1.55       cgd 	/*
    707   1.55       cgd 	 * deal with set[ug]id.
    708  1.141   thorpej 	 * MNT_NOSUID has already been used to disable s[ug]id.
    709   1.55       cgd 	 */
    710  1.141   thorpej 	if ((p->p_flag & P_TRACED) == 0 &&
    711  1.141   thorpej 
    712  1.141   thorpej 	    (((attr.va_mode & S_ISUID) != 0 &&
    713  1.141   thorpej 	      p->p_ucred->cr_uid != attr.va_uid) ||
    714  1.141   thorpej 
    715  1.141   thorpej 	     ((attr.va_mode & S_ISGID) != 0 &&
    716  1.141   thorpej 	      p->p_ucred->cr_gid != attr.va_gid))) {
    717  1.141   thorpej 		/*
    718  1.141   thorpej 		 * Mark the process as SUGID before we do
    719  1.141   thorpej 		 * anything that might block.
    720  1.141   thorpej 		 */
    721  1.141   thorpej 		p_sugid(p);
    722  1.152  christos 
    723  1.152  christos 		/* Make sure file descriptors 0..2 are in use. */
    724  1.169      fvdl 		if ((error = fdcheckstd(p)) != 0)
    725  1.152  christos 			goto exec_abort;
    726  1.141   thorpej 
    727   1.55       cgd 		p->p_ucred = crcopy(cred);
    728   1.55       cgd #ifdef KTRACE
    729   1.55       cgd 		/*
    730   1.55       cgd 		 * If process is being ktraced, turn off - unless
    731   1.55       cgd 		 * root set it.
    732   1.55       cgd 		 */
    733   1.91  christos 		if (p->p_tracep && !(p->p_traceflag & KTRFAC_ROOT))
    734   1.91  christos 			ktrderef(p);
    735   1.55       cgd #endif
    736   1.83   mycroft 		if (attr.va_mode & S_ISUID)
    737   1.55       cgd 			p->p_ucred->cr_uid = attr.va_uid;
    738   1.83   mycroft 		if (attr.va_mode & S_ISGID)
    739   1.55       cgd 			p->p_ucred->cr_gid = attr.va_gid;
    740   1.79       mrg 	} else
    741   1.79       mrg 		p->p_flag &= ~P_SUGID;
    742   1.55       cgd 	p->p_cred->p_svuid = p->p_ucred->cr_uid;
    743   1.55       cgd 	p->p_cred->p_svgid = p->p_ucred->cr_gid;
    744  1.155  gmcgarry 
    745  1.155  gmcgarry #if defined(__HAVE_RAS)
    746  1.155  gmcgarry 	/*
    747  1.155  gmcgarry 	 * Remove all RASs from the address space.
    748  1.155  gmcgarry 	 */
    749  1.155  gmcgarry 	ras_purgeall(p);
    750  1.155  gmcgarry #endif
    751  1.107      fvdl 
    752  1.107      fvdl 	doexechooks(p);
    753   1.55       cgd 
    754   1.95       eeh 	uvm_km_free_wakeup(exec_map, (vaddr_t) argp, NCARGS);
    755   1.55       cgd 
    756  1.120   thorpej 	PNBUF_PUT(nid.ni_cnd.cn_pnbuf);
    757   1.99  wrstuden 	vn_lock(pack.ep_vp, LK_EXCLUSIVE | LK_RETRY);
    758  1.169      fvdl 	VOP_CLOSE(pack.ep_vp, FREAD, cred, p);
    759   1.99  wrstuden 	vput(pack.ep_vp);
    760  1.159  jdolecek 
    761  1.159  jdolecek 	/* notify others that we exec'd */
    762  1.159  jdolecek 	KNOTE(&p->p_klist, NOTE_EXEC);
    763   1.55       cgd 
    764   1.55       cgd 	/* setup new registers and do misc. setup. */
    765  1.164   thorpej 	(*pack.ep_es->es_emul->e_setregs)(l, &pack, (u_long) stack);
    766  1.145  jdolecek 	if (pack.ep_es->es_setregs)
    767  1.164   thorpej 		(*pack.ep_es->es_setregs)(l, &pack, (u_long) stack);
    768   1.55       cgd 
    769   1.55       cgd 	if (p->p_flag & P_TRACED)
    770   1.55       cgd 		psignal(p, SIGTRAP);
    771   1.55       cgd 
    772  1.122  jdolecek 	free(pack.ep_hdr, M_EXEC);
    773  1.122  jdolecek 
    774  1.122  jdolecek 	/*
    775  1.122  jdolecek 	 * Call emulation specific exec hook. This can setup setup per-process
    776  1.122  jdolecek 	 * p->p_emuldata or do any other per-process stuff an emulation needs.
    777  1.122  jdolecek 	 *
    778  1.122  jdolecek 	 * If we are executing process of different emulation than the
    779  1.122  jdolecek 	 * original forked process, call e_proc_exit() of the old emulation
    780  1.122  jdolecek 	 * first, then e_proc_exec() of new emulation. If the emulation is
    781  1.122  jdolecek 	 * same, the exec hook code should deallocate any old emulation
    782  1.122  jdolecek 	 * resources held previously by this process.
    783  1.122  jdolecek 	 */
    784  1.124  jdolecek 	if (p->p_emul && p->p_emul->e_proc_exit
    785  1.124  jdolecek 	    && p->p_emul != pack.ep_es->es_emul)
    786  1.122  jdolecek 		(*p->p_emul->e_proc_exit)(p);
    787  1.122  jdolecek 
    788  1.123  jdolecek 	/*
    789  1.123  jdolecek 	 * Call exec hook. Emulation code may NOT store reference to anything
    790  1.123  jdolecek 	 * from &pack.
    791  1.123  jdolecek 	 */
    792  1.124  jdolecek         if (pack.ep_es->es_emul->e_proc_exec)
    793  1.124  jdolecek                 (*pack.ep_es->es_emul->e_proc_exec)(p, &pack);
    794  1.122  jdolecek 
    795  1.122  jdolecek 	/* update p_emul, the old value is no longer needed */
    796  1.124  jdolecek 	p->p_emul = pack.ep_es->es_emul;
    797  1.148   thorpej 
    798  1.148   thorpej 	/* ...and the same for p_execsw */
    799  1.148   thorpej 	p->p_execsw = pack.ep_es;
    800  1.148   thorpej 
    801  1.133   mycroft #ifdef __HAVE_SYSCALL_INTERN
    802  1.133   mycroft 	(*p->p_emul->e_syscall_intern)(p);
    803  1.133   mycroft #endif
    804   1.70  christos #ifdef KTRACE
    805   1.70  christos 	if (KTRPOINT(p, KTR_EMUL))
    806  1.169      fvdl 		ktremul(p);
    807   1.70  christos #endif
    808   1.85   mycroft 
    809  1.147  jdolecek #ifdef LKM
    810  1.130  jdolecek 	lockmgr(&exec_lock, LK_RELEASE, NULL);
    811  1.147  jdolecek #endif
    812  1.149  christos 	p->p_flag &= ~P_INEXEC;
    813  1.162      manu 
    814  1.162      manu 	if (p->p_flag & P_STOPEXEC) {
    815  1.162      manu 		int s;
    816  1.162      manu 
    817  1.162      manu 		sigminusset(&contsigmask, &p->p_sigctx.ps_siglist);
    818  1.162      manu 		SCHED_LOCK(s);
    819  1.162      manu 		p->p_stat = SSTOP;
    820  1.164   thorpej 		l->l_stat = LSSTOP;
    821  1.164   thorpej 		p->p_nrlwps--;
    822  1.164   thorpej 		mi_switch(l, NULL);
    823  1.162      manu 		SCHED_ASSERT_UNLOCKED();
    824  1.162      manu 		splx(s);
    825  1.162      manu 	}
    826  1.162      manu 
    827   1.85   mycroft 	return (EJUSTRETURN);
    828   1.55       cgd 
    829  1.138     lukem  bad:
    830  1.149  christos 	p->p_flag &= ~P_INEXEC;
    831   1.55       cgd 	/* free the vmspace-creation commands, and release their references */
    832   1.55       cgd 	kill_vmcmds(&pack.ep_vmcmds);
    833   1.55       cgd 	/* kill any opened file descriptor, if necessary */
    834   1.55       cgd 	if (pack.ep_flags & EXEC_HASFD) {
    835   1.55       cgd 		pack.ep_flags &= ~EXEC_HASFD;
    836  1.169      fvdl 		(void) fdrelease(p, pack.ep_fd);
    837   1.55       cgd 	}
    838   1.55       cgd 	/* close and put the exec'd file */
    839   1.99  wrstuden 	vn_lock(pack.ep_vp, LK_EXCLUSIVE | LK_RETRY);
    840  1.169      fvdl 	VOP_CLOSE(pack.ep_vp, FREAD, cred, p);
    841   1.99  wrstuden 	vput(pack.ep_vp);
    842  1.120   thorpej 	PNBUF_PUT(nid.ni_cnd.cn_pnbuf);
    843   1.95       eeh 	uvm_km_free_wakeup(exec_map, (vaddr_t) argp, NCARGS);
    844   1.55       cgd 
    845  1.138     lukem  freehdr:
    846  1.164   thorpej 	l->l_flag |= oldlwpflags;
    847  1.150  christos 	p->p_flag &= ~P_INEXEC;
    848  1.147  jdolecek #ifdef LKM
    849  1.130  jdolecek 	lockmgr(&exec_lock, LK_RELEASE, NULL);
    850  1.147  jdolecek #endif
    851  1.130  jdolecek 
    852  1.119   thorpej 	free(pack.ep_hdr, M_EXEC);
    853   1.55       cgd 	return error;
    854   1.55       cgd 
    855  1.138     lukem  exec_abort:
    856  1.150  christos 	p->p_flag &= ~P_INEXEC;
    857  1.147  jdolecek #ifdef LKM
    858  1.130  jdolecek 	lockmgr(&exec_lock, LK_RELEASE, NULL);
    859  1.147  jdolecek #endif
    860  1.130  jdolecek 
    861   1.55       cgd 	/*
    862   1.55       cgd 	 * the old process doesn't exist anymore.  exit gracefully.
    863   1.55       cgd 	 * get rid of the (new) address space we have created, if any, get rid
    864   1.55       cgd 	 * of our namei data and vnode, and exit noting failure
    865   1.55       cgd 	 */
    866   1.88       mrg 	uvm_deallocate(&vm->vm_map, VM_MIN_ADDRESS,
    867   1.88       mrg 		VM_MAXUSER_ADDRESS - VM_MIN_ADDRESS);
    868   1.73   mycroft 	if (pack.ep_emul_arg)
    869  1.124  jdolecek 		FREE(pack.ep_emul_arg, M_TEMP);
    870  1.120   thorpej 	PNBUF_PUT(nid.ni_cnd.cn_pnbuf);
    871   1.99  wrstuden 	vn_lock(pack.ep_vp, LK_EXCLUSIVE | LK_RETRY);
    872  1.169      fvdl 	VOP_CLOSE(pack.ep_vp, FREAD, cred, p);
    873   1.99  wrstuden 	vput(pack.ep_vp);
    874   1.95       eeh 	uvm_km_free_wakeup(exec_map, (vaddr_t) argp, NCARGS);
    875  1.119   thorpej 	free(pack.ep_hdr, M_EXEC);
    876  1.164   thorpej 	exit1(l, W_EXITCODE(error, SIGABRT));
    877   1.55       cgd 
    878   1.55       cgd 	/* NOTREACHED */
    879   1.55       cgd 	return 0;
    880   1.67  christos }
    881   1.67  christos 
    882   1.67  christos 
    883  1.144  christos int
    884  1.169      fvdl copyargs(struct proc *p, struct exec_package *pack, struct ps_strings *arginfo,
    885  1.144  christos     char **stackp, void *argp)
    886   1.67  christos {
    887  1.138     lukem 	char	**cpp, *dp, *sp;
    888  1.138     lukem 	size_t	len;
    889  1.138     lukem 	void	*nullp;
    890  1.138     lukem 	long	argc, envc;
    891  1.144  christos 	int	error;
    892  1.138     lukem 
    893  1.144  christos 	cpp = (char **)*stackp;
    894  1.138     lukem 	nullp = NULL;
    895  1.138     lukem 	argc = arginfo->ps_nargvstr;
    896  1.138     lukem 	envc = arginfo->ps_nenvstr;
    897  1.144  christos 	if ((error = copyout(&argc, cpp++, sizeof(argc))) != 0)
    898  1.144  christos 		return error;
    899   1.67  christos 
    900  1.124  jdolecek 	dp = (char *) (cpp + argc + envc + 2 + pack->ep_es->es_arglen);
    901   1.67  christos 	sp = argp;
    902   1.67  christos 
    903   1.67  christos 	/* XXX don't copy them out, remap them! */
    904   1.69   mycroft 	arginfo->ps_argvstr = cpp; /* remember location of argv for later */
    905   1.67  christos 
    906   1.67  christos 	for (; --argc >= 0; sp += len, dp += len)
    907  1.144  christos 		if ((error = copyout(&dp, cpp++, sizeof(dp))) != 0 ||
    908  1.144  christos 		    (error = copyoutstr(sp, dp, ARG_MAX, &len)) != 0)
    909  1.144  christos 			return error;
    910   1.67  christos 
    911  1.144  christos 	if ((error = copyout(&nullp, cpp++, sizeof(nullp))) != 0)
    912  1.144  christos 		return error;
    913   1.67  christos 
    914   1.69   mycroft 	arginfo->ps_envstr = cpp; /* remember location of envp for later */
    915   1.67  christos 
    916   1.67  christos 	for (; --envc >= 0; sp += len, dp += len)
    917  1.144  christos 		if ((error = copyout(&dp, cpp++, sizeof(dp))) != 0 ||
    918  1.144  christos 		    (error = copyoutstr(sp, dp, ARG_MAX, &len)) != 0)
    919  1.144  christos 			return error;
    920   1.67  christos 
    921  1.144  christos 	if ((error = copyout(&nullp, cpp++, sizeof(nullp))) != 0)
    922  1.144  christos 		return error;
    923   1.67  christos 
    924  1.144  christos 	*stackp = (char *)cpp;
    925  1.144  christos 	return 0;
    926   1.55       cgd }
    927  1.130  jdolecek 
    928  1.130  jdolecek #ifdef LKM
    929  1.130  jdolecek /*
    930  1.130  jdolecek  * Find an emulation of given name in list of emulations.
    931  1.151  jdolecek  * Needs to be called with the exec_lock held.
    932  1.130  jdolecek  */
    933  1.151  jdolecek const struct emul *
    934  1.138     lukem emul_search(const char *name)
    935  1.130  jdolecek {
    936  1.130  jdolecek 	struct emul_entry *it;
    937  1.130  jdolecek 
    938  1.130  jdolecek 	LIST_FOREACH(it, &el_head, el_list) {
    939  1.130  jdolecek 		if (strcmp(name, it->el_emul->e_name) == 0)
    940  1.130  jdolecek 			return it->el_emul;
    941  1.130  jdolecek 	}
    942  1.130  jdolecek 
    943  1.130  jdolecek 	return NULL;
    944  1.130  jdolecek }
    945  1.130  jdolecek 
    946  1.130  jdolecek /*
    947  1.130  jdolecek  * Add an emulation to list, if it's not there already.
    948  1.130  jdolecek  */
    949  1.130  jdolecek int
    950  1.138     lukem emul_register(const struct emul *emul, int ro_entry)
    951  1.130  jdolecek {
    952  1.138     lukem 	struct emul_entry	*ee;
    953  1.138     lukem 	int			error;
    954  1.130  jdolecek 
    955  1.138     lukem 	error = 0;
    956  1.130  jdolecek 	lockmgr(&exec_lock, LK_SHARED, NULL);
    957  1.130  jdolecek 
    958  1.130  jdolecek 	if (emul_search(emul->e_name)) {
    959  1.130  jdolecek 		error = EEXIST;
    960  1.130  jdolecek 		goto out;
    961  1.130  jdolecek 	}
    962  1.130  jdolecek 
    963  1.130  jdolecek 	MALLOC(ee, struct emul_entry *, sizeof(struct emul_entry),
    964  1.130  jdolecek 		M_EXEC, M_WAITOK);
    965  1.130  jdolecek 	ee->el_emul = emul;
    966  1.130  jdolecek 	ee->ro_entry = ro_entry;
    967  1.130  jdolecek 	LIST_INSERT_HEAD(&el_head, ee, el_list);
    968  1.130  jdolecek 
    969  1.138     lukem  out:
    970  1.130  jdolecek 	lockmgr(&exec_lock, LK_RELEASE, NULL);
    971  1.130  jdolecek 	return error;
    972  1.130  jdolecek }
    973  1.130  jdolecek 
    974  1.130  jdolecek /*
    975  1.130  jdolecek  * Remove emulation with name 'name' from list of supported emulations.
    976  1.130  jdolecek  */
    977  1.130  jdolecek int
    978  1.138     lukem emul_unregister(const char *name)
    979  1.130  jdolecek {
    980  1.130  jdolecek 	const struct proclist_desc *pd;
    981  1.138     lukem 	struct emul_entry	*it;
    982  1.138     lukem 	int			i, error;
    983  1.138     lukem 	struct proc		*ptmp;
    984  1.130  jdolecek 
    985  1.138     lukem 	error = 0;
    986  1.130  jdolecek 	lockmgr(&exec_lock, LK_SHARED, NULL);
    987  1.130  jdolecek 
    988  1.130  jdolecek 	LIST_FOREACH(it, &el_head, el_list) {
    989  1.130  jdolecek 		if (strcmp(it->el_emul->e_name, name) == 0)
    990  1.130  jdolecek 			break;
    991  1.130  jdolecek 	}
    992  1.130  jdolecek 
    993  1.130  jdolecek 	if (!it) {
    994  1.130  jdolecek 		error = ENOENT;
    995  1.130  jdolecek 		goto out;
    996  1.130  jdolecek 	}
    997  1.130  jdolecek 
    998  1.130  jdolecek 	if (it->ro_entry) {
    999  1.130  jdolecek 		error = EBUSY;
   1000  1.130  jdolecek 		goto out;
   1001  1.130  jdolecek 	}
   1002  1.130  jdolecek 
   1003  1.130  jdolecek 	/* test if any execw[] entry is still using this */
   1004  1.132  jdolecek 	for(i=0; i < nexecs; i++) {
   1005  1.130  jdolecek 		if (execsw[i]->es_emul == it->el_emul) {
   1006  1.130  jdolecek 			error = EBUSY;
   1007  1.130  jdolecek 			goto out;
   1008  1.130  jdolecek 		}
   1009  1.130  jdolecek 	}
   1010  1.130  jdolecek 
   1011  1.130  jdolecek 	/*
   1012  1.130  jdolecek 	 * Test if any process is running under this emulation - since
   1013  1.130  jdolecek 	 * emul_unregister() is running quite sendomly, it's better
   1014  1.130  jdolecek 	 * to do expensive check here than to use any locking.
   1015  1.130  jdolecek 	 */
   1016  1.130  jdolecek 	proclist_lock_read();
   1017  1.130  jdolecek 	for (pd = proclists; pd->pd_list != NULL && !error; pd++) {
   1018  1.130  jdolecek 		LIST_FOREACH(ptmp, pd->pd_list, p_list) {
   1019  1.130  jdolecek 			if (ptmp->p_emul == it->el_emul) {
   1020  1.130  jdolecek 				error = EBUSY;
   1021  1.130  jdolecek 				break;
   1022  1.130  jdolecek 			}
   1023  1.130  jdolecek 		}
   1024  1.130  jdolecek 	}
   1025  1.130  jdolecek 	proclist_unlock_read();
   1026  1.130  jdolecek 
   1027  1.130  jdolecek 	if (error)
   1028  1.130  jdolecek 		goto out;
   1029  1.130  jdolecek 
   1030  1.130  jdolecek 
   1031  1.130  jdolecek 	/* entry is not used, remove it */
   1032  1.130  jdolecek 	LIST_REMOVE(it, el_list);
   1033  1.130  jdolecek 	FREE(it, M_EXEC);
   1034  1.130  jdolecek 
   1035  1.138     lukem  out:
   1036  1.130  jdolecek 	lockmgr(&exec_lock, LK_RELEASE, NULL);
   1037  1.130  jdolecek 	return error;
   1038  1.130  jdolecek }
   1039  1.130  jdolecek 
   1040  1.130  jdolecek /*
   1041  1.130  jdolecek  * Add execsw[] entry.
   1042  1.130  jdolecek  */
   1043  1.130  jdolecek int
   1044  1.138     lukem exec_add(struct execsw *esp, const char *e_name)
   1045  1.130  jdolecek {
   1046  1.138     lukem 	struct exec_entry	*it;
   1047  1.138     lukem 	int			error;
   1048  1.130  jdolecek 
   1049  1.138     lukem 	error = 0;
   1050  1.130  jdolecek 	lockmgr(&exec_lock, LK_EXCLUSIVE, NULL);
   1051  1.130  jdolecek 
   1052  1.130  jdolecek 	if (!esp->es_emul) {
   1053  1.130  jdolecek 		esp->es_emul = emul_search(e_name);
   1054  1.130  jdolecek 		if (!esp->es_emul) {
   1055  1.130  jdolecek 			error = ENOENT;
   1056  1.130  jdolecek 			goto out;
   1057  1.130  jdolecek 		}
   1058  1.130  jdolecek 	}
   1059  1.130  jdolecek 
   1060  1.130  jdolecek 	LIST_FOREACH(it, &ex_head, ex_list) {
   1061  1.130  jdolecek 		/* assume tuple (makecmds, probe_func, emulation) is unique */
   1062  1.130  jdolecek 		if (it->es->es_check == esp->es_check
   1063  1.130  jdolecek 		    && it->es->u.elf_probe_func == esp->u.elf_probe_func
   1064  1.130  jdolecek 		    && it->es->es_emul == esp->es_emul) {
   1065  1.130  jdolecek 			error = EEXIST;
   1066  1.130  jdolecek 			goto out;
   1067  1.130  jdolecek 		}
   1068  1.130  jdolecek 	}
   1069  1.130  jdolecek 
   1070  1.130  jdolecek 	/* if we got here, the entry doesn't exist yet */
   1071  1.130  jdolecek 	MALLOC(it, struct exec_entry *, sizeof(struct exec_entry),
   1072  1.130  jdolecek 		M_EXEC, M_WAITOK);
   1073  1.130  jdolecek 	it->es = esp;
   1074  1.130  jdolecek 	LIST_INSERT_HEAD(&ex_head, it, ex_list);
   1075  1.130  jdolecek 
   1076  1.130  jdolecek 	/* update execsw[] */
   1077  1.130  jdolecek 	exec_init(0);
   1078  1.130  jdolecek 
   1079  1.138     lukem  out:
   1080  1.130  jdolecek 	lockmgr(&exec_lock, LK_RELEASE, NULL);
   1081  1.130  jdolecek 	return error;
   1082  1.130  jdolecek }
   1083  1.130  jdolecek 
   1084  1.130  jdolecek /*
   1085  1.130  jdolecek  * Remove execsw[] entry.
   1086  1.130  jdolecek  */
   1087  1.130  jdolecek int
   1088  1.138     lukem exec_remove(const struct execsw *esp)
   1089  1.130  jdolecek {
   1090  1.138     lukem 	struct exec_entry	*it;
   1091  1.138     lukem 	int			error;
   1092  1.130  jdolecek 
   1093  1.138     lukem 	error = 0;
   1094  1.130  jdolecek 	lockmgr(&exec_lock, LK_EXCLUSIVE, NULL);
   1095  1.130  jdolecek 
   1096  1.130  jdolecek 	LIST_FOREACH(it, &ex_head, ex_list) {
   1097  1.130  jdolecek 		/* assume tuple (makecmds, probe_func, emulation) is unique */
   1098  1.130  jdolecek 		if (it->es->es_check == esp->es_check
   1099  1.130  jdolecek 		    && it->es->u.elf_probe_func == esp->u.elf_probe_func
   1100  1.130  jdolecek 		    && it->es->es_emul == esp->es_emul)
   1101  1.130  jdolecek 			break;
   1102  1.130  jdolecek 	}
   1103  1.130  jdolecek 	if (!it) {
   1104  1.130  jdolecek 		error = ENOENT;
   1105  1.130  jdolecek 		goto out;
   1106  1.130  jdolecek 	}
   1107  1.130  jdolecek 
   1108  1.130  jdolecek 	/* remove item from list and free resources */
   1109  1.130  jdolecek 	LIST_REMOVE(it, ex_list);
   1110  1.130  jdolecek 	FREE(it, M_EXEC);
   1111  1.130  jdolecek 
   1112  1.130  jdolecek 	/* update execsw[] */
   1113  1.130  jdolecek 	exec_init(0);
   1114  1.130  jdolecek 
   1115  1.138     lukem  out:
   1116  1.130  jdolecek 	lockmgr(&exec_lock, LK_RELEASE, NULL);
   1117  1.130  jdolecek 	return error;
   1118  1.130  jdolecek }
   1119  1.130  jdolecek 
   1120  1.130  jdolecek static void
   1121  1.138     lukem link_es(struct execsw_entry **listp, const struct execsw *esp)
   1122  1.130  jdolecek {
   1123  1.130  jdolecek 	struct execsw_entry *et, *e1;
   1124  1.130  jdolecek 
   1125  1.130  jdolecek 	MALLOC(et, struct execsw_entry *, sizeof(struct execsw_entry),
   1126  1.130  jdolecek 			M_TEMP, M_WAITOK);
   1127  1.130  jdolecek 	et->next = NULL;
   1128  1.130  jdolecek 	et->es = esp;
   1129  1.130  jdolecek 	if (*listp == NULL) {
   1130  1.130  jdolecek 		*listp = et;
   1131  1.130  jdolecek 		return;
   1132  1.130  jdolecek 	}
   1133  1.130  jdolecek 
   1134  1.130  jdolecek 	switch(et->es->es_prio) {
   1135  1.130  jdolecek 	case EXECSW_PRIO_FIRST:
   1136  1.130  jdolecek 		/* put new entry as the first */
   1137  1.130  jdolecek 		et->next = *listp;
   1138  1.130  jdolecek 		*listp = et;
   1139  1.130  jdolecek 		break;
   1140  1.130  jdolecek 	case EXECSW_PRIO_ANY:
   1141  1.130  jdolecek 		/* put new entry after all *_FIRST and *_ANY entries */
   1142  1.130  jdolecek 		for(e1 = *listp; e1->next
   1143  1.130  jdolecek 			&& e1->next->es->es_prio != EXECSW_PRIO_LAST;
   1144  1.130  jdolecek 			e1 = e1->next);
   1145  1.130  jdolecek 		et->next = e1->next;
   1146  1.130  jdolecek 		e1->next = et;
   1147  1.130  jdolecek 		break;
   1148  1.130  jdolecek 	case EXECSW_PRIO_LAST:
   1149  1.130  jdolecek 		/* put new entry as the last one */
   1150  1.130  jdolecek 		for(e1 = *listp; e1->next; e1 = e1->next);
   1151  1.130  jdolecek 		e1->next = et;
   1152  1.130  jdolecek 		break;
   1153  1.130  jdolecek 	default:
   1154  1.130  jdolecek #ifdef DIAGNOSTIC
   1155  1.157    provos 		panic("execw[] entry with unknown priority %d found",
   1156  1.130  jdolecek 			et->es->es_prio);
   1157  1.130  jdolecek #endif
   1158  1.130  jdolecek 		break;
   1159  1.130  jdolecek 	}
   1160  1.130  jdolecek }
   1161  1.130  jdolecek 
   1162  1.130  jdolecek /*
   1163  1.130  jdolecek  * Initialize exec structures. If init_boot is true, also does necessary
   1164  1.130  jdolecek  * one-time initialization (it's called from main() that way).
   1165  1.147  jdolecek  * Once system is multiuser, this should be called with exec_lock held,
   1166  1.130  jdolecek  * i.e. via exec_{add|remove}().
   1167  1.130  jdolecek  */
   1168  1.130  jdolecek int
   1169  1.138     lukem exec_init(int init_boot)
   1170  1.130  jdolecek {
   1171  1.138     lukem 	const struct execsw	**new_es, * const *old_es;
   1172  1.138     lukem 	struct execsw_entry	*list, *e1;
   1173  1.138     lukem 	struct exec_entry	*e2;
   1174  1.138     lukem 	int			i, es_sz;
   1175  1.130  jdolecek 
   1176  1.130  jdolecek 	if (init_boot) {
   1177  1.130  jdolecek 		/* do one-time initializations */
   1178  1.130  jdolecek 		lockinit(&exec_lock, PWAIT, "execlck", 0, 0);
   1179  1.130  jdolecek 
   1180  1.130  jdolecek 		/* register compiled-in emulations */
   1181  1.130  jdolecek 		for(i=0; i < nexecs_builtin; i++) {
   1182  1.130  jdolecek 			if (execsw_builtin[i].es_emul)
   1183  1.130  jdolecek 				emul_register(execsw_builtin[i].es_emul, 1);
   1184  1.130  jdolecek 		}
   1185  1.130  jdolecek #ifdef DIAGNOSTIC
   1186  1.130  jdolecek 		if (i == 0)
   1187  1.157    provos 			panic("no emulations found in execsw_builtin[]");
   1188  1.130  jdolecek #endif
   1189  1.130  jdolecek 	}
   1190  1.130  jdolecek 
   1191  1.130  jdolecek 	/*
   1192  1.130  jdolecek 	 * Build execsw[] array from builtin entries and entries added
   1193  1.130  jdolecek 	 * at runtime.
   1194  1.130  jdolecek 	 */
   1195  1.130  jdolecek 	list = NULL;
   1196  1.130  jdolecek 	for(i=0; i < nexecs_builtin; i++)
   1197  1.130  jdolecek 		link_es(&list, &execsw_builtin[i]);
   1198  1.130  jdolecek 
   1199  1.130  jdolecek 	/* Add dynamically loaded entries */
   1200  1.130  jdolecek 	es_sz = nexecs_builtin;
   1201  1.130  jdolecek 	LIST_FOREACH(e2, &ex_head, ex_list) {
   1202  1.130  jdolecek 		link_es(&list, e2->es);
   1203  1.130  jdolecek 		es_sz++;
   1204  1.130  jdolecek 	}
   1205  1.130  jdolecek 
   1206  1.130  jdolecek 	/*
   1207  1.130  jdolecek 	 * Now that we have sorted all execw entries, create new execsw[]
   1208  1.130  jdolecek 	 * and free no longer needed memory in the process.
   1209  1.130  jdolecek 	 */
   1210  1.130  jdolecek 	new_es = malloc(es_sz * sizeof(struct execsw *), M_EXEC, M_WAITOK);
   1211  1.130  jdolecek 	for(i=0; list; i++) {
   1212  1.130  jdolecek 		new_es[i] = list->es;
   1213  1.130  jdolecek 		e1 = list->next;
   1214  1.130  jdolecek 		FREE(list, M_TEMP);
   1215  1.130  jdolecek 		list = e1;
   1216  1.130  jdolecek 	}
   1217  1.130  jdolecek 
   1218  1.130  jdolecek 	/*
   1219  1.130  jdolecek 	 * New execsw[] array built, now replace old execsw[] and free
   1220  1.130  jdolecek 	 * used memory.
   1221  1.130  jdolecek 	 */
   1222  1.130  jdolecek 	old_es = execsw;
   1223  1.130  jdolecek 	execsw = new_es;
   1224  1.130  jdolecek 	nexecs = es_sz;
   1225  1.130  jdolecek 	if (old_es)
   1226  1.130  jdolecek 		free((void *)old_es, M_EXEC);
   1227  1.130  jdolecek 
   1228  1.130  jdolecek 	/*
   1229  1.130  jdolecek 	 * Figure out the maximum size of an exec header.
   1230  1.130  jdolecek 	 */
   1231  1.130  jdolecek 	exec_maxhdrsz = 0;
   1232  1.130  jdolecek 	for (i = 0; i < nexecs; i++) {
   1233  1.130  jdolecek 		if (execsw[i]->es_hdrsz > exec_maxhdrsz)
   1234  1.130  jdolecek 			exec_maxhdrsz = execsw[i]->es_hdrsz;
   1235  1.130  jdolecek 	}
   1236  1.130  jdolecek 
   1237  1.130  jdolecek 	return 0;
   1238  1.130  jdolecek }
   1239  1.130  jdolecek #endif
   1240  1.130  jdolecek 
   1241  1.130  jdolecek #ifndef LKM
   1242  1.130  jdolecek /*
   1243  1.130  jdolecek  * Simplified exec_init() for kernels without LKMs. Only initialize
   1244  1.130  jdolecek  * exec_maxhdrsz and execsw[].
   1245  1.130  jdolecek  */
   1246  1.130  jdolecek int
   1247  1.138     lukem exec_init(int init_boot)
   1248  1.130  jdolecek {
   1249  1.130  jdolecek 	int i;
   1250  1.130  jdolecek 
   1251  1.130  jdolecek #ifdef DIAGNOSTIC
   1252  1.130  jdolecek 	if (!init_boot)
   1253  1.130  jdolecek 		panic("exec_init(): called with init_boot == 0");
   1254  1.130  jdolecek #endif
   1255  1.130  jdolecek 
   1256  1.130  jdolecek 	/* do one-time initializations */
   1257  1.130  jdolecek 	nexecs = nexecs_builtin;
   1258  1.130  jdolecek 	execsw = malloc(nexecs*sizeof(struct execsw *), M_EXEC, M_WAITOK);
   1259  1.130  jdolecek 
   1260  1.130  jdolecek 	/*
   1261  1.130  jdolecek 	 * Fill in execsw[] and figure out the maximum size of an exec header.
   1262  1.130  jdolecek 	 */
   1263  1.130  jdolecek 	exec_maxhdrsz = 0;
   1264  1.130  jdolecek 	for(i=0; i < nexecs; i++) {
   1265  1.130  jdolecek 		execsw[i] = &execsw_builtin[i];
   1266  1.130  jdolecek 		if (execsw_builtin[i].es_hdrsz > exec_maxhdrsz)
   1267  1.130  jdolecek 			exec_maxhdrsz = execsw_builtin[i].es_hdrsz;
   1268  1.130  jdolecek 	}
   1269  1.130  jdolecek 
   1270  1.130  jdolecek 	return 0;
   1271  1.130  jdolecek 
   1272  1.130  jdolecek }
   1273  1.130  jdolecek #endif /* !LKM */
   1274