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 | * | |
adb35f79 | 12 | * @(#)kern_exec.c 8.6 (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> | |
28db9b87 | 29 | |
38a01dbe KB |
30 | #include <machine/cpu.h> |
31 | #include <machine/reg.h> | |
d301d150 | 32 | |
38a01dbe KB |
33 | #include <sys/mman.h> |
34 | #include <vm/vm.h> | |
35 | #include <vm/vm_param.h> | |
36 | #include <vm/vm_map.h> | |
37 | #include <vm/vm_kern.h> | |
38 | #include <vm/vm_pager.h> | |
9d4095a1 | 39 | |
38a01dbe | 40 | #include <sys/signalvar.h> |
605f1ab4 | 41 | |
93422d4b | 42 | #ifdef HPUXCOMPAT |
38a01dbe KB |
43 | #include <sys/user.h> /* for pcb */ |
44 | #include <hp/hpux/hpux_exec.h> | |
93422d4b KM |
45 | #endif |
46 | ||
75a969a7 MK |
47 | #ifdef COPY_SIGCODE |
48 | extern char sigcode[], esigcode[]; | |
49 | #define szsigcode (esigcode - sigcode) | |
50 | #else | |
51 | #define szsigcode 0 | |
52 | #endif | |
53 | ||
8429d022 MK |
54 | /* |
55 | * exec system call | |
56 | */ | |
c9714ae3 KM |
57 | execve(p, uap, retval) |
58 | register struct proc *p; | |
9e97623a | 59 | register struct execve_args *uap; |
c9714ae3 | 60 | int *retval; |
28db9b87 | 61 | { |
8429d022 | 62 | register struct ucred *cred = p->p_ucred; |
5e00df3b | 63 | register struct filedesc *fdp = p->p_fd; |
0a5745b2 | 64 | int na, ne, ucp, ap, cc, ssize; |
5e00df3b KM |
65 | register char *cp; |
66 | register int nc; | |
8011f5df | 67 | unsigned len; |
28db9b87 SL |
68 | int indir, uid, gid; |
69 | char *sharg; | |
c4ec2128 | 70 | struct vnode *vp; |
34dc7acb | 71 | int resid, error, paged = 0; |
f0729cac | 72 | vm_offset_t execargs = 0; |
c4ec2128 | 73 | struct vattr vattr; |
cb9392ae | 74 | char cfarg[MAXINTERP]; |
9fd50f35 | 75 | union { |
cb9392ae | 76 | char ex_shell[MAXINTERP]; /* #! and interpreter name */ |
9fd50f35 | 77 | struct exec ex_exec; |
93422d4b KM |
78 | #ifdef HPUXCOMPAT |
79 | struct hpux_exec ex_hexec; | |
80 | #endif | |
9fd50f35 | 81 | } exdata; |
93422d4b KM |
82 | #ifdef HPUXCOMPAT |
83 | struct hpux_exec hhead; | |
84 | #endif | |
8429d022 | 85 | struct nameidata nd; |
29075cfd | 86 | struct ps_strings ps; |
ec67a3ce MK |
87 | #ifdef SECSIZE |
88 | extern long argdbsize; /* XXX */ | |
89 | #endif SECSIZE | |
28db9b87 | 90 | |
2881f082 | 91 | NDINIT(&nd, LOOKUP, FOLLOW | SAVENAME, UIO_USERSPACE, |
62ce54a4 KM |
92 | uap->fname, p); |
93 | if (error = namei(&nd)) | |
d9c2f47f | 94 | return (error); |
62ce54a4 | 95 | vp = nd.ni_vp; |
2881f082 KM |
96 | LEASE_CHECK(vp, p, cred, LEASE_READ); |
97 | VOP_LOCK(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; |
cf5ef508 | 117 | if ((p->p_flag & P_TRACED) && (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; |
a9892ae9 KM |
290 | LEASE_CHECK(vp, p, cred, LEASE_READ); |
291 | VOP_LOCK(vp); | |
f254ddb7 | 292 | if (error = VOP_GETATTR(vp, &vattr, cred, p)) |
c4ec2128 | 293 | goto bad; |
c9714ae3 KM |
294 | uid = cred->cr_uid; /* shell scripts can't be setuid */ |
295 | gid = cred->cr_gid; | |
28db9b87 SL |
296 | goto again; |
297 | } | |
298 | ||
299 | /* | |
300 | * Collect arguments on "file" in swap space. | |
301 | */ | |
302 | na = 0; | |
303 | ne = 0; | |
304 | nc = 0; | |
9d4095a1 KM |
305 | cc = NCARGS; |
306 | execargs = kmem_alloc_wait(exec_map, NCARGS); | |
f0729cac RC |
307 | #ifdef DIAGNOSTIC |
308 | if (execargs == (vm_offset_t)0) | |
309 | panic("execve: kmem_alloc_wait"); | |
310 | #endif | |
9d4095a1 | 311 | cp = (char *) execargs; |
f3aaea26 SL |
312 | /* |
313 | * Copy arguments into file in argdev area. | |
314 | */ | |
28db9b87 SL |
315 | if (uap->argp) for (;;) { |
316 | ap = NULL; | |
ce66cb03 MK |
317 | sharg = NULL; |
318 | if (indir && na == 0) { | |
62ce54a4 | 319 | sharg = nd.ni_cnd.cn_nameptr; |
ce66cb03 MK |
320 | ap = (int)sharg; |
321 | uap->argp++; /* ignore argv[0] */ | |
322 | } else if (indir && (na == 1 && cfarg[0])) { | |
323 | sharg = cfarg; | |
324 | ap = (int)sharg; | |
325 | } else if (indir && (na == 1 || na == 2 && cfarg[0])) | |
28db9b87 SL |
326 | ap = (int)uap->fname; |
327 | else if (uap->argp) { | |
328 | ap = fuword((caddr_t)uap->argp); | |
329 | uap->argp++; | |
330 | } | |
f3aaea26 | 331 | if (ap == NULL && uap->envp) { |
28db9b87 | 332 | uap->argp = NULL; |
f3aaea26 SL |
333 | if ((ap = fuword((caddr_t)uap->envp)) != NULL) |
334 | uap->envp++, ne++; | |
28db9b87 SL |
335 | } |
336 | if (ap == NULL) | |
337 | break; | |
338 | na++; | |
f3aaea26 | 339 | if (ap == -1) { |
c9714ae3 | 340 | error = EFAULT; |
9d4095a1 | 341 | goto bad; |
f3aaea26 | 342 | } |
28db9b87 | 343 | do { |
9d4095a1 KM |
344 | if (nc >= NCARGS-1) { |
345 | error = E2BIG; | |
346 | break; | |
28db9b87 | 347 | } |
ce66cb03 | 348 | if (sharg) { |
8011f5df | 349 | error = copystr(sharg, cp, (unsigned)cc, &len); |
ce66cb03 MK |
350 | sharg += len; |
351 | } else { | |
8011f5df MK |
352 | error = copyinstr((caddr_t)ap, cp, (unsigned)cc, |
353 | &len); | |
ce66cb03 MK |
354 | ap += len; |
355 | } | |
f3aaea26 SL |
356 | cp += len; |
357 | nc += len; | |
358 | cc -= len; | |
9e73a4eb | 359 | } while (error == ENAMETOOLONG); |
9d4095a1 KM |
360 | if (error) |
361 | goto bad; | |
28db9b87 | 362 | } |
0a5745b2 CT |
363 | |
364 | /* | |
365 | * XXX the following is excessively bogus | |
366 | * | |
367 | * Compute initial process stack size and location of argc | |
368 | * and character strings. `nc' is currently just the number | |
369 | * of characters of arg and env strings. | |
370 | * | |
29075cfd KM |
371 | * nc = size of ps_strings structure + |
372 | * size of signal code + | |
373 | * 4 bytes of NULL pointer + | |
374 | * nc, | |
375 | * rounded to nearest integer; | |
0a5745b2 CT |
376 | * ucp = USRSTACK - nc; [user characters pointer] |
377 | * apsize = padding (if any) + | |
378 | * 4 bytes of NULL pointer + | |
379 | * ne 4-byte pointers to env strings + | |
380 | * 4 bytes of NULL pointer + | |
381 | * (na-ne) 4-byte pointers to arg strings + | |
382 | * 4 bytes of argc; | |
383 | * (this is the same as nc + (na+3)*4) | |
384 | * ap = ucp - apsize; [user address of argc] | |
385 | * ssize = ssize + nc + machine-dependent space; | |
386 | */ | |
29075cfd | 387 | nc = (sizeof(ps) + szsigcode + 4 + nc + NBPW-1) & ~(NBPW - 1); |
e74c0572 | 388 | #if defined(sparc) || defined(mips) |
0a5745b2 | 389 | ucp = USRSTACK; |
e74c0572 | 390 | ssize = ALIGN(nc + (na + 3) * NBPW); |
0a5745b2 CT |
391 | ap = ucp - ssize; |
392 | ucp -= nc; | |
e74c0572 | 393 | #ifdef sparc |
0a5745b2 | 394 | ssize += sizeof(struct rwindow); |
e74c0572 | 395 | #endif |
0a5745b2 CT |
396 | #else |
397 | ssize = (na + 3) * NBPW; | |
398 | ucp = USRSTACK - nc; | |
399 | ap = ucp - ssize; | |
400 | ssize += nc; | |
401 | #endif | |
402 | error = getxfile(p, vp, &exdata.ex_exec, paged, ssize, uid, gid); | |
9d4095a1 | 403 | if (error) |
28db9b87 | 404 | goto bad; |
859437ef JSP |
405 | |
406 | /* take a reference to the new text vnode (for procfs) */ | |
407 | if (p->p_textvp) | |
408 | vrele(p->p_textvp); | |
409 | VREF(vp); | |
410 | p->p_textvp = vp; | |
411 | ||
c4ec2128 KM |
412 | vput(vp); |
413 | vp = NULL; | |
28db9b87 | 414 | |
93422d4b KM |
415 | #ifdef HPUXCOMPAT |
416 | /* | |
417 | * We are now committed to the exec so we can save the exec | |
418 | * header in the pcb where we can dump it if necessary in core() | |
419 | */ | |
9921f05f | 420 | if (p->p_md.md_flags & MDP_HPUX) |
93422d4b | 421 | bcopy((caddr_t)&hhead, |
9921f05f | 422 | (caddr_t)p->p_addr->u_md.md_exec, sizeof hhead); |
93422d4b KM |
423 | #endif |
424 | ||
28db9b87 | 425 | /* |
f3aaea26 | 426 | * Copy back arglist. |
28db9b87 | 427 | */ |
09936ccc | 428 | cpu_setstack(p, ap); |
28db9b87 SL |
429 | (void) suword((caddr_t)ap, na-ne); |
430 | nc = 0; | |
9d4095a1 KM |
431 | cp = (char *) execargs; |
432 | cc = NCARGS; | |
29075cfd KM |
433 | ps.ps_argvstr = (char *)ucp; /* first argv string */ |
434 | ps.ps_nargvstr = na - ne; /* argc */ | |
28db9b87 SL |
435 | for (;;) { |
436 | ap += NBPW; | |
f3aaea26 | 437 | if (na == ne) { |
28db9b87 SL |
438 | (void) suword((caddr_t)ap, 0); |
439 | ap += NBPW; | |
29075cfd KM |
440 | ps.ps_envstr = (char *)ucp; |
441 | ps.ps_nenvstr = ne; | |
28db9b87 SL |
442 | } |
443 | if (--na < 0) | |
444 | break; | |
445 | (void) suword((caddr_t)ap, ucp); | |
446 | do { | |
8011f5df MK |
447 | error = copyoutstr(cp, (caddr_t)ucp, (unsigned)cc, |
448 | &len); | |
72d4f41a SL |
449 | ucp += len; |
450 | cp += len; | |
451 | nc += len; | |
452 | cc -= len; | |
9e73a4eb | 453 | } while (error == ENAMETOOLONG); |
72d4f41a SL |
454 | if (error == EFAULT) |
455 | panic("exec: EFAULT"); | |
28db9b87 SL |
456 | } |
457 | (void) suword((caddr_t)ap, 0); | |
29075cfd | 458 | (void) copyout((caddr_t)&ps, (caddr_t)PS_STRINGS, sizeof(ps)); |
ce66cb03 | 459 | |
c9714ae3 | 460 | execsigs(p); |
ce66cb03 | 461 | |
5e00df3b | 462 | for (nc = fdp->fd_lastfile; nc >= 0; --nc) { |
605f1ab4 MK |
463 | if (fdp->fd_ofileflags[nc] & UF_EXCLOSE) { |
464 | (void) closef(fdp->fd_ofiles[nc], p); | |
465 | fdp->fd_ofiles[nc] = NULL; | |
466 | fdp->fd_ofileflags[nc] = 0; | |
8429d022 MK |
467 | if (nc < fdp->fd_freefile) |
468 | fdp->fd_freefile = nc; | |
ce66cb03 | 469 | } |
605f1ab4 | 470 | fdp->fd_ofileflags[nc] &= ~UF_MAPPED; |
ce66cb03 | 471 | } |
605f1ab4 MK |
472 | /* |
473 | * Adjust fd_lastfile to account for descriptors closed above. | |
474 | * Don't decrement fd_lastfile past 0, as it's unsigned. | |
475 | */ | |
476 | while (fdp->fd_lastfile > 0 && fdp->fd_ofiles[fdp->fd_lastfile] == NULL) | |
5e00df3b | 477 | fdp->fd_lastfile--; |
54955369 | 478 | setregs(p, exdata.ex_exec.a_entry, retval); |
75a969a7 | 479 | #ifdef COPY_SIGCODE |
9d4095a1 KM |
480 | /* |
481 | * Install sigcode at top of user stack. | |
482 | */ | |
29075cfd | 483 | copyout((caddr_t)sigcode, (caddr_t)PS_STRINGS - szsigcode, szsigcode); |
75a969a7 | 484 | #endif |
715baff1 KM |
485 | /* |
486 | * Remember file name for accounting. | |
487 | */ | |
8429d022 | 488 | p->p_acflag &= ~AFORK; |
62ce54a4 KM |
489 | if (nd.ni_cnd.cn_namelen > MAXCOMLEN) |
490 | nd.ni_cnd.cn_namelen = MAXCOMLEN; | |
491 | bcopy((caddr_t)nd.ni_cnd.cn_nameptr, (caddr_t)p->p_comm, | |
0a5745b2 | 492 | (unsigned)nd.ni_cnd.cn_namelen); |
62ce54a4 | 493 | p->p_comm[nd.ni_cnd.cn_namelen] = '\0'; |
75a969a7 | 494 | cpu_exec(p); |
28db9b87 | 495 | bad: |
62ce54a4 | 496 | FREE(nd.ni_cnd.cn_pnbuf, M_NAMEI); |
9d4095a1 KM |
497 | if (execargs) |
498 | kmem_free_wakeup(exec_map, execargs, NCARGS); | |
ec67a3ce | 499 | #endif SECSIZE |
c4ec2128 KM |
500 | if (vp) |
501 | vput(vp); | |
d9c2f47f | 502 | return (error); |
28db9b87 SL |
503 | } |
504 | ||
505 | /* | |
506 | * Read in and set up memory for executed file. | |
507 | */ | |
0a5745b2 | 508 | getxfile(p, vp, ep, paged, ssize, uid, gid) |
c9714ae3 | 509 | register struct proc *p; |
c4ec2128 | 510 | register struct vnode *vp; |
9fd50f35 | 511 | register struct exec *ep; |
0a5745b2 | 512 | int paged, ssize, uid, gid; |
28db9b87 | 513 | { |
8429d022 | 514 | register struct ucred *cred = p->p_ucred; |
0a5745b2 CT |
515 | register struct vmspace *vm = p->p_vmspace; |
516 | vm_offset_t addr; | |
517 | vm_size_t xts, size; | |
518 | segsz_t ds; | |
93422d4b | 519 | off_t toff; |
9d4095a1 | 520 | int error = 0; |
28db9b87 | 521 | |
93422d4b | 522 | #ifdef HPUXCOMPAT |
d59f854f KM |
523 | if (ep->a_mid == MID_HPUX) |
524 | toff = paged ? CLBYTES : sizeof(struct hpux_exec); | |
525 | else | |
93422d4b | 526 | #endif |
f0729cac RC |
527 | #ifdef COFF |
528 | toff = N_TXTOFF(*ep); | |
529 | #else | |
0a5745b2 CT |
530 | #ifdef sparc |
531 | if (ep->a_mid == MID_SUN_SPARC) | |
532 | toff = paged ? 0 : sizeof(struct exec); | |
533 | else | |
534 | #endif | |
34dc7acb | 535 | if (paged) |
1a7b5528 RC |
536 | #ifdef mips |
537 | toff = 0; | |
538 | #else | |
9d4095a1 | 539 | toff = CLBYTES; |
1a7b5528 | 540 | #endif |
9d4095a1 KM |
541 | else |
542 | toff = sizeof (struct exec); | |
f0729cac | 543 | #endif |
c4ec2128 | 544 | if (ep->a_text != 0 && (vp->v_flag & VTEXT) == 0 && |
82177e7b KM |
545 | vp->v_writecount != 0) |
546 | return (ETXTBSY); | |
28db9b87 SL |
547 | |
548 | /* | |
549 | * Compute text and data sizes and make sure not too large. | |
0a5745b2 CT |
550 | * Text size is rounded to an ``ld page''; data+bss is left |
551 | * in machine pages. Check data and bss separately as they | |
552 | * may overflow when summed together. (XXX not done yet) | |
28db9b87 | 553 | */ |
0a5745b2 | 554 | xts = roundup(ep->a_text, __LDPGSZ); |
f3aaea26 | 555 | ds = clrnd(btoc(ep->a_data + ep->a_bss)); |
605f1ab4 MK |
556 | |
557 | /* | |
558 | * If we're sharing the address space, allocate a new space | |
559 | * and release our reference to the old one. Otherwise, | |
560 | * empty out the existing vmspace. | |
561 | */ | |
0a5745b2 CT |
562 | #ifdef sparc |
563 | kill_user_windows(p); /* before addrs go away */ | |
564 | #endif | |
605f1ab4 | 565 | if (vm->vm_refcnt > 1) { |
54955369 WN |
566 | p->p_vmspace = vmspace_alloc(VM_MIN_ADDRESS, |
567 | VM_MAXUSER_ADDRESS, 1); | |
605f1ab4 MK |
568 | vmspace_free(vm); |
569 | vm = p->p_vmspace; | |
570 | } else { | |
9d4095a1 | 571 | #ifdef SYSVSHM |
605f1ab4 MK |
572 | if (vm->vm_shm) |
573 | shmexit(p); | |
9d4095a1 | 574 | #endif |
54955369 WN |
575 | (void) vm_map_remove(&vm->vm_map, VM_MIN_ADDRESS, |
576 | VM_MAXUSER_ADDRESS); | |
605f1ab4 | 577 | } |
28db9b87 | 578 | /* |
8429d022 | 579 | * If parent is waiting for us to exec or exit, |
cf5ef508 | 580 | * P_PPWAIT will be set; clear it and wakeup parent. |
28db9b87 | 581 | */ |
cf5ef508 KB |
582 | if (p->p_flag & P_PPWAIT) { |
583 | p->p_flag &= ~P_PPWAIT; | |
8429d022 | 584 | wakeup((caddr_t) p->p_pptr); |
28db9b87 | 585 | } |
4beec620 | 586 | #if defined(HP380) || defined(LUNA2) |
9921f05f MH |
587 | /* default to copyback caching on 68040 */ |
588 | if (mmutype == MMU_68040) | |
589 | p->p_md.md_flags |= (MDP_CCBDATA|MDP_CCBSTACK); | |
590 | #endif | |
93422d4b | 591 | #ifdef HPUXCOMPAT |
9921f05f MH |
592 | p->p_md.md_flags &= ~(MDP_HPUX|MDP_HPUXMMAP); |
593 | /* note that we are an HP-UX binary */ | |
93422d4b | 594 | if (ep->a_mid == MID_HPUX) |
9921f05f MH |
595 | p->p_md.md_flags |= MDP_HPUX; |
596 | /* deal with miscellaneous attributes */ | |
597 | if (ep->a_trsize & HPUXM_VALID) { | |
598 | if (ep->a_trsize & HPUXM_DATAWT) | |
599 | p->p_md.md_flags &= ~MDP_CCBDATA; | |
600 | if (ep->a_trsize & HPUXM_STKWT) | |
601 | p->p_md.md_flags &= ~MDP_CCBSTACK; | |
602 | } | |
f0729cac RC |
603 | #endif |
604 | #ifdef ULTRIXCOMPAT | |
605 | /* | |
606 | * Always start out as an ULTRIX process. | |
607 | * A system call in crt0.o will change us to BSD system calls later. | |
608 | */ | |
609 | p->p_md.md_flags |= MDP_ULTRIX; | |
93422d4b | 610 | #endif |
cf5ef508 | 611 | p->p_flag |= P_EXEC; |
f0729cac | 612 | #ifndef COFF |
9d4095a1 | 613 | addr = VM_MIN_ADDRESS; |
0a5745b2 | 614 | if (vm_allocate(&vm->vm_map, &addr, xts + ctob(ds), FALSE)) { |
9d4095a1 KM |
615 | uprintf("Cannot allocate text+data space\n"); |
616 | error = ENOMEM; /* XXX */ | |
617 | goto badmap; | |
618 | } | |
f0729cac | 619 | vm->vm_taddr = (caddr_t)VM_MIN_ADDRESS; |
0a5745b2 | 620 | vm->vm_daddr = (caddr_t)(VM_MIN_ADDRESS + xts); |
f0729cac RC |
621 | #else /* COFF */ |
622 | addr = (vm_offset_t)ep->ex_aout.codeStart; | |
623 | vm->vm_taddr = (caddr_t)addr; | |
0a5745b2 | 624 | if (vm_allocate(&vm->vm_map, &addr, xts, FALSE)) { |
f0729cac RC |
625 | uprintf("Cannot allocate text space\n"); |
626 | error = ENOMEM; /* XXX */ | |
627 | goto badmap; | |
628 | } | |
629 | addr = (vm_offset_t)ep->ex_aout.heapStart; | |
630 | vm->vm_daddr = (caddr_t)addr; | |
631 | if (vm_allocate(&vm->vm_map, &addr, round_page(ctob(ds)), FALSE)) { | |
632 | uprintf("Cannot allocate data space\n"); | |
633 | error = ENOMEM; /* XXX */ | |
634 | goto badmap; | |
635 | } | |
636 | #endif /* COFF */ | |
9d4095a1 | 637 | size = round_page(MAXSSIZ); /* XXX */ |
4021f565 WN |
638 | #ifdef i386 |
639 | addr = trunc_page(USRSTACK - size) - NBPG; /* XXX */ | |
640 | #else | |
54955369 | 641 | addr = trunc_page(USRSTACK - size); |
4021f565 | 642 | #endif |
8429d022 | 643 | if (vm_allocate(&vm->vm_map, &addr, size, FALSE)) { |
9d4095a1 KM |
644 | uprintf("Cannot allocate stack space\n"); |
645 | error = ENOMEM; /* XXX */ | |
646 | goto badmap; | |
647 | } | |
54955369 WN |
648 | size -= round_page(p->p_rlimit[RLIMIT_STACK].rlim_cur); |
649 | if (vm_map_protect(&vm->vm_map, addr, addr+size, VM_PROT_NONE, FALSE)) { | |
650 | uprintf("Cannot protect stack space\n"); | |
651 | error = ENOMEM; | |
652 | goto badmap; | |
653 | } | |
8429d022 | 654 | vm->vm_maxsaddr = (caddr_t)addr; |
28db9b87 | 655 | |
34dc7acb | 656 | if (paged == 0) { |
605f1ab4 MK |
657 | /* |
658 | * Read in data segment. | |
659 | */ | |
8429d022 MK |
660 | (void) vn_rdwr(UIO_READ, vp, vm->vm_daddr, (int) ep->a_data, |
661 | (off_t)(toff + ep->a_text), UIO_USERSPACE, | |
f254ddb7 | 662 | (IO_UNIT|IO_NODELOCKED), cred, (int *)0, p); |
605f1ab4 MK |
663 | /* |
664 | * Read in text segment if necessary (0410), | |
665 | * and read-protect it. | |
666 | */ | |
9d4095a1 | 667 | if (ep->a_text > 0) { |
8429d022 | 668 | error = vn_rdwr(UIO_READ, vp, vm->vm_taddr, |
451df175 KM |
669 | (int)ep->a_text, toff, UIO_USERSPACE, |
670 | (IO_UNIT|IO_NODELOCKED), cred, (int *)0, p); | |
671 | (void) vm_map_protect(&vm->vm_map, | |
672 | (vm_offset_t)vm->vm_taddr, | |
673 | (vm_offset_t)vm->vm_taddr + trunc_page(ep->a_text), | |
674 | VM_PROT_READ|VM_PROT_EXECUTE, FALSE); | |
9d4095a1 KM |
675 | } |
676 | } else { | |
677 | /* | |
678 | * Allocate a region backed by the exec'ed vnode. | |
679 | */ | |
f0729cac | 680 | #ifndef COFF |
9d4095a1 | 681 | addr = VM_MIN_ADDRESS; |
0a5745b2 | 682 | size = round_page(xts + ep->a_data); |
79f39708 MH |
683 | error = vm_mmap(&vm->vm_map, &addr, size, |
684 | VM_PROT_ALL, VM_PROT_ALL, | |
a24ecba5 | 685 | MAP_COPY|MAP_FIXED, |
8429d022 | 686 | (caddr_t)vp, (vm_offset_t)toff); |
0a5745b2 | 687 | (void) vm_map_protect(&vm->vm_map, addr, addr + xts, |
8429d022 | 688 | VM_PROT_READ|VM_PROT_EXECUTE, FALSE); |
f0729cac RC |
689 | #else /* COFF */ |
690 | addr = (vm_offset_t)vm->vm_taddr; | |
0a5745b2 | 691 | size = xts; |
f0729cac | 692 | error = vm_mmap(&vm->vm_map, &addr, size, |
79f39708 | 693 | VM_PROT_READ|VM_PROT_EXECUTE, VM_PROT_ALL, |
a24ecba5 | 694 | MAP_COPY|MAP_FIXED, |
f0729cac RC |
695 | (caddr_t)vp, (vm_offset_t)toff); |
696 | toff += size; | |
697 | addr = (vm_offset_t)vm->vm_daddr; | |
698 | size = round_page(ep->a_data); | |
79f39708 MH |
699 | error = vm_mmap(&vm->vm_map, &addr, size, |
700 | VM_PROT_ALL, VM_PROT_ALL, | |
a24ecba5 | 701 | MAP_COPY|MAP_FIXED, |
f0729cac RC |
702 | (caddr_t)vp, (vm_offset_t)toff); |
703 | #endif /* COFF */ | |
605f1ab4 | 704 | vp->v_flag |= VTEXT; |
9d4095a1 | 705 | } |
9d4095a1 | 706 | if (error) { |
0a5745b2 | 707 | badmap: |
055fc5f3 | 708 | killproc(p, "VM allocation in exec"); |
cf5ef508 | 709 | p->p_flag |= P_NOSWAP; |
9d4095a1 | 710 | return(error); |
fb1db32c | 711 | } |
28db9b87 | 712 | |
28db9b87 SL |
713 | /* |
714 | * set SUID/SGID protections, if no tracing | |
715 | */ | |
cf5ef508 KB |
716 | p->p_flag &= ~P_SUGID; |
717 | if ((p->p_flag & P_TRACED) == 0) { | |
7c9a1d1f | 718 | if (uid != cred->cr_uid || gid != cred->cr_gid) { |
8429d022 | 719 | p->p_ucred = cred = crcopy(cred); |
389d05a7 | 720 | #ifdef KTRACE |
7c9a1d1f MT |
721 | /* |
722 | * If process is being ktraced, turn off - unless | |
723 | * root set it. | |
724 | */ | |
725 | if (p->p_tracep && !(p->p_traceflag & KTRFAC_ROOT)) { | |
726 | vrele(p->p_tracep); | |
727 | p->p_tracep = NULL; | |
728 | p->p_traceflag = 0; | |
729 | } | |
389d05a7 | 730 | #endif |
0a5745b2 CT |
731 | cred->cr_uid = uid; |
732 | cred->cr_gid = gid; | |
cf5ef508 | 733 | p->p_flag |= P_SUGID; |
7c9a1d1f | 734 | } |
28db9b87 | 735 | } else |
ba7abd07 | 736 | psignal(p, SIGTRAP); |
8429d022 MK |
737 | p->p_cred->p_svuid = cred->cr_uid; |
738 | p->p_cred->p_svgid = cred->cr_gid; | |
0a5745b2 | 739 | vm->vm_tsize = btoc(xts); |
8429d022 | 740 | vm->vm_dsize = ds; |
916f93da | 741 | vm->vm_ssize = btoc(ssize); |
cf5ef508 | 742 | if (p->p_flag & P_PROFIL) |
e0ef57b1 | 743 | stopprofclock(p); |
fb1db32c | 744 | #if defined(tahoe) |
75a969a7 MK |
745 | /* move this when tahoe cpu_exec is created */ |
746 | p->p_addr->u_pcb.pcb_savacc.faddr = (float *)NULL; | |
fb1db32c | 747 | #endif |
c9714ae3 | 748 | return (0); |
28db9b87 | 749 | } |