add USL's copyright notice
[unix-history] / usr / src / sys / kern / kern_exec.c
CommitLineData
8c0dbd1c 1/*-
436acd38
KB
2 * Copyright (c) 1982, 1986, 1991, 1993
3 * The Regents of the University of California. All rights reserved.
adb35f79
KB
4 * (c) UNIX System Laboratories, Inc.
5 * All or some portions of this file are derived from material licensed
6 * to the University of California by American Telephone and Telegraph
7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 * the permission of UNIX System Laboratories, Inc.
da7c5cc6 9 *
8c0dbd1c
KB
10 * %sccs.include.proprietary.c%
11 *
adb35f79 12 * @(#)kern_exec.c 8.6 (Berkeley) %G%
da7c5cc6 13 */
28db9b87 14
38a01dbe
KB
15#include <sys/param.h>
16#include <sys/systm.h>
17#include <sys/filedesc.h>
18#include <sys/kernel.h>
19#include <sys/proc.h>
20#include <sys/mount.h>
21#include <sys/malloc.h>
22#include <sys/namei.h>
23#include <sys/vnode.h>
24#include <sys/file.h>
25#include <sys/acct.h>
26#include <sys/exec.h>
27#include <sys/ktrace.h>
28#include <sys/resourcevar.h>
28db9b87 29
38a01dbe
KB
30#include <machine/cpu.h>
31#include <machine/reg.h>
d301d150 32
38a01dbe
KB
33#include <sys/mman.h>
34#include <vm/vm.h>
35#include <vm/vm_param.h>
36#include <vm/vm_map.h>
37#include <vm/vm_kern.h>
38#include <vm/vm_pager.h>
9d4095a1 39
38a01dbe 40#include <sys/signalvar.h>
605f1ab4 41
93422d4b 42#ifdef HPUXCOMPAT
38a01dbe
KB
43#include <sys/user.h> /* for pcb */
44#include <hp/hpux/hpux_exec.h>
93422d4b
KM
45#endif
46
75a969a7
MK
47#ifdef COPY_SIGCODE
48extern char sigcode[], esigcode[];
49#define szsigcode (esigcode - sigcode)
50#else
51#define szsigcode 0
52#endif
53
8429d022
MK
54/*
55 * exec system call
56 */
c9714ae3
KM
57execve(p, uap, retval)
58 register struct proc *p;
9e97623a 59 register struct execve_args *uap;
c9714ae3 60 int *retval;
28db9b87 61{
8429d022 62 register struct ucred *cred = p->p_ucred;
5e00df3b 63 register struct filedesc *fdp = p->p_fd;
0a5745b2 64 int na, ne, ucp, ap, cc, ssize;
5e00df3b
KM
65 register char *cp;
66 register int nc;
8011f5df 67 unsigned len;
28db9b87
SL
68 int indir, uid, gid;
69 char *sharg;
c4ec2128 70 struct vnode *vp;
34dc7acb 71 int resid, error, paged = 0;
f0729cac 72 vm_offset_t execargs = 0;
c4ec2128 73 struct vattr vattr;
cb9392ae 74 char cfarg[MAXINTERP];
9fd50f35 75 union {
cb9392ae 76 char ex_shell[MAXINTERP]; /* #! and interpreter name */
9fd50f35 77 struct exec ex_exec;
93422d4b
KM
78#ifdef HPUXCOMPAT
79 struct hpux_exec ex_hexec;
80#endif
9fd50f35 81 } exdata;
93422d4b
KM
82#ifdef HPUXCOMPAT
83 struct hpux_exec hhead;
84#endif
8429d022 85 struct nameidata nd;
29075cfd 86 struct ps_strings ps;
ec67a3ce
MK
87#ifdef SECSIZE
88 extern long argdbsize; /* XXX */
89#endif SECSIZE
28db9b87 90
2881f082 91 NDINIT(&nd, LOOKUP, FOLLOW | SAVENAME, UIO_USERSPACE,
62ce54a4
KM
92 uap->fname, p);
93 if (error = namei(&nd))
d9c2f47f 94 return (error);
62ce54a4 95 vp = nd.ni_vp;
2881f082
KM
96 LEASE_CHECK(vp, p, cred, LEASE_READ);
97 VOP_LOCK(vp);
28db9b87 98 indir = 0;
c9714ae3
KM
99 uid = cred->cr_uid;
100 gid = cred->cr_gid;
f254ddb7 101 if (error = VOP_GETATTR(vp, &vattr, cred, p))
c4ec2128 102 goto bad;
54fb9dc2 103 if (vp->v_mount->mnt_flag & MNT_NOEXEC) {
c9714ae3 104 error = EACCES;
c4ec2128
KM
105 goto bad;
106 }
54fb9dc2 107 if ((vp->v_mount->mnt_flag & MNT_NOSUID) == 0) {
c4ec2128
KM
108 if (vattr.va_mode & VSUID)
109 uid = vattr.va_uid;
110 if (vattr.va_mode & VSGID)
111 gid = vattr.va_gid;
112 }
28db9b87
SL
113
114 again:
f254ddb7 115 if (error = VOP_ACCESS(vp, VEXEC, cred, p))
28db9b87 116 goto bad;
cf5ef508 117 if ((p->p_flag & P_TRACED) && (error = VOP_ACCESS(vp, VREAD, cred, p)))
28db9b87 118 goto bad;
c4ec2128
KM
119 if (vp->v_type != VREG ||
120 (vattr.va_mode & (VEXEC|(VEXEC>>3)|(VEXEC>>6))) == 0) {
c9714ae3 121 error = EACCES;
28db9b87
SL
122 goto bad;
123 }
124
125 /*
f3aaea26 126 * Read in first few bytes of file for segment sizes, magic number:
c4ec2128
KM
127 * OMAGIC = plain executable
128 * NMAGIC = RO text
129 * ZMAGIC = demand paged RO text
28db9b87
SL
130 * Also an ASCII line beginning with #! is
131 * the file name of a ``shell'' and arguments may be prepended
132 * to the argument list if given here.
133 *
134 * SHELL NAMES ARE LIMITED IN LENGTH.
135 *
136 * ONLY ONE ARGUMENT MAY BE PASSED TO THE SHELL FROM
137 * THE ASCII LINE.
138 */
9fd50f35 139 exdata.ex_shell[0] = '\0'; /* for zero length files */
c9714ae3 140 error = vn_rdwr(UIO_READ, vp, (caddr_t)&exdata, sizeof (exdata),
f254ddb7
KM
141 (off_t)0, UIO_SYSSPACE, (IO_UNIT|IO_NODELOCKED), cred, &resid,
142 (struct proc *)0);
c9714ae3 143 if (error)
28db9b87 144 goto bad;
28db9b87 145#ifndef lint
ce66cb03 146 if (resid > sizeof(exdata) - sizeof(exdata.ex_exec) &&
9fd50f35 147 exdata.ex_shell[0] != '#') {
c9714ae3 148 error = ENOEXEC;
28db9b87
SL
149 goto bad;
150 }
93422d4b 151#endif
96e7b0e1 152#if defined(hp300) || defined(luna68k)
93422d4b
KM
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);
93422d4b
KM
184 /*
185 * Shuffle important fields to their BSD locations.
186 * Note that the order in which this is done is important.
187 */
188 exdata.ex_exec.a_text = exdata.ex_hexec.ha_text;
189 exdata.ex_exec.a_data = exdata.ex_hexec.ha_data;
190 exdata.ex_exec.a_bss = exdata.ex_hexec.ha_bss;
191 exdata.ex_exec.a_entry = exdata.ex_hexec.ha_entry;
192 /*
193 * For ZMAGIC files, make sizes consistant with those
194 * generated by BSD ld.
195 */
196 if (exdata.ex_exec.a_magic == ZMAGIC) {
197 exdata.ex_exec.a_text =
198 ctob(btoc(exdata.ex_exec.a_text));
199 nc = exdata.ex_exec.a_data + exdata.ex_exec.a_bss;
200 exdata.ex_exec.a_data =
201 ctob(btoc(exdata.ex_exec.a_data));
202 nc -= (int)exdata.ex_exec.a_data;
203 exdata.ex_exec.a_bss = (nc < 0) ? 0 : nc;
204 }
205 break;
206#endif
207 }
28db9b87 208#endif
aec7dd3b 209 switch ((int)exdata.ex_exec.a_magic) {
28db9b87 210
c4ec2128 211 case OMAGIC:
f0729cac
RC
212#ifdef COFF
213 if (exdata.ex_exec.ex_fhdr.magic != COFF_MAGIC) {
214 error = ENOEXEC;
215 goto bad;
216 }
0a5745b2
CT
217#endif
218#ifdef sparc
219 if (exdata.ex_exec.a_mid != MID_SUN_SPARC) {
220 error = ENOEXEC;
221 goto bad;
222 }
f0729cac 223#endif
9fd50f35
SL
224 exdata.ex_exec.a_data += exdata.ex_exec.a_text;
225 exdata.ex_exec.a_text = 0;
28db9b87
SL
226 break;
227
c4ec2128 228 case ZMAGIC:
0a5745b2 229 paged = 1;
34dc7acb 230 /* FALLTHROUGH */
0a5745b2 231
c4ec2128 232 case NMAGIC:
f0729cac
RC
233#ifdef COFF
234 if (exdata.ex_exec.ex_fhdr.magic != COFF_MAGIC) {
235 error = ENOEXEC;
236 goto bad;
237 }
0a5745b2
CT
238#endif
239#ifdef sparc
240 if (exdata.ex_exec.a_mid != MID_SUN_SPARC) {
241 error = ENOEXEC;
242 goto bad;
243 }
f0729cac 244#endif
9fd50f35 245 if (exdata.ex_exec.a_text == 0) {
c9714ae3 246 error = ENOEXEC;
28db9b87
SL
247 goto bad;
248 }
249 break;
250
251 default:
446115cb
MK
252 if (exdata.ex_shell[0] != '#' ||
253 exdata.ex_shell[1] != '!' ||
254 indir) {
c9714ae3 255 error = ENOEXEC;
28db9b87
SL
256 goto bad;
257 }
d26813a4 258 for (cp = &exdata.ex_shell[2];; ++cp) {
446115cb 259 if (cp >= &exdata.ex_shell[MAXINTERP]) {
c9714ae3 260 error = ENOEXEC;
d26813a4
KB
261 goto bad;
262 }
263 if (*cp == '\n') {
28db9b87
SL
264 *cp = '\0';
265 break;
266 }
d26813a4
KB
267 if (*cp == '\t')
268 *cp = ' ';
28db9b87 269 }
446115cb
MK
270 cp = &exdata.ex_shell[2];
271 while (*cp == ' ')
272 cp++;
62ce54a4 273 nd.ni_dirp = cp;
446115cb
MK
274 while (*cp && *cp != ' ')
275 cp++;
e7db1101 276 cfarg[0] = '\0';
28db9b87 277 if (*cp) {
446115cb
MK
278 *cp++ = '\0';
279 while (*cp == ' ')
280 cp++;
ce66cb03 281 if (*cp)
cb9392ae 282 bcopy((caddr_t)cp, (caddr_t)cfarg, MAXINTERP);
e7db1101 283 }
446115cb 284 indir = 1;
c4ec2128 285 vput(vp);
62ce54a4
KM
286 nd.ni_segflg = UIO_SYSSPACE;
287 if (error = namei(&nd))
d9c2f47f 288 return (error);
62ce54a4 289 vp = nd.ni_vp;
a9892ae9
KM
290 LEASE_CHECK(vp, p, cred, LEASE_READ);
291 VOP_LOCK(vp);
f254ddb7 292 if (error = VOP_GETATTR(vp, &vattr, cred, p))
c4ec2128 293 goto bad;
c9714ae3
KM
294 uid = cred->cr_uid; /* shell scripts can't be setuid */
295 gid = cred->cr_gid;
28db9b87
SL
296 goto again;
297 }
298
299 /*
300 * Collect arguments on "file" in swap space.
301 */
302 na = 0;
303 ne = 0;
304 nc = 0;
9d4095a1
KM
305 cc = NCARGS;
306 execargs = kmem_alloc_wait(exec_map, NCARGS);
f0729cac
RC
307#ifdef DIAGNOSTIC
308 if (execargs == (vm_offset_t)0)
309 panic("execve: kmem_alloc_wait");
310#endif
9d4095a1 311 cp = (char *) execargs;
f3aaea26
SL
312 /*
313 * Copy arguments into file in argdev area.
314 */
28db9b87
SL
315 if (uap->argp) for (;;) {
316 ap = NULL;
ce66cb03
MK
317 sharg = NULL;
318 if (indir && na == 0) {
62ce54a4 319 sharg = nd.ni_cnd.cn_nameptr;
ce66cb03
MK
320 ap = (int)sharg;
321 uap->argp++; /* ignore argv[0] */
322 } else if (indir && (na == 1 && cfarg[0])) {
323 sharg = cfarg;
324 ap = (int)sharg;
325 } else if (indir && (na == 1 || na == 2 && cfarg[0]))
28db9b87
SL
326 ap = (int)uap->fname;
327 else if (uap->argp) {
328 ap = fuword((caddr_t)uap->argp);
329 uap->argp++;
330 }
f3aaea26 331 if (ap == NULL && uap->envp) {
28db9b87 332 uap->argp = NULL;
f3aaea26
SL
333 if ((ap = fuword((caddr_t)uap->envp)) != NULL)
334 uap->envp++, ne++;
28db9b87
SL
335 }
336 if (ap == NULL)
337 break;
338 na++;
f3aaea26 339 if (ap == -1) {
c9714ae3 340 error = EFAULT;
9d4095a1 341 goto bad;
f3aaea26 342 }
28db9b87 343 do {
9d4095a1
KM
344 if (nc >= NCARGS-1) {
345 error = E2BIG;
346 break;
28db9b87 347 }
ce66cb03 348 if (sharg) {
8011f5df 349 error = copystr(sharg, cp, (unsigned)cc, &len);
ce66cb03
MK
350 sharg += len;
351 } else {
8011f5df
MK
352 error = copyinstr((caddr_t)ap, cp, (unsigned)cc,
353 &len);
ce66cb03
MK
354 ap += len;
355 }
f3aaea26
SL
356 cp += len;
357 nc += len;
358 cc -= len;
9e73a4eb 359 } while (error == ENAMETOOLONG);
9d4095a1
KM
360 if (error)
361 goto bad;
28db9b87 362 }
0a5745b2
CT
363
364 /*
365 * XXX the following is excessively bogus
366 *
367 * Compute initial process stack size and location of argc
368 * and character strings. `nc' is currently just the number
369 * of characters of arg and env strings.
370 *
29075cfd
KM
371 * nc = size of ps_strings structure +
372 * size of signal code +
373 * 4 bytes of NULL pointer +
374 * nc,
375 * rounded to nearest integer;
0a5745b2
CT
376 * ucp = USRSTACK - nc; [user characters pointer]
377 * apsize = padding (if any) +
378 * 4 bytes of NULL pointer +
379 * ne 4-byte pointers to env strings +
380 * 4 bytes of NULL pointer +
381 * (na-ne) 4-byte pointers to arg strings +
382 * 4 bytes of argc;
383 * (this is the same as nc + (na+3)*4)
384 * ap = ucp - apsize; [user address of argc]
385 * ssize = ssize + nc + machine-dependent space;
386 */
29075cfd 387 nc = (sizeof(ps) + szsigcode + 4 + nc + NBPW-1) & ~(NBPW - 1);
e74c0572 388#if defined(sparc) || defined(mips)
0a5745b2 389 ucp = USRSTACK;
e74c0572 390 ssize = ALIGN(nc + (na + 3) * NBPW);
0a5745b2
CT
391 ap = ucp - ssize;
392 ucp -= nc;
e74c0572 393#ifdef sparc
0a5745b2 394 ssize += sizeof(struct rwindow);
e74c0572 395#endif
0a5745b2
CT
396#else
397 ssize = (na + 3) * NBPW;
398 ucp = USRSTACK - nc;
399 ap = ucp - ssize;
400 ssize += nc;
401#endif
402 error = getxfile(p, vp, &exdata.ex_exec, paged, ssize, uid, gid);
9d4095a1 403 if (error)
28db9b87 404 goto bad;
859437ef
JSP
405
406 /* take a reference to the new text vnode (for procfs) */
407 if (p->p_textvp)
408 vrele(p->p_textvp);
409 VREF(vp);
410 p->p_textvp = vp;
411
c4ec2128
KM
412 vput(vp);
413 vp = NULL;
28db9b87 414
93422d4b
KM
415#ifdef HPUXCOMPAT
416 /*
417 * We are now committed to the exec so we can save the exec
418 * header in the pcb where we can dump it if necessary in core()
419 */
9921f05f 420 if (p->p_md.md_flags & MDP_HPUX)
93422d4b 421 bcopy((caddr_t)&hhead,
9921f05f 422 (caddr_t)p->p_addr->u_md.md_exec, sizeof hhead);
93422d4b
KM
423#endif
424
28db9b87 425 /*
f3aaea26 426 * Copy back arglist.
28db9b87 427 */
09936ccc 428 cpu_setstack(p, ap);
28db9b87
SL
429 (void) suword((caddr_t)ap, na-ne);
430 nc = 0;
9d4095a1
KM
431 cp = (char *) execargs;
432 cc = NCARGS;
29075cfd
KM
433 ps.ps_argvstr = (char *)ucp; /* first argv string */
434 ps.ps_nargvstr = na - ne; /* argc */
28db9b87
SL
435 for (;;) {
436 ap += NBPW;
f3aaea26 437 if (na == ne) {
28db9b87
SL
438 (void) suword((caddr_t)ap, 0);
439 ap += NBPW;
29075cfd
KM
440 ps.ps_envstr = (char *)ucp;
441 ps.ps_nenvstr = ne;
28db9b87
SL
442 }
443 if (--na < 0)
444 break;
445 (void) suword((caddr_t)ap, ucp);
446 do {
8011f5df
MK
447 error = copyoutstr(cp, (caddr_t)ucp, (unsigned)cc,
448 &len);
72d4f41a
SL
449 ucp += len;
450 cp += len;
451 nc += len;
452 cc -= len;
9e73a4eb 453 } while (error == ENAMETOOLONG);
72d4f41a
SL
454 if (error == EFAULT)
455 panic("exec: EFAULT");
28db9b87
SL
456 }
457 (void) suword((caddr_t)ap, 0);
29075cfd 458 (void) copyout((caddr_t)&ps, (caddr_t)PS_STRINGS, sizeof(ps));
ce66cb03 459
c9714ae3 460 execsigs(p);
ce66cb03 461
5e00df3b 462 for (nc = fdp->fd_lastfile; nc >= 0; --nc) {
605f1ab4
MK
463 if (fdp->fd_ofileflags[nc] & UF_EXCLOSE) {
464 (void) closef(fdp->fd_ofiles[nc], p);
465 fdp->fd_ofiles[nc] = NULL;
466 fdp->fd_ofileflags[nc] = 0;
8429d022
MK
467 if (nc < fdp->fd_freefile)
468 fdp->fd_freefile = nc;
ce66cb03 469 }
605f1ab4 470 fdp->fd_ofileflags[nc] &= ~UF_MAPPED;
ce66cb03 471 }
605f1ab4
MK
472 /*
473 * Adjust fd_lastfile to account for descriptors closed above.
474 * Don't decrement fd_lastfile past 0, as it's unsigned.
475 */
476 while (fdp->fd_lastfile > 0 && fdp->fd_ofiles[fdp->fd_lastfile] == NULL)
5e00df3b 477 fdp->fd_lastfile--;
54955369 478 setregs(p, exdata.ex_exec.a_entry, retval);
75a969a7 479#ifdef COPY_SIGCODE
9d4095a1
KM
480 /*
481 * Install sigcode at top of user stack.
482 */
29075cfd 483 copyout((caddr_t)sigcode, (caddr_t)PS_STRINGS - szsigcode, szsigcode);
75a969a7 484#endif
715baff1
KM
485 /*
486 * Remember file name for accounting.
487 */
8429d022 488 p->p_acflag &= ~AFORK;
62ce54a4
KM
489 if (nd.ni_cnd.cn_namelen > MAXCOMLEN)
490 nd.ni_cnd.cn_namelen = MAXCOMLEN;
491 bcopy((caddr_t)nd.ni_cnd.cn_nameptr, (caddr_t)p->p_comm,
0a5745b2 492 (unsigned)nd.ni_cnd.cn_namelen);
62ce54a4 493 p->p_comm[nd.ni_cnd.cn_namelen] = '\0';
75a969a7 494 cpu_exec(p);
28db9b87 495bad:
62ce54a4 496 FREE(nd.ni_cnd.cn_pnbuf, M_NAMEI);
9d4095a1
KM
497 if (execargs)
498 kmem_free_wakeup(exec_map, execargs, NCARGS);
ec67a3ce 499#endif SECSIZE
c4ec2128
KM
500 if (vp)
501 vput(vp);
d9c2f47f 502 return (error);
28db9b87
SL
503}
504
505/*
506 * Read in and set up memory for executed file.
507 */
0a5745b2 508getxfile(p, vp, ep, paged, ssize, uid, gid)
c9714ae3 509 register struct proc *p;
c4ec2128 510 register struct vnode *vp;
9fd50f35 511 register struct exec *ep;
0a5745b2 512 int paged, ssize, uid, gid;
28db9b87 513{
8429d022 514 register struct ucred *cred = p->p_ucred;
0a5745b2
CT
515 register struct vmspace *vm = p->p_vmspace;
516 vm_offset_t addr;
517 vm_size_t xts, size;
518 segsz_t ds;
93422d4b 519 off_t toff;
9d4095a1 520 int error = 0;
28db9b87 521
93422d4b 522#ifdef HPUXCOMPAT
d59f854f
KM
523 if (ep->a_mid == MID_HPUX)
524 toff = paged ? CLBYTES : sizeof(struct hpux_exec);
525 else
93422d4b 526#endif
f0729cac
RC
527#ifdef COFF
528 toff = N_TXTOFF(*ep);
529#else
0a5745b2
CT
530#ifdef sparc
531 if (ep->a_mid == MID_SUN_SPARC)
532 toff = paged ? 0 : sizeof(struct exec);
533 else
534#endif
34dc7acb 535 if (paged)
1a7b5528
RC
536#ifdef mips
537 toff = 0;
538#else
9d4095a1 539 toff = CLBYTES;
1a7b5528 540#endif
9d4095a1
KM
541 else
542 toff = sizeof (struct exec);
f0729cac 543#endif
c4ec2128 544 if (ep->a_text != 0 && (vp->v_flag & VTEXT) == 0 &&
82177e7b
KM
545 vp->v_writecount != 0)
546 return (ETXTBSY);
28db9b87
SL
547
548 /*
549 * Compute text and data sizes and make sure not too large.
0a5745b2
CT
550 * Text size is rounded to an ``ld page''; data+bss is left
551 * in machine pages. Check data and bss separately as they
552 * may overflow when summed together. (XXX not done yet)
28db9b87 553 */
0a5745b2 554 xts = roundup(ep->a_text, __LDPGSZ);
f3aaea26 555 ds = clrnd(btoc(ep->a_data + ep->a_bss));
605f1ab4
MK
556
557 /*
558 * If we're sharing the address space, allocate a new space
559 * and release our reference to the old one. Otherwise,
560 * empty out the existing vmspace.
561 */
0a5745b2
CT
562#ifdef sparc
563 kill_user_windows(p); /* before addrs go away */
564#endif
605f1ab4 565 if (vm->vm_refcnt > 1) {
54955369
WN
566 p->p_vmspace = vmspace_alloc(VM_MIN_ADDRESS,
567 VM_MAXUSER_ADDRESS, 1);
605f1ab4
MK
568 vmspace_free(vm);
569 vm = p->p_vmspace;
570 } else {
9d4095a1 571#ifdef SYSVSHM
605f1ab4
MK
572 if (vm->vm_shm)
573 shmexit(p);
9d4095a1 574#endif
54955369
WN
575 (void) vm_map_remove(&vm->vm_map, VM_MIN_ADDRESS,
576 VM_MAXUSER_ADDRESS);
605f1ab4 577 }
28db9b87 578 /*
8429d022 579 * If parent is waiting for us to exec or exit,
cf5ef508 580 * P_PPWAIT will be set; clear it and wakeup parent.
28db9b87 581 */
cf5ef508
KB
582 if (p->p_flag & P_PPWAIT) {
583 p->p_flag &= ~P_PPWAIT;
8429d022 584 wakeup((caddr_t) p->p_pptr);
28db9b87 585 }
4beec620 586#if defined(HP380) || defined(LUNA2)
9921f05f
MH
587 /* default to copyback caching on 68040 */
588 if (mmutype == MMU_68040)
589 p->p_md.md_flags |= (MDP_CCBDATA|MDP_CCBSTACK);
590#endif
93422d4b 591#ifdef HPUXCOMPAT
9921f05f
MH
592 p->p_md.md_flags &= ~(MDP_HPUX|MDP_HPUXMMAP);
593 /* note that we are an HP-UX binary */
93422d4b 594 if (ep->a_mid == MID_HPUX)
9921f05f
MH
595 p->p_md.md_flags |= MDP_HPUX;
596 /* deal with miscellaneous attributes */
597 if (ep->a_trsize & HPUXM_VALID) {
598 if (ep->a_trsize & HPUXM_DATAWT)
599 p->p_md.md_flags &= ~MDP_CCBDATA;
600 if (ep->a_trsize & HPUXM_STKWT)
601 p->p_md.md_flags &= ~MDP_CCBSTACK;
602 }
f0729cac
RC
603#endif
604#ifdef ULTRIXCOMPAT
605 /*
606 * Always start out as an ULTRIX process.
607 * A system call in crt0.o will change us to BSD system calls later.
608 */
609 p->p_md.md_flags |= MDP_ULTRIX;
93422d4b 610#endif
cf5ef508 611 p->p_flag |= P_EXEC;
f0729cac 612#ifndef COFF
9d4095a1 613 addr = VM_MIN_ADDRESS;
0a5745b2 614 if (vm_allocate(&vm->vm_map, &addr, xts + ctob(ds), FALSE)) {
9d4095a1
KM
615 uprintf("Cannot allocate text+data space\n");
616 error = ENOMEM; /* XXX */
617 goto badmap;
618 }
f0729cac 619 vm->vm_taddr = (caddr_t)VM_MIN_ADDRESS;
0a5745b2 620 vm->vm_daddr = (caddr_t)(VM_MIN_ADDRESS + xts);
f0729cac
RC
621#else /* COFF */
622 addr = (vm_offset_t)ep->ex_aout.codeStart;
623 vm->vm_taddr = (caddr_t)addr;
0a5745b2 624 if (vm_allocate(&vm->vm_map, &addr, xts, FALSE)) {
f0729cac
RC
625 uprintf("Cannot allocate text space\n");
626 error = ENOMEM; /* XXX */
627 goto badmap;
628 }
629 addr = (vm_offset_t)ep->ex_aout.heapStart;
630 vm->vm_daddr = (caddr_t)addr;
631 if (vm_allocate(&vm->vm_map, &addr, round_page(ctob(ds)), FALSE)) {
632 uprintf("Cannot allocate data space\n");
633 error = ENOMEM; /* XXX */
634 goto badmap;
635 }
636#endif /* COFF */
9d4095a1 637 size = round_page(MAXSSIZ); /* XXX */
4021f565
WN
638#ifdef i386
639 addr = trunc_page(USRSTACK - size) - NBPG; /* XXX */
640#else
54955369 641 addr = trunc_page(USRSTACK - size);
4021f565 642#endif
8429d022 643 if (vm_allocate(&vm->vm_map, &addr, size, FALSE)) {
9d4095a1
KM
644 uprintf("Cannot allocate stack space\n");
645 error = ENOMEM; /* XXX */
646 goto badmap;
647 }
54955369
WN
648 size -= round_page(p->p_rlimit[RLIMIT_STACK].rlim_cur);
649 if (vm_map_protect(&vm->vm_map, addr, addr+size, VM_PROT_NONE, FALSE)) {
650 uprintf("Cannot protect stack space\n");
651 error = ENOMEM;
652 goto badmap;
653 }
8429d022 654 vm->vm_maxsaddr = (caddr_t)addr;
28db9b87 655
34dc7acb 656 if (paged == 0) {
605f1ab4
MK
657 /*
658 * Read in data segment.
659 */
8429d022
MK
660 (void) vn_rdwr(UIO_READ, vp, vm->vm_daddr, (int) ep->a_data,
661 (off_t)(toff + ep->a_text), UIO_USERSPACE,
f254ddb7 662 (IO_UNIT|IO_NODELOCKED), cred, (int *)0, p);
605f1ab4
MK
663 /*
664 * Read in text segment if necessary (0410),
665 * and read-protect it.
666 */
9d4095a1 667 if (ep->a_text > 0) {
8429d022 668 error = vn_rdwr(UIO_READ, vp, vm->vm_taddr,
451df175
KM
669 (int)ep->a_text, toff, UIO_USERSPACE,
670 (IO_UNIT|IO_NODELOCKED), cred, (int *)0, p);
671 (void) vm_map_protect(&vm->vm_map,
672 (vm_offset_t)vm->vm_taddr,
673 (vm_offset_t)vm->vm_taddr + trunc_page(ep->a_text),
674 VM_PROT_READ|VM_PROT_EXECUTE, FALSE);
9d4095a1
KM
675 }
676 } else {
677 /*
678 * Allocate a region backed by the exec'ed vnode.
679 */
f0729cac 680#ifndef COFF
9d4095a1 681 addr = VM_MIN_ADDRESS;
0a5745b2 682 size = round_page(xts + ep->a_data);
79f39708
MH
683 error = vm_mmap(&vm->vm_map, &addr, size,
684 VM_PROT_ALL, VM_PROT_ALL,
a24ecba5 685 MAP_COPY|MAP_FIXED,
8429d022 686 (caddr_t)vp, (vm_offset_t)toff);
0a5745b2 687 (void) vm_map_protect(&vm->vm_map, addr, addr + xts,
8429d022 688 VM_PROT_READ|VM_PROT_EXECUTE, FALSE);
f0729cac
RC
689#else /* COFF */
690 addr = (vm_offset_t)vm->vm_taddr;
0a5745b2 691 size = xts;
f0729cac 692 error = vm_mmap(&vm->vm_map, &addr, size,
79f39708 693 VM_PROT_READ|VM_PROT_EXECUTE, VM_PROT_ALL,
a24ecba5 694 MAP_COPY|MAP_FIXED,
f0729cac
RC
695 (caddr_t)vp, (vm_offset_t)toff);
696 toff += size;
697 addr = (vm_offset_t)vm->vm_daddr;
698 size = round_page(ep->a_data);
79f39708
MH
699 error = vm_mmap(&vm->vm_map, &addr, size,
700 VM_PROT_ALL, VM_PROT_ALL,
a24ecba5 701 MAP_COPY|MAP_FIXED,
f0729cac
RC
702 (caddr_t)vp, (vm_offset_t)toff);
703#endif /* COFF */
605f1ab4 704 vp->v_flag |= VTEXT;
9d4095a1 705 }
9d4095a1 706 if (error) {
0a5745b2 707badmap:
055fc5f3 708 killproc(p, "VM allocation in exec");
cf5ef508 709 p->p_flag |= P_NOSWAP;
9d4095a1 710 return(error);
fb1db32c 711 }
28db9b87 712
28db9b87
SL
713 /*
714 * set SUID/SGID protections, if no tracing
715 */
cf5ef508
KB
716 p->p_flag &= ~P_SUGID;
717 if ((p->p_flag & P_TRACED) == 0) {
7c9a1d1f 718 if (uid != cred->cr_uid || gid != cred->cr_gid) {
8429d022 719 p->p_ucred = cred = crcopy(cred);
389d05a7 720#ifdef KTRACE
7c9a1d1f
MT
721 /*
722 * If process is being ktraced, turn off - unless
723 * root set it.
724 */
725 if (p->p_tracep && !(p->p_traceflag & KTRFAC_ROOT)) {
726 vrele(p->p_tracep);
727 p->p_tracep = NULL;
728 p->p_traceflag = 0;
729 }
389d05a7 730#endif
0a5745b2
CT
731 cred->cr_uid = uid;
732 cred->cr_gid = gid;
cf5ef508 733 p->p_flag |= P_SUGID;
7c9a1d1f 734 }
28db9b87 735 } else
ba7abd07 736 psignal(p, SIGTRAP);
8429d022
MK
737 p->p_cred->p_svuid = cred->cr_uid;
738 p->p_cred->p_svgid = cred->cr_gid;
0a5745b2 739 vm->vm_tsize = btoc(xts);
8429d022 740 vm->vm_dsize = ds;
916f93da 741 vm->vm_ssize = btoc(ssize);
cf5ef508 742 if (p->p_flag & P_PROFIL)
e0ef57b1 743 stopprofclock(p);
fb1db32c 744#if defined(tahoe)
75a969a7
MK
745 /* move this when tahoe cpu_exec is created */
746 p->p_addr->u_pcb.pcb_savacc.faddr = (float *)NULL;
fb1db32c 747#endif
c9714ae3 748 return (0);
28db9b87 749}