1: /* 2: * Copyright (c) 1982, 1986 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: * 6: * @(#)kern_exec.c 7.1 (Berkeley) 6/5/86 7: */ 8: 9: #include "../machine/reg.h" 10: #include "../machine/pte.h" 11: #include "../machine/psl.h" 12: 13: #include "param.h" 14: #include "systm.h" 15: #include "map.h" 16: #include "dir.h" 17: #include "user.h" 18: #include "kernel.h" 19: #include "proc.h" 20: #include "buf.h" 21: #include "inode.h" 22: #include "seg.h" 23: #include "vm.h" 24: #include "text.h" 25: #include "file.h" 26: #include "uio.h" 27: #include "acct.h" 28: #include "exec.h" 29: 30: #ifdef vax 31: #include "../vax/mtpr.h" 32: #endif 33: 34: /* 35: * exec system call, with and without environments. 36: */ 37: struct execa { 38: char *fname; 39: char **argp; 40: char **envp; 41: }; 42: 43: execv() 44: { 45: ((struct execa *)u.u_ap)->envp = NULL; 46: execve(); 47: } 48: 49: execve() 50: { 51: register nc; 52: register char *cp; 53: register struct buf *bp; 54: register struct execa *uap; 55: int na, ne, ucp, ap, cc; 56: unsigned len; 57: int indir, uid, gid; 58: char *sharg; 59: struct inode *ip; 60: swblk_t bno; 61: char cfname[MAXCOMLEN + 1]; 62: #define SHSIZE 32 63: char cfarg[SHSIZE]; 64: union { 65: char ex_shell[SHSIZE]; /* #! and name of interpreter */ 66: struct exec ex_exec; 67: } exdata; 68: register struct nameidata *ndp = &u.u_nd; 69: int resid, error; 70: 71: ndp->ni_nameiop = LOOKUP | FOLLOW; 72: ndp->ni_segflg = UIO_USERSPACE; 73: ndp->ni_dirp = ((struct execa *)u.u_ap)->fname; 74: if ((ip = namei(ndp)) == NULL) 75: return; 76: bno = 0; 77: bp = 0; 78: indir = 0; 79: uid = u.u_uid; 80: gid = u.u_gid; 81: if (ip->i_mode & ISUID) 82: uid = ip->i_uid; 83: if (ip->i_mode & ISGID) 84: gid = ip->i_gid; 85: 86: again: 87: if (access(ip, IEXEC)) 88: goto bad; 89: if ((u.u_procp->p_flag&STRC) && access(ip, IREAD)) 90: goto bad; 91: if ((ip->i_mode & IFMT) != IFREG || 92: (ip->i_mode & (IEXEC|(IEXEC>>3)|(IEXEC>>6))) == 0) { 93: u.u_error = EACCES; 94: goto bad; 95: } 96: 97: /* 98: * Read in first few bytes of file for segment sizes, magic number: 99: * 407 = plain executable 100: * 410 = RO text 101: * 413 = demand paged RO text 102: * Also an ASCII line beginning with #! is 103: * the file name of a ``shell'' and arguments may be prepended 104: * to the argument list if given here. 105: * 106: * SHELL NAMES ARE LIMITED IN LENGTH. 107: * 108: * ONLY ONE ARGUMENT MAY BE PASSED TO THE SHELL FROM 109: * THE ASCII LINE. 110: */ 111: exdata.ex_shell[0] = '\0'; /* for zero length files */ 112: u.u_error = rdwri(UIO_READ, ip, (caddr_t)&exdata, sizeof (exdata), 113: (off_t)0, 1, &resid); 114: if (u.u_error) 115: goto bad; 116: #ifndef lint 117: if (resid > sizeof(exdata) - sizeof(exdata.ex_exec) && 118: exdata.ex_shell[0] != '#') { 119: u.u_error = ENOEXEC; 120: goto bad; 121: } 122: #endif 123: switch ((int)exdata.ex_exec.a_magic) { 124: 125: case 0407: 126: exdata.ex_exec.a_data += exdata.ex_exec.a_text; 127: exdata.ex_exec.a_text = 0; 128: break; 129: 130: case 0413: 131: case 0410: 132: if (exdata.ex_exec.a_text == 0) { 133: u.u_error = ENOEXEC; 134: goto bad; 135: } 136: break; 137: 138: default: 139: if (exdata.ex_shell[0] != '#' || 140: exdata.ex_shell[1] != '!' || 141: indir) { 142: u.u_error = ENOEXEC; 143: goto bad; 144: } 145: cp = &exdata.ex_shell[2]; /* skip "#!" */ 146: while (cp < &exdata.ex_shell[SHSIZE]) { 147: if (*cp == '\t') 148: *cp = ' '; 149: else if (*cp == '\n') { 150: *cp = '\0'; 151: break; 152: } 153: cp++; 154: } 155: if (*cp != '\0') { 156: u.u_error = ENOEXEC; 157: goto bad; 158: } 159: cp = &exdata.ex_shell[2]; 160: while (*cp == ' ') 161: cp++; 162: ndp->ni_dirp = cp; 163: while (*cp && *cp != ' ') 164: cp++; 165: cfarg[0] = '\0'; 166: if (*cp) { 167: *cp++ = '\0'; 168: while (*cp == ' ') 169: cp++; 170: if (*cp) 171: bcopy((caddr_t)cp, (caddr_t)cfarg, SHSIZE); 172: } 173: indir = 1; 174: iput(ip); 175: ndp->ni_nameiop = LOOKUP | FOLLOW; 176: ndp->ni_segflg = UIO_SYSSPACE; 177: ip = namei(ndp); 178: if (ip == NULL) 179: return; 180: bcopy((caddr_t)ndp->ni_dent.d_name, (caddr_t)cfname, 181: MAXCOMLEN); 182: cfname[MAXCOMLEN] = '\0'; 183: goto again; 184: } 185: 186: /* 187: * Collect arguments on "file" in swap space. 188: */ 189: na = 0; 190: ne = 0; 191: nc = 0; 192: cc = 0; 193: uap = (struct execa *)u.u_ap; 194: bno = rmalloc(argmap, (long)ctod(clrnd((int)btoc(NCARGS)))); 195: if (bno == 0) { 196: swkill(u.u_procp, "exec: no swap space"); 197: goto bad; 198: } 199: if (bno % CLSIZE) 200: panic("execa rmalloc"); 201: /* 202: * Copy arguments into file in argdev area. 203: */ 204: if (uap->argp) for (;;) { 205: ap = NULL; 206: sharg = NULL; 207: if (indir && na == 0) { 208: sharg = cfname; 209: ap = (int)sharg; 210: uap->argp++; /* ignore argv[0] */ 211: } else if (indir && (na == 1 && cfarg[0])) { 212: sharg = cfarg; 213: ap = (int)sharg; 214: } else if (indir && (na == 1 || na == 2 && cfarg[0])) 215: ap = (int)uap->fname; 216: else if (uap->argp) { 217: ap = fuword((caddr_t)uap->argp); 218: uap->argp++; 219: } 220: if (ap == NULL && uap->envp) { 221: uap->argp = NULL; 222: if ((ap = fuword((caddr_t)uap->envp)) != NULL) 223: uap->envp++, ne++; 224: } 225: if (ap == NULL) 226: break; 227: na++; 228: if (ap == -1) { 229: u.u_error = EFAULT; 230: break; 231: } 232: do { 233: if (cc <= 0) { 234: /* 235: * We depend on NCARGS being a multiple of 236: * CLSIZE*NBPG. This way we need only check 237: * overflow before each buffer allocation. 238: */ 239: if (nc >= NCARGS-1) { 240: error = E2BIG; 241: break; 242: } 243: if (bp) 244: bdwrite(bp); 245: cc = CLSIZE*NBPG; 246: bp = getblk(argdev, bno + ctod(nc/NBPG), cc); 247: cp = bp->b_un.b_addr; 248: } 249: if (sharg) { 250: error = copystr(sharg, cp, (unsigned)cc, &len); 251: sharg += len; 252: } else { 253: error = copyinstr((caddr_t)ap, cp, (unsigned)cc, 254: &len); 255: ap += len; 256: } 257: cp += len; 258: nc += len; 259: cc -= len; 260: } while (error == ENOENT); 261: if (error) { 262: u.u_error = error; 263: if (bp) 264: brelse(bp); 265: bp = 0; 266: goto badarg; 267: } 268: } 269: if (bp) 270: bdwrite(bp); 271: bp = 0; 272: nc = (nc + NBPW-1) & ~(NBPW-1); 273: getxfile(ip, &exdata.ex_exec, nc + (na+4)*NBPW, uid, gid); 274: if (u.u_error) { 275: badarg: 276: for (cc = 0; cc < nc; cc += CLSIZE*NBPG) { 277: bp = baddr(argdev, bno + ctod(cc/NBPG), CLSIZE*NBPG); 278: if (bp) { 279: bp->b_flags |= B_AGE; /* throw away */ 280: bp->b_flags &= ~B_DELWRI; /* cancel io */ 281: brelse(bp); 282: bp = 0; 283: } 284: } 285: goto bad; 286: } 287: iput(ip); 288: ip = NULL; 289: 290: /* 291: * Copy back arglist. 292: */ 293: ucp = USRSTACK - nc - NBPW; 294: ap = ucp - na*NBPW - 3*NBPW; 295: u.u_ar0[SP] = ap; 296: (void) suword((caddr_t)ap, na-ne); 297: nc = 0; 298: cc = 0; 299: for (;;) { 300: ap += NBPW; 301: if (na == ne) { 302: (void) suword((caddr_t)ap, 0); 303: ap += NBPW; 304: } 305: if (--na < 0) 306: break; 307: (void) suword((caddr_t)ap, ucp); 308: do { 309: if (cc <= 0) { 310: if (bp) 311: brelse(bp); 312: cc = CLSIZE*NBPG; 313: bp = bread(argdev, bno + ctod(nc / NBPG), cc); 314: bp->b_flags |= B_AGE; /* throw away */ 315: bp->b_flags &= ~B_DELWRI; /* cancel io */ 316: cp = bp->b_un.b_addr; 317: } 318: error = copyoutstr(cp, (caddr_t)ucp, (unsigned)cc, 319: &len); 320: ucp += len; 321: cp += len; 322: nc += len; 323: cc -= len; 324: } while (error == ENOENT); 325: if (error == EFAULT) 326: panic("exec: EFAULT"); 327: } 328: (void) suword((caddr_t)ap, 0); 329: 330: /* 331: * Reset caught signals. Held signals 332: * remain held through p_sigmask. 333: */ 334: while (u.u_procp->p_sigcatch) { 335: nc = ffs((long)u.u_procp->p_sigcatch); 336: u.u_procp->p_sigcatch &= ~sigmask(nc); 337: u.u_signal[nc] = SIG_DFL; 338: } 339: /* 340: * Reset stack state to the user stack. 341: * Clear set of signals caught on the signal stack. 342: */ 343: u.u_onstack = 0; 344: u.u_sigsp = 0; 345: u.u_sigonstack = 0; 346: 347: for (nc = u.u_lastfile; nc >= 0; --nc) { 348: if (u.u_pofile[nc] & UF_EXCLOSE) { 349: closef(u.u_ofile[nc]); 350: u.u_ofile[nc] = NULL; 351: u.u_pofile[nc] = 0; 352: } 353: u.u_pofile[nc] &= ~UF_MAPPED; 354: } 355: while (u.u_lastfile >= 0 && u.u_ofile[u.u_lastfile] == NULL) 356: u.u_lastfile--; 357: setregs(exdata.ex_exec.a_entry); 358: /* 359: * Remember file name for accounting. 360: */ 361: u.u_acflag &= ~AFORK; 362: if (indir) 363: bcopy((caddr_t)cfname, (caddr_t)u.u_comm, MAXCOMLEN); 364: else { 365: if (ndp->ni_dent.d_namlen > MAXCOMLEN) 366: ndp->ni_dent.d_namlen = MAXCOMLEN; 367: bcopy((caddr_t)ndp->ni_dent.d_name, (caddr_t)u.u_comm, 368: (unsigned)(ndp->ni_dent.d_namlen + 1)); 369: } 370: bad: 371: if (bp) 372: brelse(bp); 373: if (bno) 374: rmfree(argmap, (long)ctod(clrnd((int) btoc(NCARGS))), bno); 375: if (ip) 376: iput(ip); 377: } 378: 379: /* 380: * Read in and set up memory for executed file. 381: */ 382: getxfile(ip, ep, nargc, uid, gid) 383: register struct inode *ip; 384: register struct exec *ep; 385: int nargc, uid, gid; 386: { 387: size_t ts, ds, ids, uds, ss; 388: int pagi; 389: 390: if (ep->a_magic == 0413) 391: pagi = SPAGI; 392: else 393: pagi = 0; 394: if (ip->i_text && (ip->i_text->x_flag & XTRC)) { 395: u.u_error = ETXTBSY; 396: goto bad; 397: } 398: if (ep->a_text != 0 && (ip->i_flag&ITEXT) == 0 && 399: ip->i_count != 1) { 400: register struct file *fp; 401: 402: for (fp = file; fp < fileNFILE; fp++) { 403: if (fp->f_type == DTYPE_INODE && 404: fp->f_count > 0 && 405: (struct inode *)fp->f_data == ip && 406: (fp->f_flag&FWRITE)) { 407: u.u_error = ETXTBSY; 408: goto bad; 409: } 410: } 411: } 412: 413: /* 414: * Compute text and data sizes and make sure not too large. 415: * NB - Check data and bss separately as they may overflow 416: * when summed together. 417: */ 418: ts = clrnd(btoc(ep->a_text)); 419: ids = clrnd(btoc(ep->a_data)); 420: uds = clrnd(btoc(ep->a_bss)); 421: ds = clrnd(btoc(ep->a_data + ep->a_bss)); 422: ss = clrnd(SSIZE + btoc(nargc)); 423: if (chksize((unsigned)ts, (unsigned)ids, (unsigned)uds, (unsigned)ss)) 424: goto bad; 425: 426: /* 427: * Make sure enough space to start process. 428: */ 429: u.u_cdmap = zdmap; 430: u.u_csmap = zdmap; 431: if (swpexpand(ds, ss, &u.u_cdmap, &u.u_csmap) == NULL) 432: goto bad; 433: 434: /* 435: * At this point, committed to the new image! 436: * Release virtual memory resources of old process, and 437: * initialize the virtual memory of the new process. 438: * If we resulted from vfork(), instead wakeup our 439: * parent who will set SVFDONE when he has taken back 440: * our resources. 441: */ 442: if ((u.u_procp->p_flag & SVFORK) == 0) 443: vrelvm(); 444: else { 445: u.u_procp->p_flag &= ~SVFORK; 446: u.u_procp->p_flag |= SKEEP; 447: wakeup((caddr_t)u.u_procp); 448: while ((u.u_procp->p_flag & SVFDONE) == 0) 449: sleep((caddr_t)u.u_procp, PZERO - 1); 450: u.u_procp->p_flag &= ~(SVFDONE|SKEEP); 451: } 452: u.u_procp->p_flag &= ~(SPAGI|SSEQL|SUANOM|SOUSIG); 453: u.u_procp->p_flag |= pagi; 454: u.u_dmap = u.u_cdmap; 455: u.u_smap = u.u_csmap; 456: vgetvm(ts, ds, ss); 457: 458: if (pagi == 0) 459: u.u_error = 460: rdwri(UIO_READ, ip, 461: (char *)ctob(dptov(u.u_procp, 0)), 462: (int)ep->a_data, 463: (off_t)(sizeof (struct exec) + ep->a_text), 464: 0, (int *)0); 465: xalloc(ip, ep, pagi); 466: if (pagi && u.u_procp->p_textp) 467: vinifod((struct fpte *)dptopte(u.u_procp, 0), 468: PG_FTEXT, u.u_procp->p_textp->x_iptr, 469: (long)(1 + ts/CLSIZE), (size_t)btoc(ep->a_data)); 470: 471: #ifdef vax 472: /* THIS SHOULD BE DONE AT A LOWER LEVEL, IF AT ALL */ 473: mtpr(TBIA, 0); 474: #endif 475: 476: if (u.u_error) 477: swkill(u.u_procp, "exec: I/O error mapping pages"); 478: /* 479: * set SUID/SGID protections, if no tracing 480: */ 481: if ((u.u_procp->p_flag&STRC)==0) { 482: u.u_uid = uid; 483: u.u_procp->p_uid = uid; 484: u.u_gid = gid; 485: } else 486: psignal(u.u_procp, SIGTRAP); 487: u.u_tsize = ts; 488: u.u_dsize = ds; 489: u.u_ssize = ss; 490: u.u_prof.pr_scale = 0; 491: bad: 492: return; 493: }