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