Commit | Line | Data |
---|---|---|
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 | * | |
7dcb2b7d | 12 | * @(#)kern_exec.c 8.8 (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 |
49 | extern 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 |
58 | execve(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); |
2881f082 | 102 | VOP_LOCK(vp); |
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); |
a9892ae9 | 296 | VOP_LOCK(vp); |
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 CD |
336 | if (ap == NULL && SCARG(uap, envp)) { |
337 | SCARG(uap, envp) = NULL; | |
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 | 500 | bad: |
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 | 513 | getxfile(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 | 712 | badmap: |
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 | } |