1: /* 2: * Copyright (c) 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 1.8 (2.11BSD) 1999/9/6 7: */ 8: 9: #include "param.h" 10: #include "../machine/reg.h" 11: #include "../machine/seg.h" 12: 13: #include "systm.h" 14: #include "map.h" 15: #include "user.h" 16: #include "proc.h" 17: #include "buf.h" 18: #include "inode.h" 19: #include "acct.h" 20: #include "namei.h" 21: #include "fs.h" 22: #include "mount.h" 23: #include "file.h" 24: #include "text.h" 25: #include "signalvar.h" 26: extern char sigprop[]; /* XXX */ 27: 28: /* 29: * exec system call, with and without environments. 30: */ 31: struct execa { 32: char *fname; 33: char **argp; 34: char **envp; 35: }; 36: 37: execv() 38: { 39: ((struct execa *)u.u_ap)->envp = NULL; 40: execve(); 41: } 42: 43: execve() 44: { 45: int nc; 46: register char *cp; 47: register struct buf *bp; 48: struct execa *uap = (struct execa *)u.u_ap; 49: int na, ne, ucp, ap; 50: register int cc; 51: unsigned len; 52: int indir, uid, gid; 53: char *sharg; 54: struct inode *ip; 55: memaddr bno; 56: char cfname[MAXCOMLEN + 1]; 57: #define SHSIZE 32 58: char cfarg[SHSIZE]; 59: union { 60: char ex_shell[SHSIZE]; /* #! and name of interpreter */ 61: struct exec ex_exec; 62: } exdata; 63: struct nameidata nd; 64: register struct nameidata *ndp = &nd; 65: int resid, error; 66: 67: NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, uap->fname); 68: if ((ip = namei(ndp)) == NULL) 69: return; 70: bno = 0; 71: bp = 0; 72: indir = 0; 73: uid = u.u_uid; 74: gid = u.u_groups[0]; 75: if (ip->i_fs->fs_flags & MNT_NOEXEC) { 76: u.u_error = EACCES; 77: goto bad; 78: } 79: if ((ip->i_fs->fs_flags & MNT_NOSUID) == 0) { 80: if (ip->i_mode & ISUID) 81: uid = ip->i_uid; 82: if (ip->i_mode & ISGID) 83: gid = ip->i_gid; 84: } 85: again: 86: if (access(ip, IEXEC)) 87: goto bad; 88: if ((u.u_procp->p_flag & P_TRACED) && access(ip, IREAD)) 89: goto bad; 90: if ((ip->i_mode & IFMT) != IFREG || 91: (ip->i_mode & (IEXEC|(IEXEC>>3)|(IEXEC>>6))) == 0) { 92: u.u_error = EACCES; 93: goto bad; 94: } 95: 96: /* 97: * Read in first few bytes of file for segment sizes, magic number: 98: * 407 = plain executable 99: * 410 = RO text 100: * 411 = separated I/D 101: * 405 = text overlay 102: * 430 = auto-overlay (nonseparate) 103: * 431 = auto-overlay (separate) 104: * Also an ASCII line beginning with #! is 105: * the file name of a ``shell'' and arguments may be prepended 106: * to the argument list if given here. 107: * 108: * SHELL NAMES ARE LIMITED IN LENGTH. 109: * 110: * ONLY ONE ARGUMENT MAY BE PASSED TO THE SHELL FROM 111: * THE ASCII LINE. 112: */ 113: exdata.ex_shell[0] = '\0'; /* for zero length files */ 114: u.u_error = rdwri(UIO_READ, ip, &exdata, sizeof(exdata), (off_t)0, 115: UIO_SYSSPACE, IO_UNIT, &resid); 116: if (u.u_error) 117: goto bad; 118: if (resid > sizeof(exdata) - sizeof(exdata.ex_exec) && 119: exdata.ex_shell[0] != '#') { 120: u.u_error = ENOEXEC; 121: goto bad; 122: } 123: 124: switch((int)exdata.ex_exec.a_magic) { 125: 126: case A_MAGIC1: 127: case A_MAGIC2: 128: case A_MAGIC3: 129: case A_MAGIC4: 130: case A_MAGIC5: 131: case A_MAGIC6: 132: break; 133: 134: default: 135: if (exdata.ex_shell[0] != '#' || 136: exdata.ex_shell[1] != '!' || 137: indir) { 138: u.u_error = ENOEXEC; 139: goto bad; 140: } 141: /* 142: * If setuid/gid scripts were to be disallowed this is where it would 143: * have to be done. 144: * u.u_uid = uid; 145: * u.u_gid = u_groups[0]; 146: */ 147: cp = &exdata.ex_shell[2]; /* skip "#!" */ 148: while (cp < &exdata.ex_shell[SHSIZE]) { 149: if (*cp == '\t') 150: *cp = ' '; 151: else if (*cp == '\n') { 152: *cp = '\0'; 153: break; 154: } 155: cp++; 156: } 157: if (*cp != '\0') { 158: u.u_error = ENOEXEC; 159: goto bad; 160: } 161: cp = &exdata.ex_shell[2]; 162: while (*cp == ' ') 163: cp++; 164: ndp->ni_dirp = cp; 165: while (*cp && *cp != ' ') 166: cp++; 167: cfarg[0] = '\0'; 168: if (*cp) { 169: *cp++ = '\0'; 170: while (*cp == ' ') 171: cp++; 172: if (*cp) 173: bcopy((caddr_t)cp, (caddr_t)cfarg, SHSIZE); 174: } 175: indir = 1; 176: iput(ip); 177: ndp->ni_nameiop = LOOKUP | FOLLOW; 178: ndp->ni_segflg = UIO_SYSSPACE; 179: ip = namei(ndp); 180: if (ip == NULL) 181: return; 182: bcopy((caddr_t)ndp->ni_dent.d_name, (caddr_t)cfname, MAXCOMLEN); 183: cfname[MAXCOMLEN] = '\0'; 184: goto again; 185: } 186: 187: /* 188: * Collect arguments on "file" in swap space. 189: */ 190: na = 0; 191: ne = 0; 192: nc = 0; 193: cc = 0; 194: bno = malloc(swapmap, ctod((int)btoc(NCARGS + MAXBSIZE))); 195: if (bno == 0) { 196: swkill(u.u_procp, "exec"); 197: goto bad; 198: } 199: /* 200: * Copy arguments into file in argdev area. 201: */ 202: if (uap->argp) for (;;) { 203: ap = NULL; 204: sharg = NULL; 205: if (indir && na == 0) { 206: sharg = cfname; 207: ap = (int)sharg; 208: uap->argp++; /* ignore argv[0] */ 209: } else if (indir && (na == 1 && cfarg[0])) { 210: sharg = cfarg; 211: ap = (int)sharg; 212: } else if (indir && (na == 1 || na == 2 && cfarg[0])) 213: ap = (int)uap->fname; 214: else if (uap->argp) { 215: ap = fuword((caddr_t)uap->argp); 216: uap->argp++; 217: } 218: if (ap == NULL && uap->envp) { 219: uap->argp = NULL; 220: if ((ap = fuword((caddr_t)uap->envp)) != NULL) 221: uap->envp++, ne++; 222: } 223: if (ap == NULL) 224: break; 225: na++; 226: if (ap == -1) { 227: u.u_error = EFAULT; 228: break; 229: } 230: do { 231: if (cc <= 0) { 232: /* 233: * We depend on NCARGS being a multiple of 234: * CLSIZE*NBPG. This way we need only check 235: * overflow before each buffer allocation. 236: */ 237: if (nc >= NCARGS-1) { 238: error = E2BIG; 239: break; 240: } 241: if (bp) { 242: mapout(bp); 243: bdwrite(bp); 244: } 245: cc = CLSIZE*NBPG; 246: bp = getblk(swapdev, dbtofsb(clrnd(bno)) + lblkno(nc)); 247: cp = mapin(bp); 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: mapout(bp); 265: bp->b_flags |= B_AGE; 266: bp->b_flags &= ~B_DELWRI; 267: brelse(bp); 268: } 269: bp = 0; 270: goto badarg; 271: } 272: } 273: if (bp) { 274: mapout(bp); 275: bdwrite(bp); 276: } 277: bp = 0; 278: nc = (nc + NBPW-1) & ~(NBPW-1); 279: getxfile(ip, &exdata.ex_exec, nc + (na+4)*NBPW, uid, gid); 280: if (u.u_error) { 281: badarg: 282: for (cc = 0;cc < nc; cc += CLSIZE * NBPG) { 283: daddr_t blkno; 284: 285: blkno = dbtofsb(clrnd(bno)) + lblkno(cc); 286: if (incore(swapdev,blkno)) { 287: bp = bread(swapdev,blkno); 288: bp->b_flags |= B_AGE; /* throw away */ 289: bp->b_flags &= ~B_DELWRI; /* cancel io */ 290: brelse(bp); 291: bp = 0; 292: } 293: } 294: goto bad; 295: } 296: iput(ip); 297: ip = NULL; 298: 299: /* 300: * Copy back arglist. 301: */ 302: ucp = -nc - NBPW; 303: ap = ucp - na*NBPW - 3*NBPW; 304: u.u_ar0[R6] = ap; 305: (void) suword((caddr_t)ap, na-ne); 306: nc = 0; 307: cc = 0; 308: for (;;) { 309: ap += NBPW; 310: if (na == ne) { 311: (void) suword((caddr_t)ap, 0); 312: ap += NBPW; 313: } 314: if (--na < 0) 315: break; 316: (void) suword((caddr_t)ap, ucp); 317: do { 318: if (cc <= 0) { 319: if (bp) { 320: mapout(bp); 321: brelse(bp); 322: } 323: cc = CLSIZE*NBPG; 324: bp = bread(swapdev, dbtofsb(clrnd(bno)) + lblkno(nc)); 325: bp->b_flags |= B_AGE; /* throw away */ 326: bp->b_flags &= ~B_DELWRI; /* cancel io */ 327: cp = mapin(bp); 328: } 329: error = copyoutstr(cp, (caddr_t)ucp, (unsigned)cc, 330: &len); 331: ucp += len; 332: cp += len; 333: nc += len; 334: cc -= len; 335: } while (error == ENOENT); 336: if (error == EFAULT) 337: panic("exec: EFAULT"); 338: } 339: (void) suword((caddr_t)ap, 0); 340: (void) suword((caddr_t)(-NBPW), 0); 341: if (bp) { 342: mapout(bp); 343: bp->b_flags |= B_AGE; 344: brelse(bp); 345: bp = NULL; 346: } 347: execsigs(u.u_procp); 348: for (cp = u.u_pofile, cc = 0; cc <= u.u_lastfile; cc++, cp++) 349: { 350: if (*cp & UF_EXCLOSE) 351: { 352: (void)closef(u.u_ofile[cc]); 353: u.u_ofile[cc] = NULL; 354: *cp = 0; 355: } 356: } 357: while (u.u_lastfile >= 0 && u.u_ofile[u.u_lastfile] == NULL) 358: u.u_lastfile--; 359: 360: /* 361: * inline expansion of setregs(), found 362: * in ../pdp/machdep.c 363: * 364: * setregs(exdata.ex_exec.a_entry); 365: */ 366: u.u_ar0[PC] = exdata.ex_exec.a_entry & ~01; 367: u.u_fps.u_fpsr = 0; 368: 369: /* 370: * Remember file name for accounting. 371: */ 372: u.u_acflag &= ~AFORK; 373: if (indir) 374: bcopy((caddr_t)cfname, (caddr_t)u.u_comm, MAXCOMLEN); 375: else 376: bcopy((caddr_t)ndp->ni_dent.d_name, (caddr_t)u.u_comm, MAXCOMLEN); 377: bad: 378: if (bp) { 379: mapout(bp); 380: bp->b_flags |= B_AGE; 381: brelse(bp); 382: } 383: if (bno) 384: mfree(swapmap, ctod((int)btoc(NCARGS + MAXBSIZE)), bno); 385: if (ip) 386: iput(ip); 387: } 388: 389: /* 390: * Reset signals for an exec of the specified process. In 4.4 this function 391: * was in kern_sig.c but since in 2.11 kern_sig and kern_exec will likely be 392: * in different overlays placing this here potentially saves a kernel overlay 393: * switch. 394: */ 395: void 396: execsigs(p) 397: register struct proc *p; 398: { 399: register int nc; 400: unsigned long mask; 401: 402: /* 403: * Reset caught signals. Held signals remain held 404: * through p_sigmask (unless they were caught, 405: * and are now ignored by default). 406: */ 407: while (p->p_sigcatch) { 408: nc = ffs(p->p_sigcatch); 409: mask = sigmask(nc); 410: p->p_sigcatch &= ~mask; 411: if (sigprop[nc] & SA_IGNORE) { 412: if (nc != SIGCONT) 413: p->p_sigignore |= mask; 414: p->p_sig &= ~mask; 415: } 416: u.u_signal[nc] = SIG_DFL; 417: } 418: /* 419: * Reset stack state to the user stack (disable the alternate stack). 420: */ 421: u.u_sigstk.ss_flags = SA_DISABLE; 422: u.u_sigstk.ss_size = 0; 423: u.u_sigstk.ss_base = 0; 424: u.u_psflags = 0; 425: } 426: /* 427: * Read in and set up memory for executed file. 428: * u.u_error set on error 429: */ 430: getxfile(ip, ep, nargc, uid, gid) 431: struct inode *ip; 432: register struct exec *ep; 433: int nargc, uid, gid; 434: { 435: struct u_ovd sovdata; 436: long lsize; 437: off_t offset; 438: u_int ds, ts, ss; 439: u_int ovhead[NOVL + 1]; 440: int sep, overlay, ovflag, ovmax, resid; 441: 442: overlay = sep = ovflag = 0; 443: switch(ep->a_magic) { 444: case A_MAGIC1: 445: lsize = (long)ep->a_data + ep->a_text; 446: ep->a_data = (u_int)lsize; 447: if (lsize != ep->a_data) { /* check overflow */ 448: u.u_error = ENOMEM; 449: return; 450: } 451: ep->a_text = 0; 452: break; 453: case A_MAGIC3: 454: sep++; 455: break; 456: case A_MAGIC4: 457: overlay++; 458: break; 459: case A_MAGIC5: 460: ovflag++; 461: break; 462: case A_MAGIC6: 463: sep++; 464: ovflag++; 465: break; 466: } 467: 468: if (ip->i_text && (ip->i_text->x_flag & XTRC)) { 469: u.u_error = ETXTBSY; 470: return; 471: } 472: if (ep->a_text != 0 && (ip->i_flag&ITEXT) == 0 && 473: ip->i_count != 1) { 474: register struct file *fp; 475: 476: for (fp = file; fp < fileNFILE; fp++) { 477: if (fp->f_type == DTYPE_INODE && 478: fp->f_count > 0 && 479: (struct inode *)fp->f_data == ip && 480: (fp->f_flag&FWRITE)) { 481: u.u_error = ETXTBSY; 482: return; 483: } 484: } 485: } 486: 487: /* 488: * find text and data sizes try; them out for possible 489: * overflow of max sizes 490: */ 491: ts = btoc(ep->a_text); 492: lsize = (long)ep->a_data + ep->a_bss; 493: if (lsize != (u_int)lsize) { 494: u.u_error = ENOMEM; 495: return; 496: } 497: ds = btoc(lsize); 498: ss = SSIZE + btoc(nargc); 499: 500: /* 501: * if auto overlay get second header 502: */ 503: sovdata = u.u_ovdata; 504: u.u_ovdata.uo_ovbase = 0; 505: u.u_ovdata.uo_curov = 0; 506: if (ovflag) { 507: u.u_error = rdwri(UIO_READ, ip, ovhead, sizeof(ovhead), 508: (off_t)sizeof(struct exec), UIO_SYSSPACE, IO_UNIT, &resid); 509: if (resid != 0) 510: u.u_error = ENOEXEC; 511: if (u.u_error) { 512: u.u_ovdata = sovdata; 513: return; 514: } 515: /* set beginning of overlay segment */ 516: u.u_ovdata.uo_ovbase = ctos(ts); 517: 518: /* 0th entry is max size of the overlays */ 519: ovmax = btoc(ovhead[0]); 520: 521: /* set max number of segm. registers to be used */ 522: u.u_ovdata.uo_nseg = ctos(ovmax); 523: 524: /* set base of data space */ 525: u.u_ovdata.uo_dbase = stoc(u.u_ovdata.uo_ovbase + 526: u.u_ovdata.uo_nseg); 527: 528: /* 529: * Set up a table of offsets to each of the overlay 530: * segements. The ith overlay runs from ov_offst[i-1] 531: * to ov_offst[i]. 532: */ 533: u.u_ovdata.uo_ov_offst[0] = ts; 534: { 535: register int t, i; 536: 537: /* check if any overlay is larger than ovmax */ 538: for (i = 1; i <= NOVL; i++) { 539: if ((t = btoc(ovhead[i])) > ovmax) { 540: u.u_error = ENOEXEC; 541: u.u_ovdata = sovdata; 542: return; 543: } 544: u.u_ovdata.uo_ov_offst[i] = 545: t + u.u_ovdata.uo_ov_offst[i - 1]; 546: } 547: } 548: } 549: if (overlay) { 550: if (u.u_sep == 0 && ctos(ts) != ctos(u.u_tsize) || nargc) { 551: u.u_error = ENOMEM; 552: return; 553: } 554: ds = u.u_dsize; 555: ss = u.u_ssize; 556: sep = u.u_sep; 557: xfree(); 558: xalloc(ip,ep); 559: u.u_ar0[PC] = ep->a_entry & ~01; 560: } else { 561: if (estabur(ts, ds, ss, sep, RO)) { 562: u.u_ovdata = sovdata; 563: return; 564: } 565: 566: /* 567: * allocate and clear core at this point, committed 568: * to the new image 569: */ 570: u.u_prof.pr_scale = 0; 571: if (u.u_procp->p_flag & SVFORK) 572: endvfork(); 573: else 574: xfree(); 575: expand(ds, S_DATA); 576: { 577: register u_int numc, startc; 578: 579: startc = btoc(ep->a_data); /* clear BSS only */ 580: if (startc != 0) 581: startc--; 582: numc = ds - startc; 583: clear(u.u_procp->p_daddr + startc, numc); 584: } 585: expand(ss, S_STACK); 586: clear(u.u_procp->p_saddr, ss); 587: xalloc(ip, ep); 588: 589: /* 590: * read in data segment 591: */ 592: estabur((u_int)0, ds, (u_int)0, 0, RO); 593: offset = sizeof(struct exec); 594: if (ovflag) { 595: offset += sizeof(ovhead); 596: offset += (((long)u.u_ovdata.uo_ov_offst[NOVL]) << 6); 597: } 598: else 599: offset += ep->a_text; 600: rdwri(UIO_READ, ip, (caddr_t) 0, ep->a_data, offset, 601: UIO_USERSPACE, IO_UNIT, (int *)0); 602: 603: /* 604: * set SUID/SGID protections, if no tracing 605: */ 606: if ((u.u_procp->p_flag & P_TRACED)==0) { 607: u.u_uid = uid; 608: u.u_procp->p_uid = uid; 609: u.u_groups[0] = gid; 610: } else 611: psignal(u.u_procp, SIGTRAP); 612: u.u_svuid = u.u_uid; 613: u.u_svgid = u.u_groups[0]; 614: u.u_acflag &= ~ASUGID; /* start fresh setuid/gid priv use */ 615: } 616: u.u_tsize = ts; 617: u.u_dsize = ds; 618: u.u_ssize = ss; 619: u.u_sep = sep; 620: estabur(ts, ds, ss, sep, RO); 621: }