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 | * | |
c9714ae3 | 17 | * @(#)kern_exec.c 7.25 (Berkeley) %G% |
da7c5cc6 | 18 | */ |
28db9b87 | 19 | |
94368568 JB |
20 | #include "param.h" |
21 | #include "systm.h" | |
22 | #include "map.h" | |
c9714ae3 | 23 | #include "syscontext.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; | |
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)) | |
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 KM |
284 | if (error = namei(ndp)) |
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 | } | |
ba32f7c0 | 432 | vp->v_text->x_mtime = vattr.va_mtime.tv_sec; |
c4ec2128 KM |
433 | vput(vp); |
434 | vp = NULL; | |
28db9b87 | 435 | |
93422d4b KM |
436 | #ifdef HPUXCOMPAT |
437 | /* | |
438 | * We are now committed to the exec so we can save the exec | |
439 | * header in the pcb where we can dump it if necessary in core() | |
440 | */ | |
441 | if (u.u_pcb.pcb_flags & PCB_HPUXBIN) | |
442 | bcopy((caddr_t)&hhead, | |
443 | (caddr_t)u.u_pcb.pcb_exec, sizeof hhead); | |
444 | #endif | |
445 | ||
28db9b87 | 446 | /* |
f3aaea26 | 447 | * Copy back arglist. |
28db9b87 SL |
448 | */ |
449 | ucp = USRSTACK - nc - NBPW; | |
450 | ap = ucp - na*NBPW - 3*NBPW; | |
451 | u.u_ar0[SP] = ap; | |
452 | (void) suword((caddr_t)ap, na-ne); | |
453 | nc = 0; | |
72d4f41a | 454 | cc = 0; |
28db9b87 SL |
455 | for (;;) { |
456 | ap += NBPW; | |
f3aaea26 | 457 | if (na == ne) { |
28db9b87 SL |
458 | (void) suword((caddr_t)ap, 0); |
459 | ap += NBPW; | |
460 | } | |
461 | if (--na < 0) | |
462 | break; | |
463 | (void) suword((caddr_t)ap, ucp); | |
464 | do { | |
72d4f41a | 465 | if (cc <= 0) { |
28db9b87 SL |
466 | if (bp) |
467 | brelse(bp); | |
ec67a3ce MK |
468 | cc = CLBYTES; |
469 | #ifdef SECSIZE | |
470 | bp = bread(argdev, bno + nc / argdbsize, cc, | |
471 | argdbsize); | |
472 | #else SECSIZE | |
c4ec2128 | 473 | error = bread(argdev_vp, |
9ad9d3f8 KM |
474 | (daddr_t)(bno + ctod(nc / NBPG)), cc, |
475 | NOCRED, &tbp); | |
c4ec2128 | 476 | bp = tbp; |
ec67a3ce | 477 | #endif SECSIZE |
a4292a03 | 478 | bp->b_flags |= B_INVAL; /* throw away */ |
28db9b87 SL |
479 | cp = bp->b_un.b_addr; |
480 | } | |
8011f5df MK |
481 | error = copyoutstr(cp, (caddr_t)ucp, (unsigned)cc, |
482 | &len); | |
72d4f41a SL |
483 | ucp += len; |
484 | cp += len; | |
485 | nc += len; | |
486 | cc -= len; | |
487 | } while (error == ENOENT); | |
488 | if (error == EFAULT) | |
489 | panic("exec: EFAULT"); | |
28db9b87 SL |
490 | } |
491 | (void) suword((caddr_t)ap, 0); | |
ce66cb03 | 492 | |
c9714ae3 | 493 | execsigs(p); |
ce66cb03 MK |
494 | |
495 | for (nc = u.u_lastfile; nc >= 0; --nc) { | |
496 | if (u.u_pofile[nc] & UF_EXCLOSE) { | |
69be5b7a | 497 | (void) closef(u.u_ofile[nc]); |
ce66cb03 MK |
498 | u.u_ofile[nc] = NULL; |
499 | u.u_pofile[nc] = 0; | |
500 | } | |
501 | u.u_pofile[nc] &= ~UF_MAPPED; | |
502 | } | |
503 | while (u.u_lastfile >= 0 && u.u_ofile[u.u_lastfile] == NULL) | |
504 | u.u_lastfile--; | |
9fd50f35 | 505 | setregs(exdata.ex_exec.a_entry); |
715baff1 KM |
506 | /* |
507 | * Remember file name for accounting. | |
508 | */ | |
509 | u.u_acflag &= ~AFORK; | |
ce66cb03 | 510 | if (indir) |
c9714ae3 | 511 | bcopy((caddr_t)cfname, (caddr_t)p->p_comm, MAXCOMLEN); |
ce66cb03 MK |
512 | else { |
513 | if (ndp->ni_dent.d_namlen > MAXCOMLEN) | |
514 | ndp->ni_dent.d_namlen = MAXCOMLEN; | |
c9714ae3 | 515 | bcopy((caddr_t)ndp->ni_dent.d_name, (caddr_t)p->p_comm, |
ce66cb03 MK |
516 | (unsigned)(ndp->ni_dent.d_namlen + 1)); |
517 | } | |
28db9b87 SL |
518 | bad: |
519 | if (bp) | |
520 | brelse(bp); | |
521 | if (bno) | |
ec67a3ce MK |
522 | #ifdef SECSIZE |
523 | rmfree(argmap, (clrnd((int)btoc(NCARGS))) * CLBYTES / argdbsize, | |
524 | bno); | |
525 | #else SECSIZE | |
28db9b87 | 526 | rmfree(argmap, (long)ctod(clrnd((int) btoc(NCARGS))), bno); |
ec67a3ce | 527 | #endif SECSIZE |
c4ec2128 KM |
528 | if (vp) |
529 | vput(vp); | |
c9714ae3 | 530 | RETURN (error); |
28db9b87 SL |
531 | } |
532 | ||
533 | /* | |
534 | * Read in and set up memory for executed file. | |
535 | */ | |
c9714ae3 KM |
536 | getxfile(p, vp, ep, flags, nargc, uid, gid) |
537 | register struct proc *p; | |
c4ec2128 | 538 | register struct vnode *vp; |
9fd50f35 | 539 | register struct exec *ep; |
93422d4b | 540 | int flags, nargc, uid, gid; |
28db9b87 | 541 | { |
e5b27ef1 | 542 | segsz_t ts, ds, ids, uds, ss; |
c9714ae3 | 543 | register struct ucred *cred = u.u_cred; |
93422d4b | 544 | off_t toff; |
c9714ae3 | 545 | int error; |
28db9b87 | 546 | |
93422d4b KM |
547 | #ifdef HPUXCOMPAT |
548 | if (ep->a_mid == MID_HPUX) | |
549 | toff = sizeof (struct hpux_exec); | |
28db9b87 | 550 | else |
93422d4b KM |
551 | #endif |
552 | toff = sizeof (struct exec); | |
c9714ae3 KM |
553 | if (vp->v_text && (vp->v_text->x_flag & XTRC)) |
554 | return (ETXTBSY); | |
c4ec2128 | 555 | if (ep->a_text != 0 && (vp->v_flag & VTEXT) == 0 && |
c65056fe | 556 | vp->v_usecount != 1) { |
28db9b87 SL |
557 | register struct file *fp; |
558 | ||
559 | for (fp = file; fp < fileNFILE; fp++) { | |
c4ec2128 | 560 | if (fp->f_type == DTYPE_VNODE && |
28db9b87 | 561 | fp->f_count > 0 && |
c4ec2128 KM |
562 | (struct vnode *)fp->f_data == vp && |
563 | (fp->f_flag & FWRITE)) { | |
c9714ae3 | 564 | return (ETXTBSY); |
28db9b87 SL |
565 | } |
566 | } | |
567 | } | |
568 | ||
569 | /* | |
570 | * Compute text and data sizes and make sure not too large. | |
0c48b03e KM |
571 | * NB - Check data and bss separately as they may overflow |
572 | * when summed together. | |
28db9b87 | 573 | */ |
9fd50f35 | 574 | ts = clrnd(btoc(ep->a_text)); |
0c48b03e KM |
575 | ids = clrnd(btoc(ep->a_data)); |
576 | uds = clrnd(btoc(ep->a_bss)); | |
f3aaea26 | 577 | ds = clrnd(btoc(ep->a_data + ep->a_bss)); |
28db9b87 | 578 | ss = clrnd(SSIZE + btoc(nargc)); |
c9714ae3 KM |
579 | if (error = |
580 | chksize((unsigned)ts, (unsigned)ids, (unsigned)uds, (unsigned)ss)) | |
581 | return (error); | |
28db9b87 SL |
582 | |
583 | /* | |
584 | * Make sure enough space to start process. | |
585 | */ | |
586 | u.u_cdmap = zdmap; | |
587 | u.u_csmap = zdmap; | |
c9714ae3 KM |
588 | if (error = swpexpand(ds, ss, &u.u_cdmap, &u.u_csmap)) |
589 | return (error); | |
28db9b87 SL |
590 | |
591 | /* | |
c4ec2128 | 592 | * At this point, we are committed to the new image! |
28db9b87 SL |
593 | * Release virtual memory resources of old process, and |
594 | * initialize the virtual memory of the new process. | |
595 | * If we resulted from vfork(), instead wakeup our | |
596 | * parent who will set SVFDONE when he has taken back | |
597 | * our resources. | |
598 | */ | |
93422d4b KM |
599 | if ((p->p_flag & SVFORK) == 0) { |
600 | #ifdef MAPMEM | |
c9714ae3 KM |
601 | if (u.u_mmap && (error = mmexec(p))) |
602 | return (error); | |
93422d4b | 603 | #endif |
28db9b87 | 604 | vrelvm(); |
93422d4b | 605 | } else { |
ba7abd07 MK |
606 | p->p_flag &= ~SVFORK; |
607 | p->p_flag |= SKEEP; | |
608 | wakeup((caddr_t)p); | |
609 | while ((p->p_flag & SVFDONE) == 0) | |
610 | sleep((caddr_t)p, PZERO - 1); | |
611 | p->p_flag &= ~(SVFDONE|SKEEP); | |
28db9b87 | 612 | } |
93422d4b KM |
613 | #ifdef hp300 |
614 | u.u_pcb.pcb_flags &= ~(PCB_AST|PCB_HPUXMMAP|PCB_HPUXBIN); | |
615 | #ifdef HPUXCOMPAT | |
616 | /* remember that we were loaded from an HPUX format file */ | |
617 | if (ep->a_mid == MID_HPUX) | |
618 | u.u_pcb.pcb_flags |= PCB_HPUXBIN; | |
619 | #endif | |
620 | #endif | |
621 | p->p_flag &= ~(SPAGV|SSEQL|SUANOM|SHPUX); | |
622 | p->p_flag |= flags | SEXEC; | |
28db9b87 SL |
623 | u.u_dmap = u.u_cdmap; |
624 | u.u_smap = u.u_csmap; | |
625 | vgetvm(ts, ds, ss); | |
626 | ||
93422d4b | 627 | if ((flags & SPAGV) == 0) |
c9714ae3 | 628 | (void) vn_rdwr(UIO_READ, vp, |
93422d4b | 629 | (char *)ctob(dptov(p, 0)), |
9fd50f35 | 630 | (int)ep->a_data, |
93422d4b | 631 | (off_t)(toff + ep->a_text), |
c4ec2128 | 632 | UIO_USERSPACE, (IO_UNIT|IO_NODELOCKED), cred, (int *)0); |
93422d4b | 633 | xalloc(vp, ep, toff, cred); |
fb1db32c MK |
634 | #if defined(tahoe) |
635 | /* | |
636 | * Define new keys. | |
637 | */ | |
ba7abd07 MK |
638 | if (p->p_textp == 0) { /* use existing code key if shared */ |
639 | ckeyrelease(p->p_ckey); | |
640 | p->p_ckey = getcodekey(); | |
fb1db32c | 641 | } |
ba7abd07 MK |
642 | mtpr(CCK, p->p_ckey); |
643 | dkeyrelease(p->p_dkey); | |
644 | p->p_dkey = getdatakey(); | |
645 | mtpr(DCK, p->p_dkey); | |
fb1db32c | 646 | #endif |
93422d4b KM |
647 | if ((flags & SPAGV) && p->p_textp) |
648 | vinifod(p, (struct fpte *)dptopte(p, 0), | |
ba7abd07 | 649 | PG_FTEXT, p->p_textp->x_vptr, |
e5b27ef1 | 650 | (long)(1 + ts/CLSIZE), (segsz_t)btoc(ep->a_data)); |
28db9b87 | 651 | |
fb1db32c | 652 | #if defined(vax) || defined(tahoe) |
28db9b87 | 653 | /* THIS SHOULD BE DONE AT A LOWER LEVEL, IF AT ALL */ |
28db9b87 SL |
654 | mtpr(TBIA, 0); |
655 | #endif | |
93422d4b KM |
656 | #ifdef hp300 |
657 | TBIAU(); | |
658 | #endif | |
28db9b87 | 659 | |
28db9b87 SL |
660 | /* |
661 | * set SUID/SGID protections, if no tracing | |
662 | */ | |
ba7abd07 | 663 | if ((p->p_flag&STRC)==0) { |
c9714ae3 KM |
664 | if (uid != cred->cr_uid || gid != cred->cr_gid) |
665 | u.u_cred = cred = crcopy(cred); | |
666 | cred->cr_uid = uid; | |
667 | cred->cr_gid = gid; | |
ba7abd07 | 668 | p->p_uid = uid; |
28db9b87 | 669 | } else |
ba7abd07 MK |
670 | psignal(p, SIGTRAP); |
671 | p->p_svuid = p->p_uid; | |
c9714ae3 | 672 | p->p_svgid = cred->cr_gid; |
28db9b87 SL |
673 | u.u_tsize = ts; |
674 | u.u_dsize = ds; | |
675 | u.u_ssize = ss; | |
d4a03a57 | 676 | u.u_prof.pr_scale = 0; |
fb1db32c MK |
677 | #if defined(tahoe) |
678 | u.u_pcb.pcb_savacc.faddr = (float *)NULL; | |
679 | #endif | |
c9714ae3 | 680 | return (0); |
28db9b87 | 681 | } |