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