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