|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution is only permitted until one year after the first shipment
6: * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and
7: * binary forms are permitted provided that: (1) source distributions retain
8: * this entire copyright notice and comment, and (2) distributions including
9: * binaries display the following acknowledgement: This product includes
10: * software developed by the University of California, Berkeley and its
11: * contributors'' in the documentation or other materials provided with the
12: * distribution and in all advertising materials mentioning features or use
13: * of this software. Neither the name of the University nor the names of
14: * its contributors may be used to endorse or promote products derived from
15: * this software without specific prior written permission.
16: * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
17: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
18: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19: *
20: * @(#)kern_exec.c 7.30 (Berkeley) 6/30/90
21: */
22:
23: #include "param.h"
24: #include "systm.h"
25: #include "map.h"
26: #include "user.h"
27: #include "kernel.h"
28: #include "proc.h"
29: #include "mount.h"
30: #include "ucred.h"
31: #include "malloc.h"
32: #include "buf.h"
33: #include "vnode.h"
34: #include "seg.h"
35: #include "vm.h"
36: #include "text.h"
37: #include "file.h"
38: #include "uio.h"
39: #include "acct.h"
40: #include "exec.h"
41:
42: #include "machine/reg.h"
43: #include "machine/pte.h"
44: #include "machine/psl.h"
45: #include "machine/mtpr.h"
46:
47: #ifdef HPUXCOMPAT
48: #include "../hpux/hpux_exec.h"
49: #endif
50:
51: /*
52: * exec system call, with and without environments.
53: */
54: execv(p, uap, retval)
55: struct proc *p;
56: struct args {
57: char *fname;
58: char **argp;
59: char **envp;
60: } *uap;
61: int *retval;
62: {
63:
64: uap->envp = NULL;
65: return (execve(p, uap, retval));
66: }
67:
68: /* ARGSUSED */
69: execve(p, uap, retval)
70: register struct proc *p;
71: register struct args {
72: char *fname;
73: char **argp;
74: char **envp;
75: } *uap;
76: int *retval;
77: {
78: register nc;
79: register char *cp;
80: register struct buf *bp;
81: struct buf *tbp;
82: int na, ne, ucp, ap, cc;
83: unsigned len;
84: int indir, uid, gid;
85: char *sharg;
86: struct vnode *vp;
87: swblk_t bno;
88: struct vattr vattr;
89: char cfname[MAXCOMLEN + 1];
90: char cfarg[MAXINTERP];
91: union {
92: char ex_shell[MAXINTERP]; /* #! and interpreter name */
93: struct exec ex_exec;
94: #ifdef HPUXCOMPAT
95: struct hpux_exec ex_hexec;
96: #endif
97: } exdata;
98: #ifdef HPUXCOMPAT
99: struct hpux_exec hhead;
100: #endif
101: register struct ucred *cred = u.u_cred;
102: register struct nameidata *ndp = &u.u_nd;
103: int resid, error, flags = 0;
104:
105: start:
106: ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
107: ndp->ni_segflg = UIO_USERSPACE;
108: ndp->ni_dirp = uap->fname;
109: if (error = namei(ndp))
110: return (error);
111: vp = ndp->ni_vp;
112: bno = 0;
113: bp = 0;
114: indir = 0;
115: uid = cred->cr_uid;
116: gid = cred->cr_gid;
117: if (error = VOP_GETATTR(vp, &vattr, cred))
118: goto bad;
119: if (vp->v_mount->mnt_flag & MNT_NOEXEC) {
120: error = EACCES;
121: goto bad;
122: }
123: if ((vp->v_mount->mnt_flag & MNT_NOSUID) == 0) {
124: if (vattr.va_mode & VSUID)
125: uid = vattr.va_uid;
126: if (vattr.va_mode & VSGID)
127: gid = vattr.va_gid;
128: }
129:
130: again:
131: if (error = VOP_ACCESS(vp, VEXEC, cred))
132: goto bad;
133: if ((p->p_flag & STRC) && (error = VOP_ACCESS(vp, VREAD, cred)))
134: goto bad;
135: if (vp->v_type != VREG ||
136: (vattr.va_mode & (VEXEC|(VEXEC>>3)|(VEXEC>>6))) == 0) {
137: error = EACCES;
138: goto bad;
139: }
140:
141: /*
142: * Read in first few bytes of file for segment sizes, magic number:
143: * OMAGIC = plain executable
144: * NMAGIC = RO text
145: * ZMAGIC = demand paged RO text
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: */
155: exdata.ex_shell[0] = '\0'; /* for zero length files */
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)
159: goto bad;
160: #ifndef lint
161: if (resid > sizeof(exdata) - sizeof(exdata.ex_exec) &&
162: exdata.ex_shell[0] != '#') {
163: error = ENOEXEC;
164: goto bad;
165: }
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: }
230: #endif
231: switch ((int)exdata.ex_exec.a_magic) {
232:
233: case OMAGIC:
234: exdata.ex_exec.a_data += exdata.ex_exec.a_text;
235: exdata.ex_exec.a_text = 0;
236: break;
237:
238: case ZMAGIC:
239: flags |= SPAGV;
240: case NMAGIC:
241: if (exdata.ex_exec.a_text == 0) {
242: error = ENOEXEC;
243: goto bad;
244: }
245: break;
246:
247: default:
248: if (exdata.ex_shell[0] != '#' ||
249: exdata.ex_shell[1] != '!' ||
250: indir) {
251: error = ENOEXEC;
252: goto bad;
253: }
254: for (cp = &exdata.ex_shell[2];; ++cp) {
255: if (cp >= &exdata.ex_shell[MAXINTERP]) {
256: error = ENOEXEC;
257: goto bad;
258: }
259: if (*cp == '\n') {
260: *cp = '\0';
261: break;
262: }
263: if (*cp == '\t')
264: *cp = ' ';
265: }
266: cp = &exdata.ex_shell[2];
267: while (*cp == ' ')
268: cp++;
269: ndp->ni_dirp = cp;
270: while (*cp && *cp != ' ')
271: cp++;
272: cfarg[0] = '\0';
273: if (*cp) {
274: *cp++ = '\0';
275: while (*cp == ' ')
276: cp++;
277: if (*cp)
278: bcopy((caddr_t)cp, (caddr_t)cfarg, MAXINTERP);
279: }
280: indir = 1;
281: vput(vp);
282: ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
283: ndp->ni_segflg = UIO_SYSSPACE;
284: if (error = namei(ndp))
285: return (error);
286: vp = ndp->ni_vp;
287: if (error = VOP_GETATTR(vp, &vattr, cred))
288: goto bad;
289: bcopy((caddr_t)ndp->ni_dent.d_name, (caddr_t)cfname,
290: MAXCOMLEN);
291: cfname[MAXCOMLEN] = '\0';
292: uid = cred->cr_uid; /* shell scripts can't be setuid */
293: gid = cred->cr_gid;
294: goto again;
295: }
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: }
312:
313: /*
314: * Collect arguments on "file" in swap space.
315: */
316: na = 0;
317: ne = 0;
318: nc = 0;
319: cc = 0;
320: bno = rmalloc(argmap, (long)ctod(clrnd((int)btoc(NCARGS))));
321: if (bno == 0) {
322: swkill(p, "exec: no swap space");
323: goto bad;
324: }
325: if (bno % CLSIZE)
326: panic("execa rmalloc");
327: #ifdef GENERIC
328: if (rootdev == dumpdev)
329: bno += 4096;
330: #endif
331: /*
332: * Copy arguments into file in argdev area.
333: */
334: if (uap->argp) for (;;) {
335: ap = NULL;
336: sharg = NULL;
337: if (indir && na == 0) {
338: sharg = cfname;
339: ap = (int)sharg;
340: uap->argp++; /* ignore argv[0] */
341: } else if (indir && (na == 1 && cfarg[0])) {
342: sharg = cfarg;
343: ap = (int)sharg;
344: } else if (indir && (na == 1 || na == 2 && cfarg[0]))
345: ap = (int)uap->fname;
346: else if (uap->argp) {
347: ap = fuword((caddr_t)uap->argp);
348: uap->argp++;
349: }
350: if (ap == NULL && uap->envp) {
351: uap->argp = NULL;
352: if ((ap = fuword((caddr_t)uap->envp)) != NULL)
353: uap->envp++, ne++;
354: }
355: if (ap == NULL)
356: break;
357: na++;
358: if (ap == -1) {
359: error = EFAULT;
360: if (bp) {
361: brelse(bp);
362: bp = 0;
363: }
364: goto badarg;
365: }
366: do {
367: if (cc <= 0) {
368: /*
369: * We depend on NCARGS being a multiple of
370: * CLBYTES. This way we need only check
371: * overflow before each buffer allocation.
372: */
373: if (nc >= NCARGS-1) {
374: error = E2BIG;
375: break;
376: }
377: if (bp)
378: bdwrite(bp);
379: cc = CLBYTES;
380: bp = getblk(argdev_vp, bno + ctod(nc/NBPG), cc);
381: cp = bp->b_un.b_addr;
382: }
383: if (sharg) {
384: error = copystr(sharg, cp, (unsigned)cc, &len);
385: sharg += len;
386: } else {
387: error = copyinstr((caddr_t)ap, cp, (unsigned)cc,
388: &len);
389: ap += len;
390: }
391: cp += len;
392: nc += len;
393: cc -= len;
394: } while (error == ENOENT);
395: if (error) {
396: if (bp)
397: brelse(bp);
398: bp = 0;
399: goto badarg;
400: }
401: }
402: if (bp)
403: bdwrite(bp);
404: bp = 0;
405: nc = (nc + NBPW-1) & ~(NBPW-1);
406: error = getxfile(p, vp, &exdata.ex_exec, flags, nc + (na+4)*NBPW,
407: uid, gid);
408: if (error) {
409: badarg:
410: for (cc = 0; cc < nc; cc += CLBYTES) {
411: (void) baddr(argdev_vp, bno + ctod(cc/NBPG),
412: CLBYTES, NOCRED, &tbp);
413: bp = tbp;
414: if (bp) {
415: bp->b_flags |= B_INVAL; /* throw away */
416: brelse(bp);
417: bp = 0;
418: }
419: }
420: goto bad;
421: }
422: if (vp->v_text)
423: vp->v_text->x_mtime = vattr.va_mtime.tv_sec;
424: vput(vp);
425: vp = NULL;
426:
427: #ifdef HPUXCOMPAT
428: /*
429: * We are now committed to the exec so we can save the exec
430: * header in the pcb where we can dump it if necessary in core()
431: */
432: if (u.u_pcb.pcb_flags & PCB_HPUXBIN)
433: bcopy((caddr_t)&hhead,
434: (caddr_t)u.u_pcb.pcb_exec, sizeof hhead);
435: #endif
436:
437: /*
438: * Copy back arglist.
439: */
440: ucp = USRSTACK - nc - NBPW;
441: ap = ucp - na*NBPW - 3*NBPW;
442: u.u_ar0[SP] = ap;
443: (void) suword((caddr_t)ap, na-ne);
444: nc = 0;
445: cc = 0;
446: for (;;) {
447: ap += NBPW;
448: if (na == ne) {
449: (void) suword((caddr_t)ap, 0);
450: ap += NBPW;
451: }
452: if (--na < 0)
453: break;
454: (void) suword((caddr_t)ap, ucp);
455: do {
456: if (cc <= 0) {
457: if (bp)
458: brelse(bp);
459: cc = CLBYTES;
460: error = bread(argdev_vp,
461: (daddr_t)(bno + ctod(nc / NBPG)), cc,
462: NOCRED, &tbp);
463: bp = tbp;
464: bp->b_flags |= B_INVAL; /* throw away */
465: cp = bp->b_un.b_addr;
466: }
467: error = copyoutstr(cp, (caddr_t)ucp, (unsigned)cc,
468: &len);
469: ucp += len;
470: cp += len;
471: nc += len;
472: cc -= len;
473: } while (error == ENOENT);
474: if (error == EFAULT)
475: panic("exec: EFAULT");
476: }
477: (void) suword((caddr_t)ap, 0);
478:
479: execsigs(p);
480:
481: for (nc = u.u_lastfile; nc >= 0; --nc) {
482: if (u.u_pofile[nc] & UF_EXCLOSE) {
483: (void) closef(u.u_ofile[nc]);
484: u.u_ofile[nc] = NULL;
485: u.u_pofile[nc] = 0;
486: }
487: u.u_pofile[nc] &= ~UF_MAPPED;
488: }
489: while (u.u_lastfile >= 0 && u.u_ofile[u.u_lastfile] == NULL)
490: u.u_lastfile--;
491: setregs(exdata.ex_exec.a_entry, retval);
492: /*
493: * Remember file name for accounting.
494: */
495: u.u_acflag &= ~AFORK;
496: if (indir)
497: bcopy((caddr_t)cfname, (caddr_t)p->p_comm, MAXCOMLEN);
498: else {
499: if (ndp->ni_dent.d_namlen > MAXCOMLEN)
500: ndp->ni_dent.d_namlen = MAXCOMLEN;
501: bcopy((caddr_t)ndp->ni_dent.d_name, (caddr_t)p->p_comm,
502: (unsigned)(ndp->ni_dent.d_namlen + 1));
503: }
504: bad:
505: if (bp)
506: brelse(bp);
507: if (bno)
508: rmfree(argmap, (long)ctod(clrnd((int) btoc(NCARGS))), bno);
509: if (vp)
510: vput(vp);
511: return (error);
512: }
513:
514: /*
515: * Read in and set up memory for executed file.
516: */
517: getxfile(p, vp, ep, flags, nargc, uid, gid)
518: register struct proc *p;
519: register struct vnode *vp;
520: register struct exec *ep;
521: int flags, nargc, uid, gid;
522: {
523: segsz_t ts, ds, ids, uds, ss;
524: register struct ucred *cred = u.u_cred;
525: off_t toff;
526: int error;
527:
528: #ifdef HPUXCOMPAT
529: if (ep->a_mid == MID_HPUX)
530: toff = sizeof (struct hpux_exec);
531: else
532: #endif
533: toff = sizeof (struct exec);
534: if (vp->v_text && (vp->v_text->x_flag & XTRC))
535: return (ETXTBSY);
536: if (ep->a_text != 0 && (vp->v_flag & VTEXT) == 0 &&
537: vp->v_usecount != 1) {
538: register struct file *fp;
539:
540: for (fp = file; fp < fileNFILE; fp++) {
541: if (fp->f_type == DTYPE_VNODE &&
542: fp->f_count > 0 &&
543: (struct vnode *)fp->f_data == vp &&
544: (fp->f_flag & FWRITE)) {
545: return (ETXTBSY);
546: }
547: }
548: }
549:
550: /*
551: * Compute text and data sizes and make sure not too large.
552: * NB - Check data and bss separately as they may overflow
553: * when summed together.
554: */
555: ts = clrnd(btoc(ep->a_text));
556: ids = clrnd(btoc(ep->a_data));
557: uds = clrnd(btoc(ep->a_bss));
558: ds = clrnd(btoc(ep->a_data + ep->a_bss));
559: ss = clrnd(SSIZE + btoc(nargc));
560: if (error =
561: chksize((unsigned)ts, (unsigned)ids, (unsigned)uds, (unsigned)ss))
562: return (error);
563:
564: /*
565: * Make sure enough space to start process.
566: */
567: u.u_cdmap = zdmap;
568: u.u_csmap = zdmap;
569: if (error = swpexpand(ds, ss, &u.u_cdmap, &u.u_csmap))
570: return (error);
571:
572: /*
573: * At this point, we are committed to the new image!
574: * Release virtual memory resources of old process, and
575: * initialize the virtual memory of the new process.
576: * If we resulted from vfork(), instead wakeup our
577: * parent who will set SVFDONE when he has taken back
578: * our resources.
579: */
580: if ((p->p_flag & SVFORK) == 0) {
581: #ifdef MAPMEM
582: if (u.u_mmap && (error = mmexec(p)))
583: return (error);
584: #endif
585: vrelvm();
586: } else {
587: p->p_flag &= ~SVFORK;
588: p->p_flag |= SKEEP;
589: wakeup((caddr_t)p);
590: while ((p->p_flag & SVFDONE) == 0)
591: sleep((caddr_t)p, PZERO - 1);
592: p->p_flag &= ~(SVFDONE|SKEEP);
593: }
594: #ifdef hp300
595: u.u_pcb.pcb_flags &= ~(PCB_AST|PCB_HPUXMMAP|PCB_HPUXBIN);
596: #ifdef HPUXCOMPAT
597: /* remember that we were loaded from an HPUX format file */
598: if (ep->a_mid == MID_HPUX)
599: u.u_pcb.pcb_flags |= PCB_HPUXBIN;
600: #endif
601: #endif
602: p->p_flag &= ~(SPAGV|SSEQL|SUANOM|SHPUX);
603: p->p_flag |= flags | SEXEC;
604: u.u_dmap = u.u_cdmap;
605: u.u_smap = u.u_csmap;
606: vgetvm(ts, ds, ss);
607:
608: if ((flags & SPAGV) == 0)
609: (void) vn_rdwr(UIO_READ, vp,
610: (char *)ctob(dptov(p, 0)),
611: (int)ep->a_data,
612: (off_t)(toff + ep->a_text),
613: UIO_USERSPACE, (IO_UNIT|IO_NODELOCKED), cred, (int *)0);
614: xalloc(vp, ep, toff, cred);
615: #if defined(tahoe)
616: /*
617: * Define new keys.
618: */
619: if (p->p_textp == 0) { /* use existing code key if shared */
620: ckeyrelease(p->p_ckey);
621: p->p_ckey = getcodekey();
622: }
623: mtpr(CCK, p->p_ckey);
624: dkeyrelease(p->p_dkey);
625: p->p_dkey = getdatakey();
626: mtpr(DCK, p->p_dkey);
627: #endif
628: if ((flags & SPAGV) && p->p_textp)
629: vinifod(p, (struct fpte *)dptopte(p, 0),
630: PG_FTEXT, p->p_textp->x_vptr,
631: (long)(1 + ts/CLSIZE), (segsz_t)btoc(ep->a_data));
632:
633: #if defined(vax) || defined(tahoe)
634: /* THIS SHOULD BE DONE AT A LOWER LEVEL, IF AT ALL */
635: mtpr(TBIA, 0);
636: #endif
637: #ifdef hp300
638: TBIAU();
639: #endif
640: #if defined(i386)
641: tlbflush();
642: #endif
643:
644: /*
645: * set SUID/SGID protections, if no tracing
646: */
647: if ((p->p_flag&STRC)==0) {
648: if (uid != cred->cr_uid || gid != cred->cr_gid)
649: u.u_cred = cred = crcopy(cred);
650: cred->cr_uid = uid;
651: cred->cr_gid = gid;
652: p->p_uid = uid;
653: } else
654: psignal(p, SIGTRAP);
655: p->p_svuid = p->p_uid;
656: p->p_svgid = cred->cr_gid;
657: u.u_tsize = ts;
658: u.u_dsize = ds;
659: u.u_ssize = ss;
660: u.u_prof.pr_scale = 0;
661: #if defined(tahoe)
662: u.u_pcb.pcb_savacc.faddr = (float *)NULL;
663: #endif
664: return (0);
665: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.