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