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