Commit | Line | Data |
---|---|---|
da7c5cc6 | 1 | /* |
c4ec2128 KM |
2 | * Copyright (c) 1982, 1986, 1989 Regents of the University of California. |
3 | * All rights reserved. | |
da7c5cc6 | 4 | * |
c4ec2128 KM |
5 | * Redistribution and use in source and binary forms are permitted |
6 | * provided that the above copyright notice and this paragraph are | |
7 | * duplicated in all such forms and that any documentation, | |
8 | * advertising materials, and other materials related to such | |
9 | * distribution and use acknowledge that the software was developed | |
10 | * by the University of California, Berkeley. The name of the | |
11 | * University may not be used to endorse or promote products derived | |
12 | * from this software without specific prior written permission. | |
13 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR | |
14 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | |
15 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | |
16 | * | |
d9c2f47f | 17 | * @(#)kern_exec.c 7.28 (Berkeley) %G% |
da7c5cc6 | 18 | */ |
28db9b87 | 19 | |
94368568 JB |
20 | #include "param.h" |
21 | #include "systm.h" | |
22 | #include "map.h" | |
d9c2f47f | 23 | #include "user.h" |
94368568 JB |
24 | #include "kernel.h" |
25 | #include "proc.h" | |
c4ec2128 KM |
26 | #include "mount.h" |
27 | #include "ucred.h" | |
28 | #include "malloc.h" | |
94368568 | 29 | #include "buf.h" |
c4ec2128 | 30 | #include "vnode.h" |
94368568 JB |
31 | #include "seg.h" |
32 | #include "vm.h" | |
33 | #include "text.h" | |
34 | #include "file.h" | |
35 | #include "uio.h" | |
36 | #include "acct.h" | |
37 | #include "exec.h" | |
28db9b87 | 38 | |
d301d150 KM |
39 | #include "machine/reg.h" |
40 | #include "machine/pte.h" | |
41 | #include "machine/psl.h" | |
42 | #include "machine/mtpr.h" | |
43 | ||
93422d4b KM |
44 | #ifdef HPUXCOMPAT |
45 | #include "../hpux/hpux_exec.h" | |
46 | #endif | |
47 | ||
28db9b87 SL |
48 | /* |
49 | * exec system call, with and without environments. | |
50 | */ | |
c9714ae3 KM |
51 | execv(p, uap, retval) |
52 | struct proc *p; | |
53 | struct args { | |
54 | char *fname; | |
55 | char **argp; | |
56 | char **envp; | |
57 | } *uap; | |
58 | int *retval; | |
28db9b87 | 59 | { |
c9714ae3 KM |
60 | |
61 | uap->envp = NULL; | |
d9c2f47f | 62 | return (execve(p, uap, retval)); |
28db9b87 SL |
63 | } |
64 | ||
c9714ae3 KM |
65 | /* ARGSUSED */ |
66 | execve(p, uap, retval) | |
67 | register struct proc *p; | |
68 | register struct args { | |
69 | char *fname; | |
70 | char **argp; | |
71 | char **envp; | |
72 | } *uap; | |
73 | int *retval; | |
28db9b87 SL |
74 | { |
75 | register nc; | |
76 | register char *cp; | |
77 | register struct buf *bp; | |
c4ec2128 | 78 | struct buf *tbp; |
8011f5df MK |
79 | int na, ne, ucp, ap, cc; |
80 | unsigned len; | |
28db9b87 SL |
81 | int indir, uid, gid; |
82 | char *sharg; | |
c4ec2128 | 83 | struct vnode *vp; |
28db9b87 | 84 | swblk_t bno; |
c4ec2128 | 85 | struct vattr vattr; |
28db9b87 | 86 | char cfname[MAXCOMLEN + 1]; |
cb9392ae | 87 | char cfarg[MAXINTERP]; |
9fd50f35 | 88 | union { |
cb9392ae | 89 | char ex_shell[MAXINTERP]; /* #! and interpreter name */ |
9fd50f35 | 90 | struct exec ex_exec; |
93422d4b KM |
91 | #ifdef HPUXCOMPAT |
92 | struct hpux_exec ex_hexec; | |
93 | #endif | |
9fd50f35 | 94 | } exdata; |
93422d4b KM |
95 | #ifdef HPUXCOMPAT |
96 | struct hpux_exec hhead; | |
97 | #endif | |
c9714ae3 | 98 | register struct ucred *cred = u.u_cred; |
715baff1 | 99 | register struct nameidata *ndp = &u.u_nd; |
93422d4b | 100 | int resid, error, flags = 0; |
ec67a3ce MK |
101 | #ifdef SECSIZE |
102 | extern long argdbsize; /* XXX */ | |
103 | #endif SECSIZE | |
28db9b87 | 104 | |
ba32f7c0 | 105 | start: |
c4ec2128 | 106 | ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; |
715baff1 | 107 | ndp->ni_segflg = UIO_USERSPACE; |
c9714ae3 KM |
108 | ndp->ni_dirp = uap->fname; |
109 | if (error = namei(ndp)) | |
d9c2f47f | 110 | return (error); |
c4ec2128 | 111 | vp = ndp->ni_vp; |
28db9b87 SL |
112 | bno = 0; |
113 | bp = 0; | |
114 | indir = 0; | |
c9714ae3 KM |
115 | uid = cred->cr_uid; |
116 | gid = cred->cr_gid; | |
117 | if (error = VOP_GETATTR(vp, &vattr, cred)) | |
c4ec2128 | 118 | goto bad; |
54fb9dc2 | 119 | if (vp->v_mount->mnt_flag & MNT_NOEXEC) { |
c9714ae3 | 120 | error = EACCES; |
c4ec2128 KM |
121 | goto bad; |
122 | } | |
54fb9dc2 | 123 | if ((vp->v_mount->mnt_flag & MNT_NOSUID) == 0) { |
c4ec2128 KM |
124 | if (vattr.va_mode & VSUID) |
125 | uid = vattr.va_uid; | |
126 | if (vattr.va_mode & VSGID) | |
127 | gid = vattr.va_gid; | |
128 | } | |
28db9b87 SL |
129 | |
130 | again: | |
c9714ae3 | 131 | if (error = VOP_ACCESS(vp, VEXEC, cred)) |
28db9b87 | 132 | goto bad; |
c9714ae3 | 133 | if ((p->p_flag & STRC) && (error = VOP_ACCESS(vp, VREAD, cred))) |
28db9b87 | 134 | goto bad; |
c4ec2128 KM |
135 | if (vp->v_type != VREG || |
136 | (vattr.va_mode & (VEXEC|(VEXEC>>3)|(VEXEC>>6))) == 0) { | |
c9714ae3 | 137 | error = EACCES; |
28db9b87 SL |
138 | goto bad; |
139 | } | |
140 | ||
141 | /* | |
f3aaea26 | 142 | * Read in first few bytes of file for segment sizes, magic number: |
c4ec2128 KM |
143 | * OMAGIC = plain executable |
144 | * NMAGIC = RO text | |
145 | * ZMAGIC = demand paged RO text | |
28db9b87 SL |
146 | * Also an ASCII line beginning with #! is |
147 | * the file name of a ``shell'' and arguments may be prepended | |
148 | * to the argument list if given here. | |
149 | * | |
150 | * SHELL NAMES ARE LIMITED IN LENGTH. | |
151 | * | |
152 | * ONLY ONE ARGUMENT MAY BE PASSED TO THE SHELL FROM | |
153 | * THE ASCII LINE. | |
154 | */ | |
9fd50f35 | 155 | exdata.ex_shell[0] = '\0'; /* for zero length files */ |
c9714ae3 KM |
156 | error = vn_rdwr(UIO_READ, vp, (caddr_t)&exdata, sizeof (exdata), |
157 | (off_t)0, UIO_SYSSPACE, (IO_UNIT|IO_NODELOCKED), cred, &resid); | |
158 | if (error) | |
28db9b87 | 159 | goto bad; |
28db9b87 | 160 | #ifndef lint |
ce66cb03 | 161 | if (resid > sizeof(exdata) - sizeof(exdata.ex_exec) && |
9fd50f35 | 162 | exdata.ex_shell[0] != '#') { |
c9714ae3 | 163 | error = ENOEXEC; |
28db9b87 SL |
164 | goto bad; |
165 | } | |
93422d4b KM |
166 | #endif |
167 | #if defined(hp300) | |
168 | switch ((int)exdata.ex_exec.a_mid) { | |
169 | ||
170 | /* | |
171 | * An ancient hp200 or hp300 binary, shouldn't happen anymore. | |
172 | * Mark as invalid. | |
173 | */ | |
174 | case MID_ZERO: | |
175 | exdata.ex_exec.a_magic = 0; | |
176 | break; | |
177 | ||
178 | /* | |
179 | * HP200 series has a smaller page size so we cannot | |
180 | * demand-load or even write protect text, so we just | |
181 | * treat as OMAGIC. | |
182 | */ | |
183 | case MID_HP200: | |
184 | exdata.ex_exec.a_magic = OMAGIC; | |
185 | break; | |
186 | ||
187 | case MID_HP300: | |
188 | break; | |
189 | ||
190 | #ifdef HPUXCOMPAT | |
191 | case MID_HPUX: | |
192 | /* | |
193 | * Save a.out header. This is eventually saved in the pcb, | |
194 | * but we cannot do that yet in case the exec fails before | |
195 | * the image is overlayed. | |
196 | */ | |
197 | bcopy((caddr_t)&exdata.ex_hexec, | |
198 | (caddr_t)&hhead, sizeof hhead); | |
199 | /* | |
200 | * If version number is 0x2bad this is a native BSD | |
201 | * binary created via the HPUX SGS. Should not be | |
202 | * treated as an HPUX binary. | |
203 | */ | |
204 | if (exdata.ex_hexec.ha_version != BSDVNUM) | |
205 | flags |= SHPUX; | |
206 | /* | |
207 | * Shuffle important fields to their BSD locations. | |
208 | * Note that the order in which this is done is important. | |
209 | */ | |
210 | exdata.ex_exec.a_text = exdata.ex_hexec.ha_text; | |
211 | exdata.ex_exec.a_data = exdata.ex_hexec.ha_data; | |
212 | exdata.ex_exec.a_bss = exdata.ex_hexec.ha_bss; | |
213 | exdata.ex_exec.a_entry = exdata.ex_hexec.ha_entry; | |
214 | /* | |
215 | * For ZMAGIC files, make sizes consistant with those | |
216 | * generated by BSD ld. | |
217 | */ | |
218 | if (exdata.ex_exec.a_magic == ZMAGIC) { | |
219 | exdata.ex_exec.a_text = | |
220 | ctob(btoc(exdata.ex_exec.a_text)); | |
221 | nc = exdata.ex_exec.a_data + exdata.ex_exec.a_bss; | |
222 | exdata.ex_exec.a_data = | |
223 | ctob(btoc(exdata.ex_exec.a_data)); | |
224 | nc -= (int)exdata.ex_exec.a_data; | |
225 | exdata.ex_exec.a_bss = (nc < 0) ? 0 : nc; | |
226 | } | |
227 | break; | |
228 | #endif | |
229 | } | |
28db9b87 | 230 | #endif |
aec7dd3b | 231 | switch ((int)exdata.ex_exec.a_magic) { |
28db9b87 | 232 | |
c4ec2128 | 233 | case OMAGIC: |
9fd50f35 SL |
234 | exdata.ex_exec.a_data += exdata.ex_exec.a_text; |
235 | exdata.ex_exec.a_text = 0; | |
28db9b87 SL |
236 | break; |
237 | ||
c4ec2128 | 238 | case ZMAGIC: |
93422d4b | 239 | flags |= SPAGV; |
c4ec2128 | 240 | case NMAGIC: |
9fd50f35 | 241 | if (exdata.ex_exec.a_text == 0) { |
c9714ae3 | 242 | error = ENOEXEC; |
28db9b87 SL |
243 | goto bad; |
244 | } | |
245 | break; | |
246 | ||
247 | default: | |
446115cb MK |
248 | if (exdata.ex_shell[0] != '#' || |
249 | exdata.ex_shell[1] != '!' || | |
250 | indir) { | |
c9714ae3 | 251 | error = ENOEXEC; |
28db9b87 SL |
252 | goto bad; |
253 | } | |
d26813a4 | 254 | for (cp = &exdata.ex_shell[2];; ++cp) { |
446115cb | 255 | if (cp >= &exdata.ex_shell[MAXINTERP]) { |
c9714ae3 | 256 | error = ENOEXEC; |
d26813a4 KB |
257 | goto bad; |
258 | } | |
259 | if (*cp == '\n') { | |
28db9b87 SL |
260 | *cp = '\0'; |
261 | break; | |
262 | } | |
d26813a4 KB |
263 | if (*cp == '\t') |
264 | *cp = ' '; | |
28db9b87 | 265 | } |
446115cb MK |
266 | cp = &exdata.ex_shell[2]; |
267 | while (*cp == ' ') | |
268 | cp++; | |
715baff1 | 269 | ndp->ni_dirp = cp; |
446115cb MK |
270 | while (*cp && *cp != ' ') |
271 | cp++; | |
e7db1101 | 272 | cfarg[0] = '\0'; |
28db9b87 | 273 | if (*cp) { |
446115cb MK |
274 | *cp++ = '\0'; |
275 | while (*cp == ' ') | |
276 | cp++; | |
ce66cb03 | 277 | if (*cp) |
cb9392ae | 278 | bcopy((caddr_t)cp, (caddr_t)cfarg, MAXINTERP); |
e7db1101 | 279 | } |
446115cb | 280 | indir = 1; |
c4ec2128 KM |
281 | vput(vp); |
282 | ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; | |
715baff1 | 283 | ndp->ni_segflg = UIO_SYSSPACE; |
c9714ae3 | 284 | if (error = namei(ndp)) |
d9c2f47f | 285 | return (error); |
c4ec2128 | 286 | vp = ndp->ni_vp; |
c9714ae3 | 287 | if (error = VOP_GETATTR(vp, &vattr, cred)) |
c4ec2128 | 288 | goto bad; |
ce66cb03 MK |
289 | bcopy((caddr_t)ndp->ni_dent.d_name, (caddr_t)cfname, |
290 | MAXCOMLEN); | |
291 | cfname[MAXCOMLEN] = '\0'; | |
c9714ae3 KM |
292 | uid = cred->cr_uid; /* shell scripts can't be setuid */ |
293 | gid = cred->cr_gid; | |
28db9b87 SL |
294 | goto again; |
295 | } | |
ba32f7c0 KM |
296 | /* |
297 | * If the vnode has been modified since we last used it, | |
298 | * then throw away all its pages and its text table entry. | |
299 | */ | |
300 | if (vp->v_text && vp->v_text->x_mtime != vattr.va_mtime.tv_sec) { | |
301 | /* | |
302 | * Try once to release, if it is still busy | |
303 | * take more drastic action. | |
304 | */ | |
305 | xrele(vp); | |
306 | if (vp->v_flag & VTEXT) { | |
307 | vput(vp); | |
308 | vgone(vp); | |
309 | goto start; | |
310 | } | |
311 | } | |
28db9b87 SL |
312 | |
313 | /* | |
314 | * Collect arguments on "file" in swap space. | |
315 | */ | |
316 | na = 0; | |
317 | ne = 0; | |
318 | nc = 0; | |
f3aaea26 | 319 | cc = 0; |
ec67a3ce MK |
320 | #ifdef SECSIZE |
321 | bno = rmalloc(argmap, (clrnd((int)btoc(NCARGS))) * CLBYTES / argdbsize); | |
322 | #else SECSIZE | |
9fd50f35 | 323 | bno = rmalloc(argmap, (long)ctod(clrnd((int)btoc(NCARGS)))); |
ec67a3ce | 324 | #endif SECSIZE |
9fd50f35 | 325 | if (bno == 0) { |
c9714ae3 | 326 | swkill(p, "exec: no swap space"); |
28db9b87 SL |
327 | goto bad; |
328 | } | |
329 | if (bno % CLSIZE) | |
330 | panic("execa rmalloc"); | |
93422d4b KM |
331 | #ifdef GENERIC |
332 | if (rootdev == dumpdev) | |
333 | bno += 4096; | |
334 | #endif | |
f3aaea26 SL |
335 | /* |
336 | * Copy arguments into file in argdev area. | |
337 | */ | |
28db9b87 SL |
338 | if (uap->argp) for (;;) { |
339 | ap = NULL; | |
ce66cb03 MK |
340 | sharg = NULL; |
341 | if (indir && na == 0) { | |
342 | sharg = cfname; | |
343 | ap = (int)sharg; | |
344 | uap->argp++; /* ignore argv[0] */ | |
345 | } else if (indir && (na == 1 && cfarg[0])) { | |
346 | sharg = cfarg; | |
347 | ap = (int)sharg; | |
348 | } else if (indir && (na == 1 || na == 2 && cfarg[0])) | |
28db9b87 SL |
349 | ap = (int)uap->fname; |
350 | else if (uap->argp) { | |
351 | ap = fuword((caddr_t)uap->argp); | |
352 | uap->argp++; | |
353 | } | |
f3aaea26 | 354 | if (ap == NULL && uap->envp) { |
28db9b87 | 355 | uap->argp = NULL; |
f3aaea26 SL |
356 | if ((ap = fuword((caddr_t)uap->envp)) != NULL) |
357 | uap->envp++, ne++; | |
28db9b87 SL |
358 | } |
359 | if (ap == NULL) | |
360 | break; | |
361 | na++; | |
f3aaea26 | 362 | if (ap == -1) { |
c9714ae3 | 363 | error = EFAULT; |
93422d4b KM |
364 | if (bp) { |
365 | brelse(bp); | |
366 | bp = 0; | |
367 | } | |
368 | goto badarg; | |
f3aaea26 | 369 | } |
28db9b87 | 370 | do { |
f3aaea26 SL |
371 | if (cc <= 0) { |
372 | /* | |
373 | * We depend on NCARGS being a multiple of | |
ec67a3ce | 374 | * CLBYTES. This way we need only check |
f3aaea26 SL |
375 | * overflow before each buffer allocation. |
376 | */ | |
377 | if (nc >= NCARGS-1) { | |
378 | error = E2BIG; | |
379 | break; | |
380 | } | |
28db9b87 SL |
381 | if (bp) |
382 | bdwrite(bp); | |
ec67a3ce MK |
383 | cc = CLBYTES; |
384 | #ifdef SECSIZE | |
385 | bp = getblk(argdev, bno + nc / argdbsize, cc, | |
386 | argdbsize); | |
387 | #else SECSIZE | |
c4ec2128 | 388 | bp = getblk(argdev_vp, bno + ctod(nc/NBPG), cc); |
ec67a3ce | 389 | #endif SECSIZE |
28db9b87 SL |
390 | cp = bp->b_un.b_addr; |
391 | } | |
ce66cb03 | 392 | if (sharg) { |
8011f5df | 393 | error = copystr(sharg, cp, (unsigned)cc, &len); |
ce66cb03 MK |
394 | sharg += len; |
395 | } else { | |
8011f5df MK |
396 | error = copyinstr((caddr_t)ap, cp, (unsigned)cc, |
397 | &len); | |
ce66cb03 MK |
398 | ap += len; |
399 | } | |
f3aaea26 SL |
400 | cp += len; |
401 | nc += len; | |
402 | cc -= len; | |
403 | } while (error == ENOENT); | |
404 | if (error) { | |
f3aaea26 SL |
405 | if (bp) |
406 | brelse(bp); | |
407 | bp = 0; | |
408 | goto badarg; | |
409 | } | |
28db9b87 SL |
410 | } |
411 | if (bp) | |
412 | bdwrite(bp); | |
413 | bp = 0; | |
414 | nc = (nc + NBPW-1) & ~(NBPW-1); | |
c9714ae3 KM |
415 | error = getxfile(p, vp, &exdata.ex_exec, flags, nc + (na+4)*NBPW, |
416 | uid, gid); | |
417 | if (error) { | |
28db9b87 | 418 | badarg: |
c4ec2128 | 419 | for (cc = 0; cc < nc; cc += CLBYTES) { |
2fd88d7d | 420 | (void) baddr(argdev_vp, bno + ctod(cc/NBPG), |
9ad9d3f8 | 421 | CLBYTES, NOCRED, &tbp); |
c4ec2128 | 422 | bp = tbp; |
ec67a3ce | 423 | #endif SECSIZE |
28db9b87 | 424 | if (bp) { |
a4292a03 | 425 | bp->b_flags |= B_INVAL; /* throw away */ |
28db9b87 SL |
426 | brelse(bp); |
427 | bp = 0; | |
428 | } | |
429 | } | |
430 | goto bad; | |
431 | } | |
33f18f0f MH |
432 | if (vp->v_text) |
433 | vp->v_text->x_mtime = vattr.va_mtime.tv_sec; | |
c4ec2128 KM |
434 | vput(vp); |
435 | vp = NULL; | |
28db9b87 | 436 | |
93422d4b KM |
437 | #ifdef HPUXCOMPAT |
438 | /* | |
439 | * We are now committed to the exec so we can save the exec | |
440 | * header in the pcb where we can dump it if necessary in core() | |
441 | */ | |
442 | if (u.u_pcb.pcb_flags & PCB_HPUXBIN) | |
443 | bcopy((caddr_t)&hhead, | |
444 | (caddr_t)u.u_pcb.pcb_exec, sizeof hhead); | |
445 | #endif | |
446 | ||
28db9b87 | 447 | /* |
f3aaea26 | 448 | * Copy back arglist. |
28db9b87 SL |
449 | */ |
450 | ucp = USRSTACK - nc - NBPW; | |
451 | ap = ucp - na*NBPW - 3*NBPW; | |
452 | u.u_ar0[SP] = ap; | |
453 | (void) suword((caddr_t)ap, na-ne); | |
454 | nc = 0; | |
72d4f41a | 455 | cc = 0; |
28db9b87 SL |
456 | for (;;) { |
457 | ap += NBPW; | |
f3aaea26 | 458 | if (na == ne) { |
28db9b87 SL |
459 | (void) suword((caddr_t)ap, 0); |
460 | ap += NBPW; | |
461 | } | |
462 | if (--na < 0) | |
463 | break; | |
464 | (void) suword((caddr_t)ap, ucp); | |
465 | do { | |
72d4f41a | 466 | if (cc <= 0) { |
28db9b87 SL |
467 | if (bp) |
468 | brelse(bp); | |
ec67a3ce MK |
469 | cc = CLBYTES; |
470 | #ifdef SECSIZE | |
471 | bp = bread(argdev, bno + nc / argdbsize, cc, | |
472 | argdbsize); | |
473 | #else SECSIZE | |
c4ec2128 | 474 | error = bread(argdev_vp, |
9ad9d3f8 KM |
475 | (daddr_t)(bno + ctod(nc / NBPG)), cc, |
476 | NOCRED, &tbp); | |
c4ec2128 | 477 | bp = tbp; |
ec67a3ce | 478 | #endif SECSIZE |
a4292a03 | 479 | bp->b_flags |= B_INVAL; /* throw away */ |
28db9b87 SL |
480 | cp = bp->b_un.b_addr; |
481 | } | |
8011f5df MK |
482 | error = copyoutstr(cp, (caddr_t)ucp, (unsigned)cc, |
483 | &len); | |
72d4f41a SL |
484 | ucp += len; |
485 | cp += len; | |
486 | nc += len; | |
487 | cc -= len; | |
488 | } while (error == ENOENT); | |
489 | if (error == EFAULT) | |
490 | panic("exec: EFAULT"); | |
28db9b87 SL |
491 | } |
492 | (void) suword((caddr_t)ap, 0); | |
ce66cb03 | 493 | |
c9714ae3 | 494 | execsigs(p); |
ce66cb03 MK |
495 | |
496 | for (nc = u.u_lastfile; nc >= 0; --nc) { | |
497 | if (u.u_pofile[nc] & UF_EXCLOSE) { | |
69be5b7a | 498 | (void) closef(u.u_ofile[nc]); |
ce66cb03 MK |
499 | u.u_ofile[nc] = NULL; |
500 | u.u_pofile[nc] = 0; | |
501 | } | |
502 | u.u_pofile[nc] &= ~UF_MAPPED; | |
503 | } | |
504 | while (u.u_lastfile >= 0 && u.u_ofile[u.u_lastfile] == NULL) | |
505 | u.u_lastfile--; | |
ddb266b6 | 506 | setregs(exdata.ex_exec.a_entry, retval); |
715baff1 KM |
507 | /* |
508 | * Remember file name for accounting. | |
509 | */ | |
510 | u.u_acflag &= ~AFORK; | |
ce66cb03 | 511 | if (indir) |
c9714ae3 | 512 | bcopy((caddr_t)cfname, (caddr_t)p->p_comm, MAXCOMLEN); |
ce66cb03 MK |
513 | else { |
514 | if (ndp->ni_dent.d_namlen > MAXCOMLEN) | |
515 | ndp->ni_dent.d_namlen = MAXCOMLEN; | |
c9714ae3 | 516 | bcopy((caddr_t)ndp->ni_dent.d_name, (caddr_t)p->p_comm, |
ce66cb03 MK |
517 | (unsigned)(ndp->ni_dent.d_namlen + 1)); |
518 | } | |
28db9b87 SL |
519 | bad: |
520 | if (bp) | |
521 | brelse(bp); | |
522 | if (bno) | |
ec67a3ce MK |
523 | #ifdef SECSIZE |
524 | rmfree(argmap, (clrnd((int)btoc(NCARGS))) * CLBYTES / argdbsize, | |
525 | bno); | |
526 | #else SECSIZE | |
28db9b87 | 527 | rmfree(argmap, (long)ctod(clrnd((int) btoc(NCARGS))), bno); |
ec67a3ce | 528 | #endif SECSIZE |
c4ec2128 KM |
529 | if (vp) |
530 | vput(vp); | |
d9c2f47f | 531 | return (error); |
28db9b87 SL |
532 | } |
533 | ||
534 | /* | |
535 | * Read in and set up memory for executed file. | |
536 | */ | |
c9714ae3 KM |
537 | getxfile(p, vp, ep, flags, nargc, uid, gid) |
538 | register struct proc *p; | |
c4ec2128 | 539 | register struct vnode *vp; |
9fd50f35 | 540 | register struct exec *ep; |
93422d4b | 541 | int flags, nargc, uid, gid; |
28db9b87 | 542 | { |
e5b27ef1 | 543 | segsz_t ts, ds, ids, uds, ss; |
c9714ae3 | 544 | register struct ucred *cred = u.u_cred; |
93422d4b | 545 | off_t toff; |
c9714ae3 | 546 | int error; |
28db9b87 | 547 | |
93422d4b KM |
548 | #ifdef HPUXCOMPAT |
549 | if (ep->a_mid == MID_HPUX) | |
550 | toff = sizeof (struct hpux_exec); | |
28db9b87 | 551 | else |
93422d4b KM |
552 | #endif |
553 | toff = sizeof (struct exec); | |
c9714ae3 KM |
554 | if (vp->v_text && (vp->v_text->x_flag & XTRC)) |
555 | return (ETXTBSY); | |
c4ec2128 | 556 | if (ep->a_text != 0 && (vp->v_flag & VTEXT) == 0 && |
c65056fe | 557 | vp->v_usecount != 1) { |
28db9b87 SL |
558 | register struct file *fp; |
559 | ||
560 | for (fp = file; fp < fileNFILE; fp++) { | |
c4ec2128 | 561 | if (fp->f_type == DTYPE_VNODE && |
28db9b87 | 562 | fp->f_count > 0 && |
c4ec2128 KM |
563 | (struct vnode *)fp->f_data == vp && |
564 | (fp->f_flag & FWRITE)) { | |
c9714ae3 | 565 | return (ETXTBSY); |
28db9b87 SL |
566 | } |
567 | } | |
568 | } | |
569 | ||
570 | /* | |
571 | * Compute text and data sizes and make sure not too large. | |
0c48b03e KM |
572 | * NB - Check data and bss separately as they may overflow |
573 | * when summed together. | |
28db9b87 | 574 | */ |
9fd50f35 | 575 | ts = clrnd(btoc(ep->a_text)); |
0c48b03e KM |
576 | ids = clrnd(btoc(ep->a_data)); |
577 | uds = clrnd(btoc(ep->a_bss)); | |
f3aaea26 | 578 | ds = clrnd(btoc(ep->a_data + ep->a_bss)); |
28db9b87 | 579 | ss = clrnd(SSIZE + btoc(nargc)); |
c9714ae3 KM |
580 | if (error = |
581 | chksize((unsigned)ts, (unsigned)ids, (unsigned)uds, (unsigned)ss)) | |
582 | return (error); | |
28db9b87 SL |
583 | |
584 | /* | |
585 | * Make sure enough space to start process. | |
586 | */ | |
587 | u.u_cdmap = zdmap; | |
588 | u.u_csmap = zdmap; | |
c9714ae3 KM |
589 | if (error = swpexpand(ds, ss, &u.u_cdmap, &u.u_csmap)) |
590 | return (error); | |
28db9b87 SL |
591 | |
592 | /* | |
c4ec2128 | 593 | * At this point, we are committed to the new image! |
28db9b87 SL |
594 | * Release virtual memory resources of old process, and |
595 | * initialize the virtual memory of the new process. | |
596 | * If we resulted from vfork(), instead wakeup our | |
597 | * parent who will set SVFDONE when he has taken back | |
598 | * our resources. | |
599 | */ | |
93422d4b KM |
600 | if ((p->p_flag & SVFORK) == 0) { |
601 | #ifdef MAPMEM | |
c9714ae3 KM |
602 | if (u.u_mmap && (error = mmexec(p))) |
603 | return (error); | |
93422d4b | 604 | #endif |
28db9b87 | 605 | vrelvm(); |
93422d4b | 606 | } else { |
ba7abd07 MK |
607 | p->p_flag &= ~SVFORK; |
608 | p->p_flag |= SKEEP; | |
609 | wakeup((caddr_t)p); | |
610 | while ((p->p_flag & SVFDONE) == 0) | |
611 | sleep((caddr_t)p, PZERO - 1); | |
612 | p->p_flag &= ~(SVFDONE|SKEEP); | |
28db9b87 | 613 | } |
93422d4b KM |
614 | #ifdef hp300 |
615 | u.u_pcb.pcb_flags &= ~(PCB_AST|PCB_HPUXMMAP|PCB_HPUXBIN); | |
616 | #ifdef HPUXCOMPAT | |
617 | /* remember that we were loaded from an HPUX format file */ | |
618 | if (ep->a_mid == MID_HPUX) | |
619 | u.u_pcb.pcb_flags |= PCB_HPUXBIN; | |
620 | #endif | |
621 | #endif | |
622 | p->p_flag &= ~(SPAGV|SSEQL|SUANOM|SHPUX); | |
623 | p->p_flag |= flags | SEXEC; | |
28db9b87 SL |
624 | u.u_dmap = u.u_cdmap; |
625 | u.u_smap = u.u_csmap; | |
626 | vgetvm(ts, ds, ss); | |
627 | ||
93422d4b | 628 | if ((flags & SPAGV) == 0) |
c9714ae3 | 629 | (void) vn_rdwr(UIO_READ, vp, |
93422d4b | 630 | (char *)ctob(dptov(p, 0)), |
9fd50f35 | 631 | (int)ep->a_data, |
93422d4b | 632 | (off_t)(toff + ep->a_text), |
c4ec2128 | 633 | UIO_USERSPACE, (IO_UNIT|IO_NODELOCKED), cred, (int *)0); |
93422d4b | 634 | xalloc(vp, ep, toff, cred); |
fb1db32c MK |
635 | #if defined(tahoe) |
636 | /* | |
637 | * Define new keys. | |
638 | */ | |
ba7abd07 MK |
639 | if (p->p_textp == 0) { /* use existing code key if shared */ |
640 | ckeyrelease(p->p_ckey); | |
641 | p->p_ckey = getcodekey(); | |
fb1db32c | 642 | } |
ba7abd07 MK |
643 | mtpr(CCK, p->p_ckey); |
644 | dkeyrelease(p->p_dkey); | |
645 | p->p_dkey = getdatakey(); | |
646 | mtpr(DCK, p->p_dkey); | |
fb1db32c | 647 | #endif |
93422d4b KM |
648 | if ((flags & SPAGV) && p->p_textp) |
649 | vinifod(p, (struct fpte *)dptopte(p, 0), | |
ba7abd07 | 650 | PG_FTEXT, p->p_textp->x_vptr, |
e5b27ef1 | 651 | (long)(1 + ts/CLSIZE), (segsz_t)btoc(ep->a_data)); |
28db9b87 | 652 | |
fb1db32c | 653 | #if defined(vax) || defined(tahoe) |
28db9b87 | 654 | /* THIS SHOULD BE DONE AT A LOWER LEVEL, IF AT ALL */ |
28db9b87 SL |
655 | mtpr(TBIA, 0); |
656 | #endif | |
93422d4b KM |
657 | #ifdef hp300 |
658 | TBIAU(); | |
659 | #endif | |
28db9b87 | 660 | |
28db9b87 SL |
661 | /* |
662 | * set SUID/SGID protections, if no tracing | |
663 | */ | |
ba7abd07 | 664 | if ((p->p_flag&STRC)==0) { |
c9714ae3 KM |
665 | if (uid != cred->cr_uid || gid != cred->cr_gid) |
666 | u.u_cred = cred = crcopy(cred); | |
667 | cred->cr_uid = uid; | |
668 | cred->cr_gid = gid; | |
ba7abd07 | 669 | p->p_uid = uid; |
28db9b87 | 670 | } else |
ba7abd07 MK |
671 | psignal(p, SIGTRAP); |
672 | p->p_svuid = p->p_uid; | |
c9714ae3 | 673 | p->p_svgid = cred->cr_gid; |
28db9b87 SL |
674 | u.u_tsize = ts; |
675 | u.u_dsize = ds; | |
676 | u.u_ssize = ss; | |
d4a03a57 | 677 | u.u_prof.pr_scale = 0; |
fb1db32c MK |
678 | #if defined(tahoe) |
679 | u.u_pcb.pcb_savacc.faddr = (float *)NULL; | |
680 | #endif | |
c9714ae3 | 681 | return (0); |
28db9b87 | 682 | } |