xref: /openbsd-src/sys/kern/kern_exec.c (revision d479e8712bed4bdddf12a22be1e1cf5a88eaadb4)
1*d479e871Sclaudio /*	$OpenBSD: kern_exec.c,v 1.260 2025/01/25 19:21:40 claudio Exp $	*/
25ac46f4aSniklas /*	$NetBSD: kern_exec.c,v 1.75 1996/02/09 18:59:28 christos Exp $	*/
3df930be7Sderaadt 
4df930be7Sderaadt /*-
5df930be7Sderaadt  * Copyright (C) 1993, 1994 Christopher G. Demetriou
6df930be7Sderaadt  * Copyright (C) 1992 Wolfgang Solfrank.
7df930be7Sderaadt  * Copyright (C) 1992 TooLs GmbH.
8df930be7Sderaadt  * All rights reserved.
9df930be7Sderaadt  *
10df930be7Sderaadt  * Redistribution and use in source and binary forms, with or without
11df930be7Sderaadt  * modification, are permitted provided that the following conditions
12df930be7Sderaadt  * are met:
13df930be7Sderaadt  * 1. Redistributions of source code must retain the above copyright
14df930be7Sderaadt  *    notice, this list of conditions and the following disclaimer.
15df930be7Sderaadt  * 2. Redistributions in binary form must reproduce the above copyright
16df930be7Sderaadt  *    notice, this list of conditions and the following disclaimer in the
17df930be7Sderaadt  *    documentation and/or other materials provided with the distribution.
18df930be7Sderaadt  * 3. All advertising materials mentioning features or use of this software
19df930be7Sderaadt  *    must display the following acknowledgement:
20df930be7Sderaadt  *	This product includes software developed by TooLs GmbH.
21df930be7Sderaadt  * 4. The name of TooLs GmbH may not be used to endorse or promote products
22df930be7Sderaadt  *    derived from this software without specific prior written permission.
23df930be7Sderaadt  *
24df930be7Sderaadt  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
25df930be7Sderaadt  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26df930be7Sderaadt  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27df930be7Sderaadt  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28df930be7Sderaadt  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29df930be7Sderaadt  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
30df930be7Sderaadt  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31df930be7Sderaadt  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32df930be7Sderaadt  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
33df930be7Sderaadt  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34df930be7Sderaadt  */
35df930be7Sderaadt 
36df930be7Sderaadt #include <sys/param.h>
37df930be7Sderaadt #include <sys/systm.h>
38df930be7Sderaadt #include <sys/filedesc.h>
39df930be7Sderaadt #include <sys/proc.h>
40a2c764f6Sderaadt #include <sys/user.h>
41df930be7Sderaadt #include <sys/mount.h>
42df930be7Sderaadt #include <sys/malloc.h>
43dbe27ba0Stedu #include <sys/pool.h>
44df930be7Sderaadt #include <sys/namei.h>
45df930be7Sderaadt #include <sys/vnode.h>
464b1f64dcSguenther #include <sys/fcntl.h>
47df930be7Sderaadt #include <sys/file.h>
48df930be7Sderaadt #include <sys/acct.h>
49df930be7Sderaadt #include <sys/exec.h>
50682e3c94Sguenther #include <sys/exec_elf.h>
51df930be7Sderaadt #include <sys/ktrace.h>
52df930be7Sderaadt #include <sys/resourcevar.h>
53df930be7Sderaadt #include <sys/mman.h>
54df930be7Sderaadt #include <sys/signalvar.h>
55df930be7Sderaadt #include <sys/stat.h>
56faa48718Sart #include <sys/conf.h>
57df174574Sderaadt #include <sys/pledge.h>
585ac46f4aSniklas #ifdef SYSVSHM
595ac46f4aSniklas #include <sys/shm.h>
605ac46f4aSniklas #endif
61df930be7Sderaadt 
62df930be7Sderaadt #include <sys/syscallargs.h>
63df930be7Sderaadt 
64fde894e5Stedu #include <uvm/uvm_extern.h>
65c6319251Sguenther #include <machine/tcb.h>
66c6319251Sguenther 
67d82e6535Spirofti #include <sys/timetc.h>
68d82e6535Spirofti 
695a72e03eSguenther struct uvm_object *sigobject;		/* shared sigcode object */
7013f0bae7Skettenis vaddr_t sigcode_va;
7113f0bae7Skettenis vsize_t sigcode_sz;
72d82e6535Spirofti struct uvm_object *timekeep_object;
73d82e6535Spirofti struct timekeep *timekeep;
74d82e6535Spirofti 
758b23add8Sbeck void	unveil_destroy(struct process *ps);
768b23add8Sbeck 
77b324ced2Skettenis const struct kmem_va_mode kv_exec = {
78b324ced2Skettenis 	.kv_wait = 1,
79b324ced2Skettenis 	.kv_map = &exec_map
80b324ced2Skettenis };
81b324ced2Skettenis 
82586305f1Sart /*
834a5480feSart  * Map the shared signal code.
844a5480feSart  */
855a72e03eSguenther int exec_sigcode_map(struct process *);
864a5480feSart 
874a5480feSart /*
88d82e6535Spirofti  * Map the shared timekeep page.
89d82e6535Spirofti  */
90d82e6535Spirofti int exec_timekeep_map(struct process *);
91d82e6535Spirofti 
92d82e6535Spirofti /*
93b8736dc1Sderaadt  * If non-zero, stackgap_random specifies the upper limit of the random gap size
942bda40dcSmiod  * added to the fixed stack position. Must be n^2.
95586305f1Sart  */
96312d058fSderaadt int stackgap_random = STACKGAP_RANDOM;
97586305f1Sart 
98df930be7Sderaadt /*
99df930be7Sderaadt  * check exec:
100df930be7Sderaadt  * given an "executable" described in the exec package's namei info,
101df930be7Sderaadt  * see what we can do with it.
102df930be7Sderaadt  *
103df930be7Sderaadt  * ON ENTRY:
104df930be7Sderaadt  *	exec package with appropriate namei info
105df930be7Sderaadt  *	proc pointer of exec'ing proc
106df930be7Sderaadt  *	NO SELF-LOCKED VNODES
107df930be7Sderaadt  *
108df930be7Sderaadt  * ON EXIT:
109df930be7Sderaadt  *	error:	nothing held, etc.  exec header still allocated.
110df930be7Sderaadt  *	ok:	filled exec package, one locked vnode.
111df930be7Sderaadt  *
112df930be7Sderaadt  * EXEC SWITCH ENTRY:
113df930be7Sderaadt  * 	Locked vnode to check, exec package, proc.
114df930be7Sderaadt  *
115df930be7Sderaadt  * EXEC SWITCH EXIT:
116df930be7Sderaadt  *	ok:	return 0, filled exec package, one locked vnode.
117df930be7Sderaadt  *	error:	destructive:
118a3c911baSschwarze  *			everything deallocated except exec header.
119d84b7fccSmiod  *		non-destructive:
120df930be7Sderaadt  *			error code, locked vnode, exec header unmodified
121df930be7Sderaadt  */
122df930be7Sderaadt int
123158fb4f9Sjsg check_exec(struct proc *p, struct exec_package *epp)
124df930be7Sderaadt {
125df930be7Sderaadt 	int error, i;
126df930be7Sderaadt 	struct vnode *vp;
127df930be7Sderaadt 	struct nameidata *ndp;
1289b355cb2Smillert 	size_t resid;
129df930be7Sderaadt 
130df930be7Sderaadt 	ndp = epp->ep_ndp;
131df930be7Sderaadt 	ndp->ni_cnd.cn_nameiop = LOOKUP;
132df930be7Sderaadt 	ndp->ni_cnd.cn_flags = FOLLOW | LOCKLEAF | SAVENAME;
13362111f95Sderaadt 	if (epp->ep_flags & EXEC_INDIR)
13462111f95Sderaadt 		ndp->ni_cnd.cn_flags |= BYPASSUNVEIL;
135df930be7Sderaadt 	/* first get the vnode */
1365ac46f4aSniklas 	if ((error = namei(ndp)) != 0)
137bcfbf755Sniklas 		return (error);
138df930be7Sderaadt 	epp->ep_vp = vp = ndp->ni_vp;
139df930be7Sderaadt 
140df930be7Sderaadt 	/* check for regular file */
141df930be7Sderaadt 	if (vp->v_type != VREG) {
142df930be7Sderaadt 		error = EACCES;
143df930be7Sderaadt 		goto bad1;
144df930be7Sderaadt 	}
145df930be7Sderaadt 
146df930be7Sderaadt 	/* get attributes */
1475ac46f4aSniklas 	if ((error = VOP_GETATTR(vp, epp->ep_vap, p->p_ucred, p)) != 0)
148df930be7Sderaadt 		goto bad1;
149df930be7Sderaadt 
150df930be7Sderaadt 	/* Check mount point */
151df930be7Sderaadt 	if (vp->v_mount->mnt_flag & MNT_NOEXEC) {
152df930be7Sderaadt 		error = EACCES;
153df930be7Sderaadt 		goto bad1;
154df930be7Sderaadt 	}
155e55d0f86Sart 
1564ea7ed56Sderaadt 	/* SUID programs may not be started with execpromises */
1574ea7ed56Sderaadt 	if ((epp->ep_vap->va_mode & (VSUID | VSGID)) &&
1584ea7ed56Sderaadt 	    (p->p_p->ps_flags & PS_EXECPLEDGE)) {
1594ea7ed56Sderaadt 		error = EACCES;
1604ea7ed56Sderaadt 		goto bad1;
1614ea7ed56Sderaadt 	}
1624ea7ed56Sderaadt 
16351f754c1Sart 	if ((vp->v_mount->mnt_flag & MNT_NOSUID))
16451f754c1Sart 		epp->ep_vap->va_mode &= ~(VSUID | VSGID);
165bfa108a0Sderaadt 
166df930be7Sderaadt 	/* check access.  for root we have to see if any exec bit on */
1675ac46f4aSniklas 	if ((error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p)) != 0)
168df930be7Sderaadt 		goto bad1;
169df930be7Sderaadt 	if ((epp->ep_vap->va_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0) {
170df930be7Sderaadt 		error = EACCES;
171df930be7Sderaadt 		goto bad1;
172df930be7Sderaadt 	}
173df930be7Sderaadt 
174df930be7Sderaadt 	/* try to open it */
1755ac46f4aSniklas 	if ((error = VOP_OPEN(vp, FREAD, p->p_ucred, p)) != 0)
176df930be7Sderaadt 		goto bad1;
177df930be7Sderaadt 
178d84dbf2eSart 	/* unlock vp, we need it unlocked from here */
17936bb23f1Svisa 	VOP_UNLOCK(vp);
180d84dbf2eSart 
181df930be7Sderaadt 	/* now we have the file, get the exec header */
1825ac46f4aSniklas 	error = vn_rdwr(UIO_READ, vp, epp->ep_hdr, epp->ep_hdrlen, 0,
183d84dbf2eSart 	    UIO_SYSSPACE, 0, p->p_ucred, &resid, p);
1845ac46f4aSniklas 	if (error)
185df930be7Sderaadt 		goto bad2;
186df930be7Sderaadt 	epp->ep_hdrvalid = epp->ep_hdrlen - resid;
187df930be7Sderaadt 
188df930be7Sderaadt 	/*
189df930be7Sderaadt 	 * set up the vmcmds for creation of the process
190df930be7Sderaadt 	 * address space
191df930be7Sderaadt 	 */
192df930be7Sderaadt 	error = ENOEXEC;
193df930be7Sderaadt 	for (i = 0; i < nexecs && error != 0; i++) {
194df930be7Sderaadt 		int newerror;
195df930be7Sderaadt 
196df930be7Sderaadt 		if (execsw[i].es_check == NULL)
197df930be7Sderaadt 			continue;
198df930be7Sderaadt 		newerror = (*execsw[i].es_check)(p, epp);
199df930be7Sderaadt 		/* make sure the first "interesting" error code is saved. */
200df930be7Sderaadt 		if (!newerror || error == ENOEXEC)
201df930be7Sderaadt 			error = newerror;
202df930be7Sderaadt 		if (epp->ep_flags & EXEC_DESTR && error != 0)
203bcfbf755Sniklas 			return (error);
204df930be7Sderaadt 	}
205df930be7Sderaadt 	if (!error) {
206df930be7Sderaadt 		/* check that entry point is sane */
207ab30c277Spefo 		if (epp->ep_entry > VM_MAXUSER_ADDRESS) {
208df930be7Sderaadt 			error = ENOEXEC;
209ab30c277Spefo 		}
210df930be7Sderaadt 
211df930be7Sderaadt 		/* check limits */
212df930be7Sderaadt 		if ((epp->ep_tsize > MAXTSIZ) ||
213edc99bcdSvisa 		    (epp->ep_dsize > lim_cur(RLIMIT_DATA)))
214df930be7Sderaadt 			error = ENOMEM;
215df930be7Sderaadt 
216df930be7Sderaadt 		if (!error)
217df930be7Sderaadt 			return (0);
218df930be7Sderaadt 	}
219df930be7Sderaadt 
220df930be7Sderaadt 	/*
221df930be7Sderaadt 	 * free any vmspace-creation commands,
222df930be7Sderaadt 	 * and release their references
223df930be7Sderaadt 	 */
224df930be7Sderaadt 	kill_vmcmds(&epp->ep_vmcmds);
225df930be7Sderaadt 
226df930be7Sderaadt bad2:
227df930be7Sderaadt 	/*
228d84dbf2eSart 	 * close the vnode, free the pathname buf, and punt.
229df930be7Sderaadt 	 */
230df930be7Sderaadt 	vn_close(vp, FREAD, p->p_ucred, p);
231dbe27ba0Stedu 	pool_put(&namei_pool, ndp->ni_cnd.cn_pnbuf);
232bcfbf755Sniklas 	return (error);
233df930be7Sderaadt 
234df930be7Sderaadt bad1:
235df930be7Sderaadt 	/*
236df930be7Sderaadt 	 * free the namei pathname buffer, and put the vnode
237df930be7Sderaadt 	 * (which we don't yet have open).
238df930be7Sderaadt 	 */
239dbe27ba0Stedu 	pool_put(&namei_pool, ndp->ni_cnd.cn_pnbuf);
240df930be7Sderaadt 	vput(vp);
241bcfbf755Sniklas 	return (error);
242df930be7Sderaadt }
243df930be7Sderaadt 
244df930be7Sderaadt /*
245df930be7Sderaadt  * exec system call
246df930be7Sderaadt  */
2475ac46f4aSniklas int
248158fb4f9Sjsg sys_execve(struct proc *p, void *v, register_t *retval)
249df930be7Sderaadt {
250586305f1Sart 	struct sys_execve_args /* {
25101b77f95Shenning 		syscallarg(const char *) path;
25201b77f95Shenning 		syscallarg(char *const *) argp;
25301b77f95Shenning 		syscallarg(char *const *) envp;
254df930be7Sderaadt 	} */ *uap = v;
255e20a449dStedu 	int error;
256df930be7Sderaadt 	struct exec_package pack;
257df930be7Sderaadt 	struct nameidata nid;
258df930be7Sderaadt 	struct vattr attr;
259df930be7Sderaadt 	struct ucred *cred = p->p_ucred;
260df930be7Sderaadt 	char *argp;
261d8434bb1Stholo 	char * const *cpp, *dp, *sp;
2625e0c3889Sguenther #ifdef KTRACE
2635e0c3889Sguenther 	char *env_start;
2645e0c3889Sguenther #endif
265bfb8af8fSguenther 	struct process *pr = p->p_p;
266df930be7Sderaadt 	long argc, envc;
2670233b312Sflorian 	size_t len, sgap, dstsize;
268cc576edfSmickey #ifdef MACHINE_STACK_GROWS_UP
269cc576edfSmickey 	size_t slen;
270cc576edfSmickey #endif
271df930be7Sderaadt 	char *stack;
272df930be7Sderaadt 	struct ps_strings arginfo;
273a2c764f6Sderaadt 	struct vmspace *vm = p->p_vmspace;
2747359b57aStedu 	struct vnode *otvp;
275df930be7Sderaadt 
27614835c38Sclaudio 	/*
27714835c38Sclaudio 	 * Get other threads to stop, if contested return ERESTART,
27814835c38Sclaudio 	 * so the syscall is restarted after halting in userret.
27914835c38Sclaudio 	 */
28014835c38Sclaudio 	if (single_thread_set(p, SINGLE_UNWIND | SINGLE_DEEP))
28114835c38Sclaudio 		return (ERESTART);
2822ea51a70Sguenther 
283df930be7Sderaadt 	/*
284d5f75ac0Sart 	 * Cheap solution to complicated problems.
285d5f75ac0Sart 	 * Mark this process as "leave me alone, I'm execing".
286d5f75ac0Sart 	 */
2876b6f3ef9Sguenther 	atomic_setbits_int(&pr->ps_flags, PS_INEXEC);
288d5f75ac0Sart 
28945573b1fSkettenis 	NDINIT(&nid, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
290345a92b4Ssemarie 	nid.ni_pledge = PLEDGE_EXEC;
291e1a6e226Sbeck 	nid.ni_unveil = UNVEIL_EXEC;
292df930be7Sderaadt 
293df930be7Sderaadt 	/*
294df930be7Sderaadt 	 * initialize the fields of the exec package.
295df930be7Sderaadt 	 */
296d8434bb1Stholo 	pack.ep_name = (char *)SCARG(uap, path);
297176819c2Sart 	pack.ep_hdr = malloc(exec_maxhdrsz, M_EXEC, M_WAITOK);
298df930be7Sderaadt 	pack.ep_hdrlen = exec_maxhdrsz;
299df930be7Sderaadt 	pack.ep_hdrvalid = 0;
300df930be7Sderaadt 	pack.ep_ndp = &nid;
301c0c22b04Stedu 	pack.ep_interp = NULL;
302682e3c94Sguenther 	pack.ep_args = NULL;
303682e3c94Sguenther 	pack.ep_auxinfo = NULL;
3041bdf816eSart 	VMCMDSET_INIT(&pack.ep_vmcmds);
305df930be7Sderaadt 	pack.ep_vap = &attr;
306df930be7Sderaadt 	pack.ep_flags = 0;
307f0efa6a8Sderaadt 	pack.ep_pins = NULL;
308f0efa6a8Sderaadt 	pack.ep_npins = 0;
309df930be7Sderaadt 
310df930be7Sderaadt 	/* see if we can run it. */
311ab30c277Spefo 	if ((error = check_exec(p, &pack)) != 0) {
312df930be7Sderaadt 		goto freehdr;
313ab30c277Spefo 	}
314df930be7Sderaadt 
315df930be7Sderaadt 	/* XXX -- THE FOLLOWING SECTION NEEDS MAJOR CLEANUP */
316df930be7Sderaadt 
317df930be7Sderaadt 	/* allocate an argument buffer */
318b324ced2Skettenis 	argp = km_alloc(NCARGS, &kv_exec, &kp_pageable, &kd_waitok);
319df930be7Sderaadt #ifdef DIAGNOSTIC
320b5099d50Snordin 	if (argp == NULL)
321df930be7Sderaadt 		panic("execve: argp == NULL");
322df930be7Sderaadt #endif
323df930be7Sderaadt 	dp = argp;
324df930be7Sderaadt 	argc = 0;
325df930be7Sderaadt 
3260233b312Sflorian 	/*
3270233b312Sflorian 	 * Copy the fake args list, if there's one, freeing it as we go.
3280233b312Sflorian 	 * exec_script_makecmds() allocates either 2 or 3 fake args bounded
3290233b312Sflorian 	 * by MAXINTERP + MAXPATHLEN < NCARGS so no overflow can happen.
3300233b312Sflorian 	 */
331df930be7Sderaadt 	if (pack.ep_flags & EXEC_HASARGL) {
3320233b312Sflorian 		dstsize = NCARGS;
3330233b312Sflorian 		for(; pack.ep_fa[argc] != NULL; argc++) {
3340233b312Sflorian 			len = strlcpy(dp, pack.ep_fa[argc], dstsize);
3350233b312Sflorian 			len++;
3360233b312Sflorian 			dp += len; dstsize -= len;
3370233b312Sflorian 			if (pack.ep_fa[argc+1] != NULL)
3380233b312Sflorian 				free(pack.ep_fa[argc], M_EXEC, len);
3390233b312Sflorian 			else
3400233b312Sflorian 				free(pack.ep_fa[argc], M_EXEC, MAXPATHLEN);
341df930be7Sderaadt 		}
3420233b312Sflorian 		free(pack.ep_fa, M_EXEC, 4 * sizeof(char *));
343df930be7Sderaadt 		pack.ep_flags &= ~EXEC_HASARGL;
344df930be7Sderaadt 	}
345df930be7Sderaadt 
346df930be7Sderaadt 	/* Now get argv & environment */
347df930be7Sderaadt 	if (!(cpp = SCARG(uap, argp))) {
348a5ceb13eSmickey 		error = EFAULT;
349df930be7Sderaadt 		goto bad;
350df930be7Sderaadt 	}
351df930be7Sderaadt 
352df930be7Sderaadt 	if (pack.ep_flags & EXEC_SKIPARG)
353df930be7Sderaadt 		cpp++;
354df930be7Sderaadt 
355df930be7Sderaadt 	while (1) {
356df930be7Sderaadt 		len = argp + ARG_MAX - dp;
3575ac46f4aSniklas 		if ((error = copyin(cpp, &sp, sizeof(sp))) != 0)
358df930be7Sderaadt 			goto bad;
359df930be7Sderaadt 		if (!sp)
360df930be7Sderaadt 			break;
3615ac46f4aSniklas 		if ((error = copyinstr(sp, dp, len, &len)) != 0) {
362df930be7Sderaadt 			if (error == ENAMETOOLONG)
363df930be7Sderaadt 				error = E2BIG;
364df930be7Sderaadt 			goto bad;
365df930be7Sderaadt 		}
366df930be7Sderaadt 		dp += len;
367df930be7Sderaadt 		cpp++;
368df930be7Sderaadt 		argc++;
369df930be7Sderaadt 	}
370df930be7Sderaadt 
37174212563Stedu 	/* must have at least one argument */
37274212563Stedu 	if (argc == 0) {
37374212563Stedu 		error = EINVAL;
37474212563Stedu 		goto bad;
37574212563Stedu 	}
37674212563Stedu 
3775e0c3889Sguenther #ifdef KTRACE
3785e0c3889Sguenther 	if (KTRPOINT(p, KTR_EXECARGS))
3795e0c3889Sguenther 		ktrexec(p, KTR_EXECARGS, argp, dp - argp);
3805e0c3889Sguenther #endif
3815e0c3889Sguenther 
382df930be7Sderaadt 	envc = 0;
383507f831cSmickey 	/* environment does not need to be there */
3845ac46f4aSniklas 	if ((cpp = SCARG(uap, envp)) != NULL ) {
3855e0c3889Sguenther #ifdef KTRACE
3865e0c3889Sguenther 		env_start = dp;
3875e0c3889Sguenther #endif
388df930be7Sderaadt 		while (1) {
389df930be7Sderaadt 			len = argp + ARG_MAX - dp;
3905ac46f4aSniklas 			if ((error = copyin(cpp, &sp, sizeof(sp))) != 0)
391df930be7Sderaadt 				goto bad;
392df930be7Sderaadt 			if (!sp)
393df930be7Sderaadt 				break;
3945ac46f4aSniklas 			if ((error = copyinstr(sp, dp, len, &len)) != 0) {
395df930be7Sderaadt 				if (error == ENAMETOOLONG)
396df930be7Sderaadt 					error = E2BIG;
397df930be7Sderaadt 				goto bad;
398df930be7Sderaadt 			}
399df930be7Sderaadt 			dp += len;
400df930be7Sderaadt 			cpp++;
401df930be7Sderaadt 			envc++;
402df930be7Sderaadt 		}
4035e0c3889Sguenther 
4045e0c3889Sguenther #ifdef KTRACE
4055e0c3889Sguenther 		if (KTRPOINT(p, KTR_EXECENV))
4065e0c3889Sguenther 			ktrexec(p, KTR_EXECENV, env_start, dp - env_start);
4075e0c3889Sguenther #endif
408df930be7Sderaadt 	}
409df930be7Sderaadt 
410b8736dc1Sderaadt 	dp = (char *)(((long)dp + _STACKALIGNBYTES) & ~_STACKALIGNBYTES);
411df930be7Sderaadt 
4122bda40dcSmiod 	/*
4132bda40dcSmiod 	 * If we have enabled random stackgap, the stack itself has already
4142bda40dcSmiod 	 * been moved from a random location, but is still aligned to a page
4152bda40dcSmiod 	 * boundary.  Provide the lower bits of random placement now.
4162bda40dcSmiod 	 */
4172f033923Sguenther 	if (stackgap_random == 0) {
4182f033923Sguenther 		sgap = 0;
4192f033923Sguenther 	} else {
4202f033923Sguenther 		sgap = arc4random() & PAGE_MASK;
421b8736dc1Sderaadt 		sgap = (sgap + _STACKALIGNBYTES) & ~_STACKALIGNBYTES;
422b8736dc1Sderaadt 	}
423b8736dc1Sderaadt 
424df930be7Sderaadt 	/* Now check if args & environ fit into new stack */
425b702d795Sguenther 	len = ((argc + envc + 2 + ELF_AUX_WORDS) * sizeof(char *) +
4264a5480feSart 	    sizeof(long) + dp + sgap + sizeof(struct ps_strings)) - argp;
427df930be7Sderaadt 
428b8736dc1Sderaadt 	len = (len + _STACKALIGNBYTES) &~ _STACKALIGNBYTES;
429df930be7Sderaadt 
430df930be7Sderaadt 	if (len > pack.ep_ssize) { /* in effect, compare to initial limit */
431df930be7Sderaadt 		error = ENOMEM;
432df930be7Sderaadt 		goto bad;
433df930be7Sderaadt 	}
434df930be7Sderaadt 
435df930be7Sderaadt 	/* adjust "active stack depth" for process VSZ */
436df930be7Sderaadt 	pack.ep_ssize = len;	/* maybe should go elsewhere, but... */
437df930be7Sderaadt 
43886607369Sart 	/*
4392ea51a70Sguenther 	 * we're committed: any further errors will kill the process, so
4402ea51a70Sguenther 	 * kill the other threads now.
4412ea51a70Sguenther 	 */
442a556b217Sclaudio 	single_thread_set(p, SINGLE_EXIT);
4432ea51a70Sguenther 
4442ea51a70Sguenther 	/*
44586607369Sart 	 * Prepare vmspace for remapping. Note that uvmspace_exec can replace
446a9872addSguenther 	 * ps_vmspace!
44786607369Sart 	 */
448cac1bff1Sart 	uvmspace_exec(p, VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS);
449df930be7Sderaadt 
450924be113Sguenther 	vm = pr->ps_vmspace;
451df930be7Sderaadt 	/* Now map address space */
452ff3fdef1Skettenis 	vm->vm_taddr = (char *)trunc_page(pack.ep_taddr);
453ff3fdef1Skettenis 	vm->vm_tsize = atop(round_page(pack.ep_taddr + pack.ep_tsize) -
454ff3fdef1Skettenis 	    trunc_page(pack.ep_taddr));
455ff3fdef1Skettenis 	vm->vm_daddr = (char *)trunc_page(pack.ep_daddr);
456ff3fdef1Skettenis 	vm->vm_dsize = atop(round_page(pack.ep_daddr + pack.ep_dsize) -
457ff3fdef1Skettenis 	    trunc_page(pack.ep_daddr));
4580ebeee85Sderaadt 	vm->vm_dused = 0;
45976d52da2Smartin 	vm->vm_ssize = atop(round_page(pack.ep_ssize));
460df930be7Sderaadt 	vm->vm_maxsaddr = (char *)pack.ep_maxsaddr;
461d9040bf8Smickey 	vm->vm_minsaddr = (char *)pack.ep_minsaddr;
462df930be7Sderaadt 
463df930be7Sderaadt 	/* create the new process's VM space by running the vmcmds */
464df930be7Sderaadt #ifdef DIAGNOSTIC
465df930be7Sderaadt 	if (pack.ep_vmcmds.evs_used == 0)
466df930be7Sderaadt 		panic("execve: no vmcmds");
467df930be7Sderaadt #endif
4681e04e351Sart 	error = exec_process_vmcmds(p, &pack);
469df930be7Sderaadt 
470df930be7Sderaadt 	/* if an error happened, deallocate and punt */
471df930be7Sderaadt 	if (error)
472df930be7Sderaadt 		goto exec_abort;
473df930be7Sderaadt 
47456b6d613Skettenis #ifdef MACHINE_STACK_GROWS_UP
4757180d9eaSmiod 	pr->ps_strings = (vaddr_t)vm->vm_maxsaddr + sgap;
47656b6d613Skettenis         if (uvm_map_protect(&vm->vm_map, (vaddr_t)vm->vm_maxsaddr,
4774c8ae43bSderaadt             trunc_page(pr->ps_strings), PROT_NONE, 0, TRUE, FALSE))
47856b6d613Skettenis                 goto exec_abort;
47956b6d613Skettenis #else
4807180d9eaSmiod 	pr->ps_strings = (vaddr_t)vm->vm_minsaddr - sizeof(arginfo) - sgap;
48156b6d613Skettenis         if (uvm_map_protect(&vm->vm_map,
48256b6d613Skettenis             round_page(pr->ps_strings + sizeof(arginfo)),
4834c8ae43bSderaadt             (vaddr_t)vm->vm_minsaddr, PROT_NONE, 0, TRUE, FALSE))
48456b6d613Skettenis                 goto exec_abort;
48556b6d613Skettenis #endif
48656b6d613Skettenis 
4876c87c9e2Sbluhm 	memset(&arginfo, 0, sizeof(arginfo));
4886c87c9e2Sbluhm 
489df930be7Sderaadt 	/* remember information about the process */
490df930be7Sderaadt 	arginfo.ps_nargvstr = argc;
491df930be7Sderaadt 	arginfo.ps_nenvstr = envc;
492df930be7Sderaadt 
493910e6419Smickey #ifdef MACHINE_STACK_GROWS_UP
4947180d9eaSmiod 	stack = (char *)vm->vm_maxsaddr + sizeof(arginfo) + sgap;
495f18df0c5Skettenis 	slen = len - sizeof(arginfo) - sgap;
496910e6419Smickey #else
4977180d9eaSmiod 	stack = (char *)(vm->vm_minsaddr - len);
498910e6419Smickey #endif
499df930be7Sderaadt 	/* Now copy argc, args & environ to new stack */
500682e3c94Sguenther 	if (!copyargs(&pack, &arginfo, stack, argp))
501df930be7Sderaadt 		goto exec_abort;
502df930be7Sderaadt 
5034ec5462fSmbuhl 	pr->ps_auxinfo = (vaddr_t)pack.ep_auxinfo;
5044ec5462fSmbuhl 
505df930be7Sderaadt 	/* copy out the process's ps_strings structure */
506a78264c4Skettenis 	if (copyout(&arginfo, (char *)pr->ps_strings, sizeof(arginfo)))
507df930be7Sderaadt 		goto exec_abort;
508df930be7Sderaadt 
509f0efa6a8Sderaadt 	free(pr->ps_pin.pn_pins, M_PINSYSCALL,
510f0efa6a8Sderaadt 	    pr->ps_pin.pn_npins * sizeof(u_int));
511f0efa6a8Sderaadt 	if (pack.ep_npins) {
512f0efa6a8Sderaadt 		pr->ps_pin.pn_start = pack.ep_pinstart;
513f0efa6a8Sderaadt 		pr->ps_pin.pn_end = pack.ep_pinend;
514f0efa6a8Sderaadt 		pr->ps_pin.pn_pins = pack.ep_pins;
515f0efa6a8Sderaadt 		pack.ep_pins = NULL;
516f0efa6a8Sderaadt 		pr->ps_pin.pn_npins = pack.ep_npins;
517f0efa6a8Sderaadt 	} else {
518f0efa6a8Sderaadt 		pr->ps_pin.pn_start = pr->ps_pin.pn_end = 0;
519f0efa6a8Sderaadt 		pr->ps_pin.pn_pins = NULL;
520f0efa6a8Sderaadt 		pr->ps_pin.pn_npins = 0;
521f0efa6a8Sderaadt 	}
522f0efa6a8Sderaadt 	if (pr->ps_libcpin.pn_pins) {
523f0efa6a8Sderaadt 		free(pr->ps_libcpin.pn_pins, M_PINSYSCALL,
524f0efa6a8Sderaadt 		    pr->ps_libcpin.pn_npins * sizeof(u_int));
525f0efa6a8Sderaadt 		pr->ps_libcpin.pn_start = pr->ps_libcpin.pn_end = 0;
526f0efa6a8Sderaadt 		pr->ps_libcpin.pn_pins = NULL;
527f0efa6a8Sderaadt 		pr->ps_libcpin.pn_npins = 0;
528f0efa6a8Sderaadt 	}
529f0efa6a8Sderaadt 
53018914fdfSguenther 	stopprofclock(pr);	/* stop profiling */
531df930be7Sderaadt 	fdcloseexec(p);		/* handle close on exec */
532611924b3Smiod 	execsigs(p);		/* reset caught signals */
533c6319251Sguenther 	TCB_SET(p, NULL);	/* reset the TCB address */
534440e6fe6Sguenther 	pr->ps_kbind_addr = 0;	/* reset the kbind bits */
535440e6fe6Sguenther 	pr->ps_kbind_cookie = 0;
5367730d1d9Sderaadt 	arc4random_buf(&pr->ps_sigcookie, sizeof pr->ps_sigcookie);
537df930be7Sderaadt 
538df930be7Sderaadt 	/* set command name & other accounting info */
5398fda72b7Sguenther 	memset(pr->ps_comm, 0, sizeof(pr->ps_comm));
540633fc60bSderaadt 	strlcpy(pr->ps_comm, nid.ni_cnd.cn_nameptr, sizeof(pr->ps_comm));
5410839b846Smikeb 	pr->ps_acflag &= ~AFORK;
542df930be7Sderaadt 
543cf6677a6Sguenther 	/* record proc's vnode, for use by sysctl */
5444ab8ed70Sguenther 	otvp = pr->ps_textvp;
545627b2c48Sthib 	vref(pack.ep_vp);
5464ab8ed70Sguenther 	pr->ps_textvp = pack.ep_vp;
5477359b57aStedu 	if (otvp)
5487359b57aStedu 		vrele(otvp);
549df930be7Sderaadt 
550a8701c59Sguenther 	if (pack.ep_flags & EXEC_NOBTCFI)
551a8701c59Sguenther 		atomic_setbits_int(&p->p_p->ps_flags, PS_NOBTCFI);
552a8701c59Sguenther 	else
553a8701c59Sguenther 		atomic_clearbits_int(&p->p_p->ps_flags, PS_NOBTCFI);
554a8701c59Sguenther 
555e2590abeSguenther 	atomic_setbits_int(&pr->ps_flags, PS_EXEC);
556c0ce47d9Sguenther 	if (pr->ps_flags & PS_PPWAIT) {
557c0ce47d9Sguenther 		atomic_clearbits_int(&pr->ps_flags, PS_PPWAIT);
558c0ce47d9Sguenther 		atomic_clearbits_int(&pr->ps_pptr->ps_flags, PS_ISPWAIT);
559bfb8af8fSguenther 		wakeup(pr->ps_pptr);
560df930be7Sderaadt 	}
561df930be7Sderaadt 
562df930be7Sderaadt 	/*
563855755d9Smillert 	 * If process does execve() while it has a mismatched real,
564bfb8af8fSguenther 	 * effective, or saved uid/gid, we set PS_SUGIDEXEC.
56525b40de6Sderaadt 	 */
566d559b8cbSguenther 	if (cred->cr_uid != cred->cr_ruid ||
567d559b8cbSguenther 	    cred->cr_uid != cred->cr_svuid ||
568d559b8cbSguenther 	    cred->cr_gid != cred->cr_rgid ||
569d559b8cbSguenther 	    cred->cr_gid != cred->cr_svgid)
570bfb8af8fSguenther 		atomic_setbits_int(&pr->ps_flags, PS_SUGIDEXEC);
571855755d9Smillert 	else
572bfb8af8fSguenther 		atomic_clearbits_int(&pr->ps_flags, PS_SUGIDEXEC);
57325b40de6Sderaadt 
5744ea7ed56Sderaadt 	if (pr->ps_flags & PS_EXECPLEDGE) {
5754ea7ed56Sderaadt 		pr->ps_pledge = pr->ps_execpledge;
5764ea7ed56Sderaadt 		atomic_setbits_int(&pr->ps_flags, PS_PLEDGE);
5774ea7ed56Sderaadt 	} else {
578df174574Sderaadt 		atomic_clearbits_int(&pr->ps_flags, PS_PLEDGE);
5794ea7ed56Sderaadt 		pr->ps_pledge = 0;
5808b23add8Sbeck 		/* XXX XXX XXX XXX */
5818b23add8Sbeck 		/* Clear our unveil paths out so the child
5828b23add8Sbeck 		 * starts afresh
5838b23add8Sbeck 		 */
5848b23add8Sbeck 		unveil_destroy(pr);
5858b23add8Sbeck 		pr->ps_uvdone = 0;
5864ea7ed56Sderaadt 	}
587609289baSderaadt 
58825b40de6Sderaadt 	/*
589df930be7Sderaadt 	 * deal with set[ug]id.
59051f754c1Sart 	 * MNT_NOEXEC has already been used to disable s[ug]id.
591df930be7Sderaadt 	 */
59251f754c1Sart 	if ((attr.va_mode & (VSUID | VSGID)) && proc_cansugid(p)) {
593bbf7a176Sderaadt 		int i;
594bbf7a176Sderaadt 
595bfb8af8fSguenther 		atomic_setbits_int(&pr->ps_flags, PS_SUGID|PS_SUGIDEXEC);
59651f754c1Sart 
597df930be7Sderaadt #ifdef KTRACE
598df930be7Sderaadt 		/*
599df930be7Sderaadt 		 * If process is being ktraced, turn off - unless
600df930be7Sderaadt 		 * root set it.
601df930be7Sderaadt 		 */
602a2e04e14Sguenther 		if (pr->ps_tracevp && !(pr->ps_traceflag & KTRFAC_ROOT))
603a2e04e14Sguenther 			ktrcleartrace(pr);
604df930be7Sderaadt #endif
605d559b8cbSguenther 		p->p_ucred = cred = crcopy(cred);
606df930be7Sderaadt 		if (attr.va_mode & VSUID)
607d559b8cbSguenther 			cred->cr_uid = attr.va_uid;
608df930be7Sderaadt 		if (attr.va_mode & VSGID)
609d559b8cbSguenther 			cred->cr_gid = attr.va_gid;
610bbf7a176Sderaadt 
611bbf7a176Sderaadt 		/*
612bba8c139Sderaadt 		 * For set[ug]id processes, a few caveats apply to
613bba8c139Sderaadt 		 * stdin, stdout, and stderr.
614bbf7a176Sderaadt 		 */
615638f0017Sguenther 		error = 0;
616638f0017Sguenther 		fdplock(p->p_fd);
617bbf7a176Sderaadt 		for (i = 0; i < 3; i++) {
618c3315ca6Sderaadt 			struct file *fp = NULL;
619c3315ca6Sderaadt 
620af97e5cfSart 			/*
621af97e5cfSart 			 * NOTE - This will never return NULL because of
6222addf348Sjmc 			 * immature fds. The file descriptor table is not
623af97e5cfSart 			 * shared because we're suid.
624af97e5cfSart 			 */
625af97e5cfSart 			fp = fd_getfile(p->p_fd, i);
626c3315ca6Sderaadt 
627c3315ca6Sderaadt 			/*
628c3315ca6Sderaadt 			 * Ensure that stdin, stdout, and stderr are already
629c3315ca6Sderaadt 			 * allocated.  We do not want userland to accidentally
630c3315ca6Sderaadt 			 * allocate descriptors in this range which has implied
631c3315ca6Sderaadt 			 * meaning to libc.
632c3315ca6Sderaadt 			 */
633c3315ca6Sderaadt 			if (fp == NULL) {
634c3315ca6Sderaadt 				short flags = FREAD | (i == 0 ? 0 : FWRITE);
635faa48718Sart 				struct vnode *vp;
636bbf7a176Sderaadt 				int indx;
63758d9451eSart 
638cd6537e7Smpi 				if ((error = falloc(p, &fp, &indx)) != 0)
639638f0017Sguenther 					break;
640faa48718Sart #ifdef DIAGNOSTIC
641faa48718Sart 				if (indx != i)
642faa48718Sart 					panic("sys_execve: falloc indx != i");
643faa48718Sart #endif
644faa48718Sart 				if ((error = cdevvp(getnulldev(), &vp)) != 0) {
645bb720fc6Sprovos 					fdremove(p->p_fd, indx);
64643c6a78bSart 					closef(fp, p);
647638f0017Sguenther 					break;
648bbf7a176Sderaadt 				}
649d559b8cbSguenther 				if ((error = VOP_OPEN(vp, flags, cred, p)) != 0) {
650faa48718Sart 					fdremove(p->p_fd, indx);
65143c6a78bSart 					closef(fp, p);
652faa48718Sart 					vrele(vp);
653638f0017Sguenther 					break;
654faa48718Sart 				}
655faa48718Sart 				if (flags & FWRITE)
656faa48718Sart 					vp->v_writecount++;
65758d9451eSart 				fp->f_flag = flags;
658bbf7a176Sderaadt 				fp->f_type = DTYPE_VNODE;
659bbf7a176Sderaadt 				fp->f_ops = &vnops;
660faa48718Sart 				fp->f_data = (caddr_t)vp;
661cd6537e7Smpi 				fdinsert(p->p_fd, indx, 0, fp);
662bbf7a176Sderaadt 			}
663cd6537e7Smpi 			FRELE(fp, p);
664f695adb7Smpi 		}
665638f0017Sguenther 		fdpunlock(p->p_fd);
666638f0017Sguenther 		if (error)
667638f0017Sguenther 			goto exec_abort;
66825b40de6Sderaadt 	} else
669bfb8af8fSguenther 		atomic_clearbits_int(&pr->ps_flags, PS_SUGID);
670d559b8cbSguenther 
671a9ddc286Sguenther 	/*
672a9ddc286Sguenther 	 * Reset the saved ugids and update the process's copy of the
673a9ddc286Sguenther 	 * creds if the creds have been changed
674a9ddc286Sguenther 	 */
675d559b8cbSguenther 	if (cred->cr_uid != cred->cr_svuid ||
676d559b8cbSguenther 	    cred->cr_gid != cred->cr_svgid) {
677d559b8cbSguenther 		/* make sure we have unshared ucreds */
678d559b8cbSguenther 		p->p_ucred = cred = crcopy(cred);
679d559b8cbSguenther 		cred->cr_svuid = cred->cr_uid;
680d559b8cbSguenther 		cred->cr_svgid = cred->cr_gid;
681d559b8cbSguenther 	}
682df930be7Sderaadt 
683a9ddc286Sguenther 	if (pr->ps_ucred != cred) {
684a9ddc286Sguenther 		struct ucred *ocred;
685a9ddc286Sguenther 
686a9ddc286Sguenther 		ocred = pr->ps_ucred;
687a9ddc286Sguenther 		crhold(cred);
688a9ddc286Sguenther 		pr->ps_ucred = cred;
689a9ddc286Sguenther 		crfree(ocred);
690a9ddc286Sguenther 	}
691a9ddc286Sguenther 
692bfb8af8fSguenther 	if (pr->ps_flags & PS_SUGIDEXEC) {
693ae96cbdaScheloha 		cancel_all_itimers();
69421b2622bSderaadt 	}
69521b2622bSderaadt 
6967b36c281Sguenther 	/* reset CPU time usage for the thread, but not the process */
6977b36c281Sguenther 	timespecclear(&p->p_tu.tu_runtime);
6987b36c281Sguenther 	p->p_tu.tu_uticks = p->p_tu.tu_sticks = p->p_tu.tu_iticks = 0;
699241d6723Sclaudio 	p->p_tu.tu_gen = 0;
7007b36c281Sguenther 
701cef5a146Sguenther 	memset(p->p_name, 0, sizeof p->p_name);
702cef5a146Sguenther 
703b324ced2Skettenis 	km_free(argp, NCARGS, &kv_exec, &kp_pageable);
704df930be7Sderaadt 
705dbe27ba0Stedu 	pool_put(&namei_pool, nid.ni_cnd.cn_pnbuf);
706d84dbf2eSart 	vn_close(pack.ep_vp, FREAD, cred, p);
707df930be7Sderaadt 
7081a12e8a7Sprovos 	/*
7091a12e8a7Sprovos 	 * notify others that we exec'd
7101a12e8a7Sprovos 	 */
7110747e3d2Sclaudio 	knote(&pr->ps_klist, NOTE_EXEC);
7121a12e8a7Sprovos 
7134ed6f7c2Sguenther 	/* map the process's timekeep page, needs to be before exec_elf_fixup */
714d82e6535Spirofti 	if (exec_timekeep_map(pr))
715d82e6535Spirofti 		goto free_pack_abort;
716d82e6535Spirofti 
717df930be7Sderaadt 	/* setup new registers and do misc. setup. */
7184ed6f7c2Sguenther 	if (exec_elf_fixup(p, &pack) != 0)
719ab30c277Spefo 		goto free_pack_abort;
720910e6419Smickey #ifdef MACHINE_STACK_GROWS_UP
7211b4a394fSguenther 	setregs(p, &pack, (u_long)stack + slen, &arginfo);
722910e6419Smickey #else
7231b4a394fSguenther 	setregs(p, &pack, (u_long)stack, &arginfo);
724910e6419Smickey #endif
725df930be7Sderaadt 
7264a5480feSart 	/* map the process's signal trampoline code */
7275a72e03eSguenther 	if (exec_sigcode_map(pr))
728c0c22b04Stedu 		goto free_pack_abort;
7294a5480feSart 
7304c0d1b1bSmiod #ifdef __HAVE_EXEC_MD_MAP
7314c0d1b1bSmiod 	/* perform md specific mappings that process might need */
7324c0d1b1bSmiod 	if (exec_md_map(p, &pack))
7334c0d1b1bSmiod 		goto free_pack_abort;
7344c0d1b1bSmiod #endif
7354c0d1b1bSmiod 
7366b6f3ef9Sguenther 	if (pr->ps_flags & PS_TRACED)
737df930be7Sderaadt 		psignal(p, SIGTRAP);
738df930be7Sderaadt 
7397da957a5Sderaadt 	free(pack.ep_hdr, M_EXEC, pack.ep_hdrlen);
740df930be7Sderaadt 
741d9f343eeSderaadt 	p->p_descfd = 255;
742d9f343eeSderaadt 	if ((pack.ep_flags & EXEC_HASFD) && pack.ep_fd < 255)
743d9f343eeSderaadt 		p->p_descfd = pack.ep_fd;
744d9f343eeSderaadt 
745f68ce565Sderaadt 	if (pack.ep_flags & EXEC_WXNEEDED)
7469648c32bSanton 		atomic_setbits_int(&p->p_p->ps_flags, PS_WXNEEDED);
747131b88b7Sjca 	else
7489648c32bSanton 		atomic_clearbits_int(&p->p_p->ps_flags, PS_WXNEEDED);
749f68ce565Sderaadt 
7506b6f3ef9Sguenther 	atomic_clearbits_int(&pr->ps_flags, PS_INEXEC);
751*d479e871Sclaudio 	single_thread_clear(p);
7525c025fc6Smarius 
7531b4a394fSguenther 	/* setregs() sets up all the registers, so just 'return' */
7541b4a394fSguenther 	return EJUSTRETURN;
755df930be7Sderaadt 
756df930be7Sderaadt bad:
757df930be7Sderaadt 	/* free the vmspace-creation commands, and release their references */
758df930be7Sderaadt 	kill_vmcmds(&pack.ep_vmcmds);
759df930be7Sderaadt 	/* kill any opened file descriptor, if necessary */
760df930be7Sderaadt 	if (pack.ep_flags & EXEC_HASFD) {
761df930be7Sderaadt 		pack.ep_flags &= ~EXEC_HASFD;
762638f0017Sguenther 		fdplock(p->p_fd);
7638994f64aSvisa 		/* fdrelease unlocks p->p_fd. */
764df930be7Sderaadt 		(void) fdrelease(p, pack.ep_fd);
765df930be7Sderaadt 	}
766c0c22b04Stedu 	if (pack.ep_interp != NULL)
767335c12deSmickey 		pool_put(&namei_pool, pack.ep_interp);
768682e3c94Sguenther 	free(pack.ep_args, M_TEMP, sizeof *pack.ep_args);
769f0efa6a8Sderaadt 	free(pack.ep_pins, M_PINSYSCALL, pack.ep_npins * sizeof(u_int));
770df930be7Sderaadt 	/* close and put the exec'd file */
771d84dbf2eSart 	vn_close(pack.ep_vp, FREAD, cred, p);
772dbe27ba0Stedu 	pool_put(&namei_pool, nid.ni_cnd.cn_pnbuf);
773b324ced2Skettenis 	km_free(argp, NCARGS, &kv_exec, &kp_pageable);
774df930be7Sderaadt 
775df930be7Sderaadt freehdr:
7767da957a5Sderaadt 	free(pack.ep_hdr, M_EXEC, pack.ep_hdrlen);
7776b6f3ef9Sguenther 	atomic_clearbits_int(&pr->ps_flags, PS_INEXEC);
778*d479e871Sclaudio 	single_thread_clear(p);
779a792ab75Sart 
780bcfbf755Sniklas 	return (error);
781df930be7Sderaadt 
782df930be7Sderaadt exec_abort:
783df930be7Sderaadt 	/*
784df930be7Sderaadt 	 * the old process doesn't exist anymore.  exit gracefully.
785df930be7Sderaadt 	 * get rid of the (new) address space we have created, if any, get rid
786df930be7Sderaadt 	 * of our namei data and vnode, and exit noting failure
787df930be7Sderaadt 	 */
788782069b1Smpi 	uvm_unmap(&vm->vm_map, VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS);
789c0c22b04Stedu 	if (pack.ep_interp != NULL)
790335c12deSmickey 		pool_put(&namei_pool, pack.ep_interp);
791682e3c94Sguenther 	free(pack.ep_args, M_TEMP, sizeof *pack.ep_args);
792dbe27ba0Stedu 	pool_put(&namei_pool, nid.ni_cnd.cn_pnbuf);
793d84dbf2eSart 	vn_close(pack.ep_vp, FREAD, cred, p);
794b324ced2Skettenis 	km_free(argp, NCARGS, &kv_exec, &kp_pageable);
795ab30c277Spefo 
796ab30c277Spefo free_pack_abort:
7977da957a5Sderaadt 	free(pack.ep_hdr, M_EXEC, pack.ep_hdrlen);
798381e34d2Sguenther 	exit1(p, 0, SIGABRT, EXIT_NORMAL);
799df930be7Sderaadt 	/* NOTREACHED */
800df930be7Sderaadt }
801df930be7Sderaadt 
802df930be7Sderaadt 
803682e3c94Sguenther int
804158fb4f9Sjsg copyargs(struct exec_package *pack, struct ps_strings *arginfo, void *stack,
805158fb4f9Sjsg     void *argp)
806df930be7Sderaadt {
807df930be7Sderaadt 	char **cpp = stack;
808df930be7Sderaadt 	char *dp, *sp;
809df930be7Sderaadt 	size_t len;
810df930be7Sderaadt 	void *nullp = NULL;
811d2b5d78fSart 	long argc = arginfo->ps_nargvstr;
812df930be7Sderaadt 	int envc = arginfo->ps_nenvstr;
813df930be7Sderaadt 
814df930be7Sderaadt 	if (copyout(&argc, cpp++, sizeof(argc)))
815682e3c94Sguenther 		return (0);
816df930be7Sderaadt 
817b702d795Sguenther 	dp = (char *) (cpp + argc + envc + 2 + ELF_AUX_WORDS);
818df930be7Sderaadt 	sp = argp;
819df930be7Sderaadt 
820df930be7Sderaadt 	/* XXX don't copy them out, remap them! */
821df930be7Sderaadt 	arginfo->ps_argvstr = cpp; /* remember location of argv for later */
822df930be7Sderaadt 
823df930be7Sderaadt 	for (; --argc >= 0; sp += len, dp += len)
824df930be7Sderaadt 		if (copyout(&dp, cpp++, sizeof(dp)) ||
825df930be7Sderaadt 		    copyoutstr(sp, dp, ARG_MAX, &len))
826682e3c94Sguenther 			return (0);
827df930be7Sderaadt 
828df930be7Sderaadt 	if (copyout(&nullp, cpp++, sizeof(nullp)))
829682e3c94Sguenther 		return (0);
830df930be7Sderaadt 
831df930be7Sderaadt 	arginfo->ps_envstr = cpp; /* remember location of envp for later */
832df930be7Sderaadt 
833df930be7Sderaadt 	for (; --envc >= 0; sp += len, dp += len)
834df930be7Sderaadt 		if (copyout(&dp, cpp++, sizeof(dp)) ||
835df930be7Sderaadt 		    copyoutstr(sp, dp, ARG_MAX, &len))
836682e3c94Sguenther 			return (0);
837df930be7Sderaadt 
838df930be7Sderaadt 	if (copyout(&nullp, cpp++, sizeof(nullp)))
839682e3c94Sguenther 		return (0);
840df930be7Sderaadt 
841682e3c94Sguenther 	/* if this process needs auxinfo, note where to place it */
842682e3c94Sguenther 	if (pack->ep_args != NULL)
843682e3c94Sguenther 		pack->ep_auxinfo = cpp;
844682e3c94Sguenther 
845682e3c94Sguenther 	return (1);
846df930be7Sderaadt }
8474a5480feSart 
8484a5480feSart int
8495a72e03eSguenther exec_sigcode_map(struct process *pr)
8504a5480feSart {
8515a72e03eSguenther 	extern char sigcode[], esigcode[], sigcoderet[];
8524a5480feSart 	vsize_t sz;
8534a5480feSart 
8545a72e03eSguenther 	sz = (vaddr_t)esigcode - (vaddr_t)sigcode;
8554a5480feSart 
8564a5480feSart 	/*
8575a72e03eSguenther 	 * If we don't have a sigobject yet, create one.
8584a5480feSart 	 *
8594a5480feSart 	 * sigobject is an anonymous memory object (just like SYSV shared
8604a5480feSart 	 * memory) that we keep a permanent reference to and that we map
8614a5480feSart 	 * in all processes that need this sigcode. The creation is simple,
8624a5480feSart 	 * we create an object, add a permanent reference to it, map it in
8631db99e90Sderaadt 	 * kernel space, copy out the sigcode to it and unmap it.  Then we map
8641db99e90Sderaadt 	 * it with PROT_EXEC into the process just the way sys_mmap would map it.
8654a5480feSart 	 */
8665a72e03eSguenther 	if (sigobject == NULL) {
867b983598cSderaadt 		extern int sigfillsiz;
868b983598cSderaadt 		extern u_char sigfill[];
869d5ee67c8Sderaadt 		size_t off, left;
8704a5480feSart 		vaddr_t va;
8714a5480feSart 		int r;
8724a5480feSart 
8735a72e03eSguenther 		sigobject = uao_create(sz, 0);
8745a72e03eSguenther 		uao_reference(sigobject);	/* permanent reference */
8754a5480feSart 
8765a72e03eSguenther 		if ((r = uvm_map(kernel_map, &va, round_page(sz), sigobject,
8771e8cdc2eSderaadt 		    0, 0, UVM_MAPFLAG(PROT_READ | PROT_WRITE, PROT_READ | PROT_WRITE,
87815cd8707Sguenther 		    MAP_INHERIT_SHARE, MADV_RANDOM, 0)))) {
8795a72e03eSguenther 			uao_detach(sigobject);
8804a5480feSart 			return (ENOMEM);
8814a5480feSart 		}
882b983598cSderaadt 
883d5ee67c8Sderaadt 		for (off = 0, left = round_page(sz); left != 0;
884d5ee67c8Sderaadt 		    off += sigfillsiz) {
885d5ee67c8Sderaadt 			size_t chunk = ulmin(left, sigfillsiz);
886d5ee67c8Sderaadt 			memcpy((caddr_t)va + off, sigfill, chunk);
887d5ee67c8Sderaadt 			left -= chunk;
888d5ee67c8Sderaadt 		}
8895a72e03eSguenther 		memcpy((caddr_t)va, sigcode, sz);
89013f0bae7Skettenis 
89113f0bae7Skettenis 		(void) uvm_map_protect(kernel_map, va, round_page(sz),
89213f0bae7Skettenis 		    PROT_READ, 0, FALSE, FALSE);
89313f0bae7Skettenis 		sigcode_va = va;
89413f0bae7Skettenis 		sigcode_sz = round_page(sz);
8954a5480feSart 	}
8964a5480feSart 
897924be113Sguenther 	pr->ps_sigcode = 0; /* no hint */
8985a72e03eSguenther 	uao_reference(sigobject);
899924be113Sguenther 	if (uvm_map(&pr->ps_vmspace->vm_map, &pr->ps_sigcode, round_page(sz),
9001db99e90Sderaadt 	    sigobject, 0, 0, UVM_MAPFLAG(PROT_EXEC,
90112ccc845Skettenis 	    PROT_READ | PROT_WRITE | PROT_EXEC, MAP_INHERIT_COPY,
90230d20579Sderaadt 	    MADV_RANDOM, UVM_FLAG_COPYONW))) {
9035a72e03eSguenther 		uao_detach(sigobject);
9044a5480feSart 		return (ENOMEM);
9054a5480feSart 	}
9068db818c7Sderaadt 	uvm_map_immutable(&pr->ps_vmspace->vm_map, pr->ps_sigcode,
9071c71e4e1Sderaadt 	    pr->ps_sigcode + round_page(sz), 1);
9084a5480feSart 
9097730d1d9Sderaadt 	/* Calculate PC at point of sigreturn entry */
9105a72e03eSguenther 	pr->ps_sigcoderet = pr->ps_sigcode + (sigcoderet - sigcode);
9117730d1d9Sderaadt 
9124a5480feSart 	return (0);
9134a5480feSart }
914d82e6535Spirofti 
915d82e6535Spirofti int
916d82e6535Spirofti exec_timekeep_map(struct process *pr)
917d82e6535Spirofti {
9186a3d01b2Skettenis 	size_t timekeep_sz = round_page(sizeof(struct timekeep));
919d82e6535Spirofti 
920d82e6535Spirofti 	/*
921f231ff59Sguenther 	 * Similar to the sigcode object
922d82e6535Spirofti 	 */
923d82e6535Spirofti 	if (timekeep_object == NULL) {
924d82e6535Spirofti 		vaddr_t va = 0;
925d82e6535Spirofti 
926d82e6535Spirofti 		timekeep_object = uao_create(timekeep_sz, 0);
927d82e6535Spirofti 		uao_reference(timekeep_object);
928d82e6535Spirofti 
9296a3d01b2Skettenis 		if (uvm_map(kernel_map, &va, timekeep_sz, timekeep_object,
930d82e6535Spirofti 		    0, 0, UVM_MAPFLAG(PROT_READ | PROT_WRITE, PROT_READ | PROT_WRITE,
931d82e6535Spirofti 		    MAP_INHERIT_SHARE, MADV_RANDOM, 0))) {
932d82e6535Spirofti 			uao_detach(timekeep_object);
9336a3d01b2Skettenis 			timekeep_object = NULL;
9346a3d01b2Skettenis 			return (ENOMEM);
9356a3d01b2Skettenis 		}
9366a3d01b2Skettenis 		if (uvm_fault_wire(kernel_map, va, va + timekeep_sz,
9376a3d01b2Skettenis 		    PROT_READ | PROT_WRITE)) {
9386a3d01b2Skettenis 			uvm_unmap(kernel_map, va, va + timekeep_sz);
9396a3d01b2Skettenis 			uao_detach(timekeep_object);
9406a3d01b2Skettenis 			timekeep_object = NULL;
941d82e6535Spirofti 			return (ENOMEM);
942d82e6535Spirofti 		}
943d82e6535Spirofti 
944d82e6535Spirofti 		timekeep = (struct timekeep *)va;
945d82e6535Spirofti 		timekeep->tk_version = TK_VERSION;
946d82e6535Spirofti 	}
947d82e6535Spirofti 
948d82e6535Spirofti 	pr->ps_timekeep = 0; /* no hint */
949d82e6535Spirofti 	uao_reference(timekeep_object);
9501502f498Snaddy 	if (uvm_map(&pr->ps_vmspace->vm_map, &pr->ps_timekeep, timekeep_sz,
951d82e6535Spirofti 	    timekeep_object, 0, 0, UVM_MAPFLAG(PROT_READ, PROT_READ,
952d82e6535Spirofti 	    MAP_INHERIT_COPY, MADV_RANDOM, 0))) {
953d82e6535Spirofti 		uao_detach(timekeep_object);
954d82e6535Spirofti 		return (ENOMEM);
955d82e6535Spirofti 	}
9568db818c7Sderaadt 	uvm_map_immutable(&pr->ps_vmspace->vm_map, pr->ps_timekeep,
9571c71e4e1Sderaadt 	    pr->ps_timekeep + timekeep_sz, 1);
958d82e6535Spirofti 
959d82e6535Spirofti 	return (0);
960d82e6535Spirofti }
961