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