1 /* 2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 3 * All rights reserved. 4 * 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 * 17 * @(#)kern_exec.c 7.21 (Berkeley) 02/23/90 18 */ 19 20 #include "param.h" 21 #include "systm.h" 22 #include "map.h" 23 #include "user.h" 24 #include "kernel.h" 25 #include "proc.h" 26 #include "mount.h" 27 #include "ucred.h" 28 #include "malloc.h" 29 #include "buf.h" 30 #include "vnode.h" 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" 38 39 #include "machine/reg.h" 40 #include "machine/pte.h" 41 #include "machine/psl.h" 42 #include "machine/mtpr.h" 43 44 /* 45 * exec system call, with and without environments. 46 */ 47 struct execa { 48 char *fname; 49 char **argp; 50 char **envp; 51 }; 52 53 execv() 54 { 55 ((struct execa *)u.u_ap)->envp = NULL; 56 execve(); 57 } 58 59 execve() 60 { 61 register nc; 62 register char *cp; 63 register struct buf *bp; 64 struct buf *tbp; 65 register struct execa *uap; 66 int na, ne, ucp, ap, cc; 67 unsigned len; 68 int indir, uid, gid; 69 char *sharg; 70 struct vnode *vp; 71 swblk_t bno; 72 struct vattr vattr; 73 char cfname[MAXCOMLEN + 1]; 74 char cfarg[MAXINTERP]; 75 union { 76 char ex_shell[MAXINTERP]; /* #! and interpreter name */ 77 struct exec ex_exec; 78 } exdata; 79 register struct nameidata *ndp = &u.u_nd; 80 int resid, error; 81 82 start: 83 ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 84 ndp->ni_segflg = UIO_USERSPACE; 85 ndp->ni_dirp = ((struct execa *)u.u_ap)->fname; 86 if (u.u_error = namei(ndp)) { 87 return; 88 } 89 vp = ndp->ni_vp; 90 bno = 0; 91 bp = 0; 92 indir = 0; 93 uid = u.u_cred->cr_uid; 94 gid = u.u_cred->cr_gid; 95 if (u.u_error = VOP_GETATTR(vp, &vattr, u.u_cred)) 96 goto bad; 97 if (vp->v_mount->m_flag & M_NOEXEC) { 98 u.u_error = EACCES; 99 goto bad; 100 } 101 if ((vp->v_mount->m_flag & M_NOSUID) == 0) { 102 if (vattr.va_mode & VSUID) 103 uid = vattr.va_uid; 104 if (vattr.va_mode & VSGID) 105 gid = vattr.va_gid; 106 } 107 108 again: 109 if (u.u_error = VOP_ACCESS(vp, VEXEC, u.u_cred)) 110 goto bad; 111 if ((u.u_procp->p_flag & STRC) && 112 (u.u_error = VOP_ACCESS(vp, VREAD, u.u_cred))) 113 goto bad; 114 if (vp->v_type != VREG || 115 (vattr.va_mode & (VEXEC|(VEXEC>>3)|(VEXEC>>6))) == 0) { 116 u.u_error = EACCES; 117 goto bad; 118 } 119 120 /* 121 * Read in first few bytes of file for segment sizes, magic number: 122 * OMAGIC = plain executable 123 * NMAGIC = RO text 124 * ZMAGIC = demand paged RO text 125 * Also an ASCII line beginning with #! is 126 * the file name of a ``shell'' and arguments may be prepended 127 * to the argument list if given here. 128 * 129 * SHELL NAMES ARE LIMITED IN LENGTH. 130 * 131 * ONLY ONE ARGUMENT MAY BE PASSED TO THE SHELL FROM 132 * THE ASCII LINE. 133 */ 134 exdata.ex_shell[0] = '\0'; /* for zero length files */ 135 u.u_error = vn_rdwr(UIO_READ, vp, (caddr_t)&exdata, sizeof (exdata), 136 (off_t)0, UIO_SYSSPACE, (IO_UNIT|IO_NODELOCKED), u.u_cred, &resid); 137 if (u.u_error) 138 goto bad; 139 #ifndef lint 140 if (resid > sizeof(exdata) - sizeof(exdata.ex_exec) && 141 exdata.ex_shell[0] != '#') { 142 u.u_error = ENOEXEC; 143 goto bad; 144 } 145 #endif 146 switch ((int)exdata.ex_exec.a_magic) { 147 148 case OMAGIC: 149 exdata.ex_exec.a_data += exdata.ex_exec.a_text; 150 exdata.ex_exec.a_text = 0; 151 break; 152 153 case ZMAGIC: 154 case NMAGIC: 155 if (exdata.ex_exec.a_text == 0) { 156 u.u_error = ENOEXEC; 157 goto bad; 158 } 159 break; 160 161 default: 162 if (exdata.ex_shell[0] != '#' || 163 exdata.ex_shell[1] != '!' || 164 indir) { 165 u.u_error = ENOEXEC; 166 goto bad; 167 } 168 for (cp = &exdata.ex_shell[2];; ++cp) { 169 if (cp >= &exdata.ex_shell[MAXINTERP]) { 170 u.u_error = ENOEXEC; 171 goto bad; 172 } 173 if (*cp == '\n') { 174 *cp = '\0'; 175 break; 176 } 177 if (*cp == '\t') 178 *cp = ' '; 179 } 180 cp = &exdata.ex_shell[2]; 181 while (*cp == ' ') 182 cp++; 183 ndp->ni_dirp = cp; 184 while (*cp && *cp != ' ') 185 cp++; 186 cfarg[0] = '\0'; 187 if (*cp) { 188 *cp++ = '\0'; 189 while (*cp == ' ') 190 cp++; 191 if (*cp) 192 bcopy((caddr_t)cp, (caddr_t)cfarg, MAXINTERP); 193 } 194 indir = 1; 195 vput(vp); 196 ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 197 ndp->ni_segflg = UIO_SYSSPACE; 198 if (u.u_error = namei(ndp)) 199 return; 200 vp = ndp->ni_vp; 201 if (u.u_error = VOP_GETATTR(vp, &vattr, u.u_cred)) 202 goto bad; 203 bcopy((caddr_t)ndp->ni_dent.d_name, (caddr_t)cfname, 204 MAXCOMLEN); 205 cfname[MAXCOMLEN] = '\0'; 206 uid = u.u_cred->cr_uid; /* shell scripts can't be setuid */ 207 gid = u.u_cred->cr_gid; 208 goto again; 209 } 210 /* 211 * If the vnode has been modified since we last used it, 212 * then throw away all its pages and its text table entry. 213 */ 214 if (vp->v_text && vp->v_text->x_mtime != vattr.va_mtime.tv_sec) { 215 /* 216 * Try once to release, if it is still busy 217 * take more drastic action. 218 */ 219 xrele(vp); 220 if (vp->v_flag & VTEXT) { 221 vput(vp); 222 vgone(vp); 223 goto start; 224 } 225 } 226 227 /* 228 * Collect arguments on "file" in swap space. 229 */ 230 na = 0; 231 ne = 0; 232 nc = 0; 233 cc = 0; 234 uap = (struct execa *)u.u_ap; 235 bno = rmalloc(argmap, (long)ctod(clrnd((int)btoc(NCARGS)))); 236 if (bno == 0) { 237 swkill(u.u_procp, "exec: no swap space"); 238 goto bad; 239 } 240 if (bno % CLSIZE) 241 panic("execa rmalloc"); 242 /* 243 * Copy arguments into file in argdev area. 244 */ 245 if (uap->argp) for (;;) { 246 ap = NULL; 247 sharg = NULL; 248 if (indir && na == 0) { 249 sharg = cfname; 250 ap = (int)sharg; 251 uap->argp++; /* ignore argv[0] */ 252 } else if (indir && (na == 1 && cfarg[0])) { 253 sharg = cfarg; 254 ap = (int)sharg; 255 } else if (indir && (na == 1 || na == 2 && cfarg[0])) 256 ap = (int)uap->fname; 257 else if (uap->argp) { 258 ap = fuword((caddr_t)uap->argp); 259 uap->argp++; 260 } 261 if (ap == NULL && uap->envp) { 262 uap->argp = NULL; 263 if ((ap = fuword((caddr_t)uap->envp)) != NULL) 264 uap->envp++, ne++; 265 } 266 if (ap == NULL) 267 break; 268 na++; 269 if (ap == -1) { 270 u.u_error = EFAULT; 271 break; 272 } 273 do { 274 if (cc <= 0) { 275 /* 276 * We depend on NCARGS being a multiple of 277 * CLBYTES. This way we need only check 278 * overflow before each buffer allocation. 279 */ 280 if (nc >= NCARGS-1) { 281 error = E2BIG; 282 break; 283 } 284 if (bp) 285 bdwrite(bp); 286 cc = CLBYTES; 287 bp = getblk(argdev_vp, bno + ctod(nc/NBPG), cc); 288 cp = bp->b_un.b_addr; 289 } 290 if (sharg) { 291 error = copystr(sharg, cp, (unsigned)cc, &len); 292 sharg += len; 293 } else { 294 error = copyinstr((caddr_t)ap, cp, (unsigned)cc, 295 &len); 296 ap += len; 297 } 298 cp += len; 299 nc += len; 300 cc -= len; 301 } while (error == ENOENT); 302 if (error) { 303 u.u_error = error; 304 if (bp) 305 brelse(bp); 306 bp = 0; 307 goto badarg; 308 } 309 } 310 if (bp) 311 bdwrite(bp); 312 bp = 0; 313 nc = (nc + NBPW-1) & ~(NBPW-1); 314 getxfile(vp, &exdata.ex_exec, nc + (na+4)*NBPW, uid, gid, u.u_cred); 315 if (u.u_error) { 316 badarg: 317 for (cc = 0; cc < nc; cc += CLBYTES) { 318 (void) baddr(argdev_vp, bno + ctod(cc/NBPG), 319 CLBYTES, NOCRED, &tbp); 320 bp = tbp; 321 if (bp) { 322 bp->b_flags |= B_INVAL; /* throw away */ 323 brelse(bp); 324 bp = 0; 325 } 326 } 327 goto bad; 328 } 329 vp->v_text->x_mtime = vattr.va_mtime.tv_sec; 330 vput(vp); 331 vp = NULL; 332 333 /* 334 * Copy back arglist. 335 */ 336 ucp = USRSTACK - nc - NBPW; 337 ap = ucp - na*NBPW - 3*NBPW; 338 u.u_ar0[SP] = ap; 339 (void) suword((caddr_t)ap, na-ne); 340 nc = 0; 341 cc = 0; 342 for (;;) { 343 ap += NBPW; 344 if (na == ne) { 345 (void) suword((caddr_t)ap, 0); 346 ap += NBPW; 347 } 348 if (--na < 0) 349 break; 350 (void) suword((caddr_t)ap, ucp); 351 do { 352 if (cc <= 0) { 353 if (bp) 354 brelse(bp); 355 cc = CLBYTES; 356 error = bread(argdev_vp, 357 (daddr_t)(bno + ctod(nc / NBPG)), cc, 358 NOCRED, &tbp); 359 bp = tbp; 360 bp->b_flags |= B_INVAL; /* throw away */ 361 cp = bp->b_un.b_addr; 362 } 363 error = copyoutstr(cp, (caddr_t)ucp, (unsigned)cc, 364 &len); 365 ucp += len; 366 cp += len; 367 nc += len; 368 cc -= len; 369 } while (error == ENOENT); 370 if (error == EFAULT) 371 panic("exec: EFAULT"); 372 } 373 (void) suword((caddr_t)ap, 0); 374 375 execsigs(u.u_procp); 376 377 for (nc = u.u_lastfile; nc >= 0; --nc) { 378 if (u.u_pofile[nc] & UF_EXCLOSE) { 379 (void) closef(u.u_ofile[nc]); 380 u.u_ofile[nc] = NULL; 381 u.u_pofile[nc] = 0; 382 } 383 u.u_pofile[nc] &= ~UF_MAPPED; 384 } 385 while (u.u_lastfile >= 0 && u.u_ofile[u.u_lastfile] == NULL) 386 u.u_lastfile--; 387 setregs(exdata.ex_exec.a_entry); 388 /* 389 * Remember file name for accounting. 390 */ 391 u.u_acflag &= ~AFORK; 392 if (indir) 393 bcopy((caddr_t)cfname, (caddr_t)u.u_procp->p_comm, MAXCOMLEN); 394 else { 395 if (ndp->ni_dent.d_namlen > MAXCOMLEN) 396 ndp->ni_dent.d_namlen = MAXCOMLEN; 397 bcopy((caddr_t)ndp->ni_dent.d_name, (caddr_t)u.u_procp->p_comm, 398 (unsigned)(ndp->ni_dent.d_namlen + 1)); 399 } 400 bad: 401 if (bp) 402 brelse(bp); 403 if (bno) 404 rmfree(argmap, (long)ctod(clrnd((int) btoc(NCARGS))), bno); 405 if (vp) 406 vput(vp); 407 } 408 409 /* 410 * Read in and set up memory for executed file. 411 */ 412 getxfile(vp, ep, nargc, uid, gid, cred) 413 register struct vnode *vp; 414 register struct exec *ep; 415 int nargc, uid, gid; 416 struct ucred *cred; 417 { 418 register struct proc *p = u.u_procp; 419 size_t ts, ds, ids, uds, ss; 420 int pagi; 421 422 if (ep->a_magic == ZMAGIC) 423 pagi = SPAGV; 424 else 425 pagi = 0; 426 if (vp->v_text && (vp->v_text->x_flag & XTRC)) { 427 u.u_error = ETXTBSY; 428 goto bad; 429 } 430 if (ep->a_text != 0 && (vp->v_flag & VTEXT) == 0 && 431 vp->v_usecount != 1) { 432 register struct file *fp; 433 434 for (fp = file; fp < fileNFILE; fp++) { 435 if (fp->f_type == DTYPE_VNODE && 436 fp->f_count > 0 && 437 (struct vnode *)fp->f_data == vp && 438 (fp->f_flag & FWRITE)) { 439 u.u_error = ETXTBSY; 440 goto bad; 441 } 442 } 443 } 444 445 /* 446 * Compute text and data sizes and make sure not too large. 447 * NB - Check data and bss separately as they may overflow 448 * when summed together. 449 */ 450 ts = clrnd(btoc(ep->a_text)); 451 ids = clrnd(btoc(ep->a_data)); 452 uds = clrnd(btoc(ep->a_bss)); 453 ds = clrnd(btoc(ep->a_data + ep->a_bss)); 454 ss = clrnd(SSIZE + btoc(nargc)); 455 if (chksize((unsigned)ts, (unsigned)ids, (unsigned)uds, (unsigned)ss)) 456 goto bad; 457 458 /* 459 * Make sure enough space to start process. 460 */ 461 u.u_cdmap = zdmap; 462 u.u_csmap = zdmap; 463 if (swpexpand(ds, ss, &u.u_cdmap, &u.u_csmap) == NULL) 464 goto bad; 465 466 /* 467 * At this point, we are committed to the new image! 468 * Release virtual memory resources of old process, and 469 * initialize the virtual memory of the new process. 470 * If we resulted from vfork(), instead wakeup our 471 * parent who will set SVFDONE when he has taken back 472 * our resources. 473 */ 474 if ((p->p_flag & SVFORK) == 0) 475 vrelvm(); 476 else { 477 p->p_flag &= ~SVFORK; 478 p->p_flag |= SKEEP; 479 wakeup((caddr_t)p); 480 while ((p->p_flag & SVFDONE) == 0) 481 sleep((caddr_t)p, PZERO - 1); 482 p->p_flag &= ~(SVFDONE|SKEEP); 483 } 484 p->p_flag &= ~(SPAGV|SSEQL|SUANOM); 485 p->p_flag |= pagi | SEXEC; 486 u.u_dmap = u.u_cdmap; 487 u.u_smap = u.u_csmap; 488 vgetvm(ts, ds, ss); 489 490 if (pagi == 0) 491 u.u_error = vn_rdwr(UIO_READ, vp, 492 (char *)ctob(dptov(u.u_procp, 0)), 493 (int)ep->a_data, 494 (off_t)(sizeof (struct exec) + ep->a_text), 495 UIO_USERSPACE, (IO_UNIT|IO_NODELOCKED), cred, (int *)0); 496 xalloc(vp, ep, pagi, cred); 497 #if defined(tahoe) 498 /* 499 * Define new keys. 500 */ 501 if (p->p_textp == 0) { /* use existing code key if shared */ 502 ckeyrelease(p->p_ckey); 503 p->p_ckey = getcodekey(); 504 } 505 mtpr(CCK, p->p_ckey); 506 dkeyrelease(p->p_dkey); 507 p->p_dkey = getdatakey(); 508 mtpr(DCK, p->p_dkey); 509 #endif 510 if (pagi && p->p_textp) 511 vinifod(u.u_procp, (struct fpte *)dptopte(p, 0), 512 PG_FTEXT, p->p_textp->x_vptr, 513 (long)(1 + ts/CLSIZE), (size_t)btoc(ep->a_data)); 514 515 #if defined(vax) || defined(tahoe) 516 /* THIS SHOULD BE DONE AT A LOWER LEVEL, IF AT ALL */ 517 mtpr(TBIA, 0); 518 #endif 519 520 /* 521 * set SUID/SGID protections, if no tracing 522 */ 523 if ((p->p_flag&STRC)==0) { 524 if (uid != u.u_cred->cr_uid || gid != u.u_cred->cr_gid) 525 u.u_cred = crcopy(u.u_cred); 526 u.u_cred->cr_uid = uid; 527 u.u_cred->cr_gid = gid; 528 p->p_uid = uid; 529 } else 530 psignal(p, SIGTRAP); 531 p->p_svuid = p->p_uid; 532 p->p_svgid = u.u_cred->cr_gid; 533 u.u_tsize = ts; 534 u.u_dsize = ds; 535 u.u_ssize = ss; 536 u.u_prof.pr_scale = 0; 537 #if defined(tahoe) 538 u.u_pcb.pcb_savacc.faddr = (float *)NULL; 539 #endif 540 bad: 541 return; 542 } 543