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