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