xref: /original-bsd/sys/kern/kern_exec.c (revision dd262573)
1 /*
2  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)kern_exec.c	7.33 (Berkeley) 12/05/90
8  */
9 
10 #include "param.h"
11 #include "systm.h"
12 #include "user.h"
13 #include "kernel.h"
14 #include "proc.h"
15 #include "mount.h"
16 #include "ucred.h"
17 #include "malloc.h"
18 #include "vnode.h"
19 #include "seg.h"
20 #include "file.h"
21 #include "uio.h"
22 #include "acct.h"
23 #include "exec.h"
24 #include "ktrace.h"
25 
26 #include "machine/reg.h"
27 #include "machine/psl.h"
28 #include "machine/mtpr.h"
29 
30 #include "mman.h"
31 #include "../vm/vm_param.h"
32 #include "../vm/vm_map.h"
33 #include "../vm/vm_kern.h"
34 #include "../vm/vm_pager.h"
35 
36 #ifdef HPUXCOMPAT
37 #include "../hpux/hpux_exec.h"
38 #endif
39 
40 /*
41  * exec system call, with and without environments.
42  */
43 execv(p, uap, retval)
44 	struct proc *p;
45 	struct args {
46 		char	*fname;
47 		char	**argp;
48 		char	**envp;
49 	} *uap;
50 	int *retval;
51 {
52 
53 	uap->envp = NULL;
54 	return (execve(p, uap, retval));
55 }
56 
57 /* ARGSUSED */
58 execve(p, uap, retval)
59 	register struct proc *p;
60 	register struct args {
61 		char	*fname;
62 		char	**argp;
63 		char	**envp;
64 	} *uap;
65 	int *retval;
66 {
67 	register nc;
68 	register char *cp;
69 	int na, ne, ucp, ap, cc;
70 	unsigned len;
71 	int indir, uid, gid;
72 	char *sharg;
73 	struct vnode *vp;
74 	struct vattr vattr;
75 	char cfname[MAXCOMLEN + 1];
76 	char cfarg[MAXINTERP];
77 	union {
78 		char	ex_shell[MAXINTERP];	/* #! and interpreter name */
79 		struct	exec ex_exec;
80 #ifdef HPUXCOMPAT
81 		struct	hpux_exec ex_hexec;
82 #endif
83 	} exdata;
84 #ifdef HPUXCOMPAT
85 	struct hpux_exec hhead;
86 #endif
87 	register struct ucred *cred = u.u_cred;
88 	register struct nameidata *ndp = &u.u_nd;
89 	int resid, error, flags = 0;
90 	vm_offset_t execargs;
91 
92   start:
93 	ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
94 	ndp->ni_segflg = UIO_USERSPACE;
95 	ndp->ni_dirp = uap->fname;
96 	if (error = namei(ndp))
97 		return (error);
98 	vp = ndp->ni_vp;
99 	indir = 0;
100 	uid = cred->cr_uid;
101 	gid = cred->cr_gid;
102 	if (error = VOP_GETATTR(vp, &vattr, cred))
103 		goto bad;
104 	if (vp->v_mount->mnt_flag & MNT_NOEXEC) {
105 		error = EACCES;
106 		goto bad;
107 	}
108 	if ((vp->v_mount->mnt_flag & MNT_NOSUID) == 0) {
109 		if (vattr.va_mode & VSUID)
110 			uid = vattr.va_uid;
111 		if (vattr.va_mode & VSGID)
112 			gid = vattr.va_gid;
113 	}
114 
115   again:
116 	if (error = VOP_ACCESS(vp, VEXEC, cred))
117 		goto bad;
118 	if ((p->p_flag & STRC) && (error = VOP_ACCESS(vp, VREAD, cred)))
119 		goto bad;
120 	if (vp->v_type != VREG ||
121 	    (vattr.va_mode & (VEXEC|(VEXEC>>3)|(VEXEC>>6))) == 0) {
122 		error = EACCES;
123 		goto bad;
124 	}
125 
126 	/*
127 	 * Read in first few bytes of file for segment sizes, magic number:
128 	 *	OMAGIC = plain executable
129 	 *	NMAGIC = RO text
130 	 *	ZMAGIC = demand paged RO text
131 	 * Also an ASCII line beginning with #! is
132 	 * the file name of a ``shell'' and arguments may be prepended
133 	 * to the argument list if given here.
134 	 *
135 	 * SHELL NAMES ARE LIMITED IN LENGTH.
136 	 *
137 	 * ONLY ONE ARGUMENT MAY BE PASSED TO THE SHELL FROM
138 	 * THE ASCII LINE.
139 	 */
140 	exdata.ex_shell[0] = '\0';	/* for zero length files */
141 	error = vn_rdwr(UIO_READ, vp, (caddr_t)&exdata, sizeof (exdata),
142 	    (off_t)0, UIO_SYSSPACE, (IO_UNIT|IO_NODELOCKED), cred, &resid);
143 	if (error)
144 		goto bad;
145 #ifndef lint
146 	if (resid > sizeof(exdata) - sizeof(exdata.ex_exec) &&
147 	    exdata.ex_shell[0] != '#') {
148 		error = ENOEXEC;
149 		goto bad;
150 	}
151 #endif
152 #if defined(hp300)
153 	switch ((int)exdata.ex_exec.a_mid) {
154 
155 	/*
156 	 * An ancient hp200 or hp300 binary, shouldn't happen anymore.
157 	 * Mark as invalid.
158 	 */
159 	case MID_ZERO:
160 		exdata.ex_exec.a_magic = 0;
161 		break;
162 
163 	/*
164 	 * HP200 series has a smaller page size so we cannot
165 	 * demand-load or even write protect text, so we just
166 	 * treat as OMAGIC.
167 	 */
168 	case MID_HP200:
169 		exdata.ex_exec.a_magic = OMAGIC;
170 		break;
171 
172 	case MID_HP300:
173 		break;
174 
175 #ifdef HPUXCOMPAT
176 	case MID_HPUX:
177 		/*
178 		 * Save a.out header.  This is eventually saved in the pcb,
179 		 * but we cannot do that yet in case the exec fails before
180 		 * the image is overlayed.
181 		 */
182 		bcopy((caddr_t)&exdata.ex_hexec,
183 		      (caddr_t)&hhead, sizeof hhead);
184 		/*
185 		 * If version number is 0x2bad this is a native BSD
186 		 * binary created via the HPUX SGS.  Should not be
187 		 * treated as an HPUX binary.
188 		 */
189 		if (exdata.ex_hexec.ha_version != BSDVNUM)
190 			flags |= SHPUX;
191 		/*
192 		 * Shuffle important fields to their BSD locations.
193 		 * Note that the order in which this is done is important.
194 		 */
195 		exdata.ex_exec.a_text = exdata.ex_hexec.ha_text;
196 		exdata.ex_exec.a_data = exdata.ex_hexec.ha_data;
197 		exdata.ex_exec.a_bss = exdata.ex_hexec.ha_bss;
198 		exdata.ex_exec.a_entry = exdata.ex_hexec.ha_entry;
199 		/*
200 		 * For ZMAGIC files, make sizes consistant with those
201 		 * generated by BSD ld.
202 		 */
203 		if (exdata.ex_exec.a_magic == ZMAGIC) {
204 			exdata.ex_exec.a_text =
205 				ctob(btoc(exdata.ex_exec.a_text));
206 			nc = exdata.ex_exec.a_data + exdata.ex_exec.a_bss;
207 			exdata.ex_exec.a_data =
208 				ctob(btoc(exdata.ex_exec.a_data));
209 			nc -= (int)exdata.ex_exec.a_data;
210 			exdata.ex_exec.a_bss = (nc < 0) ? 0 : nc;
211 		}
212 		break;
213 #endif
214 	}
215 #endif
216 	switch ((int)exdata.ex_exec.a_magic) {
217 
218 	case OMAGIC:
219 		exdata.ex_exec.a_data += exdata.ex_exec.a_text;
220 		exdata.ex_exec.a_text = 0;
221 		break;
222 
223 	case ZMAGIC:
224 		flags |= SPAGV;
225 	case NMAGIC:
226 		if (exdata.ex_exec.a_text == 0) {
227 			error = ENOEXEC;
228 			goto bad;
229 		}
230 		break;
231 
232 	default:
233 		if (exdata.ex_shell[0] != '#' ||
234 		    exdata.ex_shell[1] != '!' ||
235 		    indir) {
236 			error = ENOEXEC;
237 			goto bad;
238 		}
239 		for (cp = &exdata.ex_shell[2];; ++cp) {
240 			if (cp >= &exdata.ex_shell[MAXINTERP]) {
241 				error = ENOEXEC;
242 				goto bad;
243 			}
244 			if (*cp == '\n') {
245 				*cp = '\0';
246 				break;
247 			}
248 			if (*cp == '\t')
249 				*cp = ' ';
250 		}
251 		cp = &exdata.ex_shell[2];
252 		while (*cp == ' ')
253 			cp++;
254 		ndp->ni_dirp = cp;
255 		while (*cp && *cp != ' ')
256 			cp++;
257 		cfarg[0] = '\0';
258 		if (*cp) {
259 			*cp++ = '\0';
260 			while (*cp == ' ')
261 				cp++;
262 			if (*cp)
263 				bcopy((caddr_t)cp, (caddr_t)cfarg, MAXINTERP);
264 		}
265 		indir = 1;
266 		vput(vp);
267 		ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
268 		ndp->ni_segflg = UIO_SYSSPACE;
269 		if (error = namei(ndp))
270 			return (error);
271 		vp = ndp->ni_vp;
272 		if (error = VOP_GETATTR(vp, &vattr, cred))
273 			goto bad;
274 		bcopy((caddr_t)ndp->ni_dent.d_name, (caddr_t)cfname,
275 		    MAXCOMLEN);
276 		cfname[MAXCOMLEN] = '\0';
277 		uid = cred->cr_uid;	/* shell scripts can't be setuid */
278 		gid = cred->cr_gid;
279 		goto again;
280 	}
281 
282 	/*
283 	 * Collect arguments on "file" in swap space.
284 	 */
285 	na = 0;
286 	ne = 0;
287 	nc = 0;
288 	cc = NCARGS;
289 	execargs = kmem_alloc_wait(exec_map, NCARGS);
290 	cp = (char *) execargs;
291 	/*
292 	 * Copy arguments into file in argdev area.
293 	 */
294 	if (uap->argp) for (;;) {
295 		ap = NULL;
296 		sharg = NULL;
297 		if (indir && na == 0) {
298 			sharg = cfname;
299 			ap = (int)sharg;
300 			uap->argp++;		/* ignore argv[0] */
301 		} else if (indir && (na == 1 && cfarg[0])) {
302 			sharg = cfarg;
303 			ap = (int)sharg;
304 		} else if (indir && (na == 1 || na == 2 && cfarg[0]))
305 			ap = (int)uap->fname;
306 		else if (uap->argp) {
307 			ap = fuword((caddr_t)uap->argp);
308 			uap->argp++;
309 		}
310 		if (ap == NULL && uap->envp) {
311 			uap->argp = NULL;
312 			if ((ap = fuword((caddr_t)uap->envp)) != NULL)
313 				uap->envp++, ne++;
314 		}
315 		if (ap == NULL)
316 			break;
317 		na++;
318 		if (ap == -1) {
319 			error = EFAULT;
320 			goto bad;
321 		}
322 		do {
323 			if (nc >= NCARGS-1) {
324 				error = E2BIG;
325 				break;
326 			}
327 			if (sharg) {
328 				error = copystr(sharg, cp, (unsigned)cc, &len);
329 				sharg += len;
330 			} else {
331 				error = copyinstr((caddr_t)ap, cp, (unsigned)cc,
332 				    &len);
333 				ap += len;
334 			}
335 			cp += len;
336 			nc += len;
337 			cc -= len;
338 		} while (error == ENAMETOOLONG);
339 		if (error)
340 			goto bad;
341 	}
342 	nc = (nc + NBPW-1) & ~(NBPW-1);
343 	error = getxfile(p, vp, &exdata.ex_exec, flags, nc + (na+4)*NBPW,
344 	    uid, gid);
345 	if (error)
346 		goto bad;
347 	vput(vp);
348 	vp = NULL;
349 
350 #ifdef HPUXCOMPAT
351 	/*
352 	 * We are now committed to the exec so we can save the exec
353 	 * header in the pcb where we can dump it if necessary in core()
354 	 */
355 	if (u.u_pcb.pcb_flags & PCB_HPUXBIN)
356 		bcopy((caddr_t)&hhead,
357 		      (caddr_t)u.u_pcb.pcb_exec, sizeof hhead);
358 #endif
359 
360 	/*
361 	 * Copy back arglist.
362 	 */
363 	ucp = USRSTACK - sizeof(u.u_pcb.pcb_sigc) - nc - NBPW;
364 	ap = ucp - na*NBPW - 3*NBPW;
365 	u.u_ar0[SP] = ap;
366 	(void) suword((caddr_t)ap, na-ne);
367 	nc = 0;
368 	cp = (char *) execargs;
369 	cc = NCARGS;
370 	for (;;) {
371 		ap += NBPW;
372 		if (na == ne) {
373 			(void) suword((caddr_t)ap, 0);
374 			ap += NBPW;
375 		}
376 		if (--na < 0)
377 			break;
378 		(void) suword((caddr_t)ap, ucp);
379 		do {
380 			error = copyoutstr(cp, (caddr_t)ucp, (unsigned)cc,
381 			    &len);
382 			ucp += len;
383 			cp += len;
384 			nc += len;
385 			cc -= len;
386 		} while (error == ENAMETOOLONG);
387 		if (error == EFAULT)
388 			panic("exec: EFAULT");
389 	}
390 	(void) suword((caddr_t)ap, 0);
391 
392 	execsigs(p);
393 
394 	for (nc = u.u_lastfile; nc >= 0; --nc) {
395 		if (u.u_pofile[nc] & UF_EXCLOSE) {
396 			(void) closef(u.u_ofile[nc]);
397 			u.u_ofile[nc] = NULL;
398 			u.u_pofile[nc] = 0;
399 		}
400 		u.u_pofile[nc] &= ~UF_MAPPED;
401 	}
402 	while (u.u_lastfile >= 0 && u.u_ofile[u.u_lastfile] == NULL)
403 		u.u_lastfile--;
404 	setregs(exdata.ex_exec.a_entry, retval);
405 	/*
406 	 * Install sigcode at top of user stack.
407 	 */
408 	copyout((caddr_t)u.u_pcb.pcb_sigc,
409 		(caddr_t)(USRSTACK - sizeof(u.u_pcb.pcb_sigc)),
410 		sizeof(u.u_pcb.pcb_sigc));
411 	/*
412 	 * Remember file name for accounting.
413 	 */
414 	u.u_acflag &= ~AFORK;
415 	if (indir)
416 		bcopy((caddr_t)cfname, (caddr_t)p->p_comm, MAXCOMLEN);
417 	else {
418 		if (ndp->ni_dent.d_namlen > MAXCOMLEN)
419 			ndp->ni_dent.d_namlen = MAXCOMLEN;
420 		bcopy((caddr_t)ndp->ni_dent.d_name, (caddr_t)p->p_comm,
421 		    (unsigned)(ndp->ni_dent.d_namlen + 1));
422 	}
423 bad:
424 	if (execargs)
425 		kmem_free_wakeup(exec_map, execargs, NCARGS);
426 	if (vp)
427 		vput(vp);
428 	return (error);
429 }
430 
431 /*
432  * Read in and set up memory for executed file.
433  */
434 getxfile(p, vp, ep, flags, nargc, uid, gid)
435 	register struct proc *p;
436 	register struct vnode *vp;
437 	register struct exec *ep;
438 	int flags, nargc, uid, gid;
439 {
440 	segsz_t ts, ds, ss;
441 	register struct ucred *cred = u.u_cred;
442 	off_t toff;
443 	int error = 0;
444 	vm_offset_t addr;
445 	vm_size_t size;
446 	vm_map_t map = VM_MAP_NULL;
447 
448 #ifdef HPUXCOMPAT
449 	if (ep->a_mid == MID_HPUX) {
450 		if (flags & SPAGV)
451 			toff = CLBYTES;
452 		else
453 			toff = sizeof (struct hpux_exec);
454 	} else
455 #endif
456 	if (flags & SPAGV)
457 		toff = CLBYTES;
458 	else
459 		toff = sizeof (struct exec);
460 	if (ep->a_text != 0 && (vp->v_flag & VTEXT) == 0 &&
461 	    vp->v_usecount != 1) {
462 		register struct file *fp;
463 
464 		for (fp = file; fp < fileNFILE; fp++) {
465 			if (fp->f_type == DTYPE_VNODE &&
466 			    fp->f_count > 0 &&
467 			    (struct vnode *)fp->f_data == vp &&
468 			    (fp->f_flag & FWRITE)) {
469 				return (ETXTBSY);
470 			}
471 		}
472 	}
473 
474 	/*
475 	 * Compute text and data sizes and make sure not too large.
476 	 * NB - Check data and bss separately as they may overflow
477 	 * when summed together.
478 	 */
479 	ts = clrnd(btoc(ep->a_text));
480 	ds = clrnd(btoc(ep->a_data + ep->a_bss));
481 	ss = clrnd(SSIZE + btoc(nargc + sizeof(u.u_pcb.pcb_sigc)));
482 #ifdef SYSVSHM
483 	if (p->p_shm)
484 		shmexit(p);
485 #endif
486 	map = p->p_map;
487 	(void) vm_map_remove(map, vm_map_min(map), vm_map_max(map));
488 	/*
489 	 * XXX preserve synchronization semantics of vfork
490 	 */
491 	if (p->p_flag & SVFORK) {
492 		p->p_flag &= ~SVFORK;
493 		wakeup((caddr_t)p);
494 		while ((p->p_flag & SVFDONE) == 0)
495 			sleep((caddr_t)p, PZERO - 1);
496 		p->p_flag &= ~SVFDONE;
497 	}
498 #ifdef hp300
499 	u.u_pcb.pcb_flags &= ~(PCB_AST|PCB_HPUXMMAP|PCB_HPUXBIN);
500 #ifdef HPUXCOMPAT
501 	/* remember that we were loaded from an HPUX format file */
502 	if (ep->a_mid == MID_HPUX)
503 		u.u_pcb.pcb_flags |= PCB_HPUXBIN;
504 #endif
505 #endif
506 	p->p_flag &= ~(SPAGV|SSEQL|SUANOM|SHPUX);
507 	p->p_flag |= flags | SEXEC;
508 	addr = VM_MIN_ADDRESS;
509 	if (vm_allocate(map, &addr, round_page(ctob(ts + ds)), FALSE)) {
510 		uprintf("Cannot allocate text+data space\n");
511 		error = ENOMEM;			/* XXX */
512 		goto badmap;
513 	}
514 	size = round_page(MAXSSIZ);		/* XXX */
515 	addr = trunc_page(VM_MAX_ADDRESS - size);
516 	if (vm_allocate(map, &addr, size, FALSE)) {
517 		uprintf("Cannot allocate stack space\n");
518 		error = ENOMEM;			/* XXX */
519 		goto badmap;
520 	}
521 	u.u_maxsaddr = (caddr_t)addr;
522 	u.u_taddr = (caddr_t)VM_MIN_ADDRESS;
523 	u.u_daddr = (caddr_t)(VM_MIN_ADDRESS + ctob(ts));
524 
525 	if ((flags & SPAGV) == 0)
526 		(void) vn_rdwr(UIO_READ, vp,
527 			u.u_daddr,
528 			(int)ep->a_data,
529 			(off_t)(toff + ep->a_text),
530 			UIO_USERSPACE, (IO_UNIT|IO_NODELOCKED), cred, (int *)0);
531 	/*
532 	 * Read in text segment if necessary (0410), and read-protect it.
533 	 */
534 	if ((flags & SPAGV) == 0) {
535 		if (ep->a_text > 0) {
536 			error = vn_rdwr(UIO_READ, vp,
537 					u.u_taddr, (int)ep->a_text, toff,
538 					UIO_USERSPACE, (IO_UNIT|IO_NODELOCKED),
539 					cred, (int *)0);
540 			(void) vm_map_protect(map,
541 					VM_MIN_ADDRESS,
542 					VM_MIN_ADDRESS+trunc_page(ep->a_text),
543 					VM_PROT_READ|VM_PROT_EXECUTE, FALSE);
544 		}
545 	} else {
546 		/*
547 		 * Allocate a region backed by the exec'ed vnode.
548 		 */
549 		addr = VM_MIN_ADDRESS;
550 		size = round_page(ep->a_text + ep->a_data);
551 		error = vm_mmap(map, &addr, size, VM_PROT_ALL,
552 				MAP_FILE|MAP_COPY|MAP_FIXED,
553 				(caddr_t)vp, (vm_offset_t)toff);
554 		(void) vm_map_protect(map, addr,
555 				addr+trunc_page(ep->a_text),
556 				VM_PROT_READ|VM_PROT_EXECUTE, FALSE);
557 	}
558 badmap:
559 	if (error) {
560 		if (map != VM_MAP_NULL)
561 			vm_deallocate(map, vm_map_min(map), vm_map_max(map));
562 		printf("pid %d: VM allocation failure\n", p->p_pid);
563 		uprintf("sorry, pid %d was killed in exec: VM allocation\n",
564 			p->p_pid);
565 		psignal(p, SIGKILL);
566 		p->p_flag |= SULOCK;
567 		return(error);
568 	}
569 
570 	/*
571 	 * set SUID/SGID protections, if no tracing
572 	 */
573 	if ((p->p_flag&STRC)==0) {
574 		if (uid != cred->cr_uid || gid != cred->cr_gid) {
575 			u.u_cred = cred = crcopy(cred);
576 			/*
577 			 * If process is being ktraced, turn off - unless
578 			 * root set it.
579 			 */
580 			if (p->p_tracep && !(p->p_traceflag & KTRFAC_ROOT)) {
581 				vrele(p->p_tracep);
582 				p->p_tracep = NULL;
583 				p->p_traceflag = 0;
584 			}
585 		}
586 		cred->cr_uid = uid;
587 		cred->cr_gid = gid;
588 		p->p_uid = uid;
589 	} else
590 		psignal(p, SIGTRAP);
591 	p->p_svuid = p->p_uid;
592 	p->p_svgid = cred->cr_gid;
593 	u.u_tsize = ts;
594 	u.u_dsize = ds;
595 	u.u_ssize = ss;
596 	u.u_prof.pr_scale = 0;
597 #if defined(tahoe)
598 	u.u_pcb.pcb_savacc.faddr = (float *)NULL;
599 #endif
600 	return (0);
601 }
602