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