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