|
|
1.1.1.2 ! root 1: /* ! 2: * Copyright (C) 1993 Christopher G. Demetriou ! 3: * Copyright (C) 1992 Wolfgang Solfrank. ! 4: * Copyright (C) 1992 TooLs GmbH. 1.1 root 5: * All rights reserved. 6: * 7: * Redistribution and use in source and binary forms, with or without 8: * modification, are permitted provided that the following conditions 9: * are met: 10: * 1. Redistributions of source code must retain the above copyright 11: * notice, this list of conditions and the following disclaimer. 12: * 2. Redistributions in binary form must reproduce the above copyright 13: * notice, this list of conditions and the following disclaimer in the 14: * documentation and/or other materials provided with the distribution. 15: * 3. All advertising materials mentioning features or use of this software 16: * must display the following acknowledgement: 1.1.1.2 ! root 17: * This product includes software developed by TooLs GmbH. ! 18: * 4. The name of TooLs GmbH may not be used to endorse or promote products ! 19: * derived from this software without specific prior written permission. 1.1 root 20: * 1.1.1.2 ! root 21: * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR ! 22: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ! 23: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ! 24: * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ! 25: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, ! 26: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; ! 27: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ! 28: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR ! 29: * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ! 30: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.1 root 31: * 1.1.1.2 ! root 32: * kern_exec.c,v 1.20 1993/07/13 22:13:19 cgd Exp 1.1 root 33: */ 34: 1.1.1.2 ! root 35: #undef SETUIDSCRIPTS /* Define this for setuid scripts */ ! 36: #ifdef SETUIDSCRIPTS ! 37: #define FDSCRIPTS /* setuid scripts probably also want this */ ! 38: #endif ! 39: 1.1 root 40: #include "param.h" 41: #include "systm.h" 42: #include "filedesc.h" 43: #include "kernel.h" 44: #include "proc.h" 45: #include "mount.h" 46: #include "malloc.h" 47: #include "namei.h" 48: #include "vnode.h" 1.1.1.2 ! root 49: /* #include "seg.h" ??? -- cgd */ 1.1 root 50: #include "file.h" 51: #include "acct.h" 52: #include "exec.h" 53: #include "ktrace.h" 54: #include "resourcevar.h" 1.1.1.2 ! root 55: #include "wait.h" 1.1 root 56: 57: #include "machine/cpu.h" 58: #include "machine/reg.h" 1.1.1.2 ! root 59: #include "machine/exec.h" 1.1 root 60: 61: #include "mman.h" 62: #include "vm/vm.h" 63: #include "vm/vm_param.h" 64: #include "vm/vm_map.h" 65: #include "vm/vm_kern.h" 66: #include "vm/vm_pager.h" 67: 68: #include "signalvar.h" 69: #include "kinfo_proc.h" 70: 71: #ifdef COPY_SIGCODE 72: extern char sigcode[], esigcode[]; 73: #define szsigcode (esigcode - sigcode) 74: #else 75: #define szsigcode 0 76: #endif 77: 1.1.1.2 ! root 78: #ifdef FDSCRIPTS ! 79: /* The returned attributes are only good for set[ug]id scripts/programs */ ! 80: static checkaout(p,ndp,vpp,ap,hdr,fdp,argp,argc,epp) ! 81: struct proc *p; ! 82: struct nameidata *ndp; ! 83: struct vnode **vpp; ! 84: struct vattr *ap; ! 85: struct exec *hdr; ! 86: int *fdp; ! 87: char **argp; ! 88: int *argc; ! 89: struct exec_package *epp; ! 90: #else ! 91: static checkaout(p,ndp,vpp,ap,hdr,argp,argc,epp) ! 92: struct proc *p; ! 93: struct nameidata *ndp; ! 94: struct vnode **vpp; ! 95: struct vattr *ap; ! 96: struct exec *hdr; ! 97: char **argp; ! 98: int *argc; ! 99: struct exec_package *epp; ! 100: #endif ! 101: { ! 102: int error; ! 103: struct vnode *vp; ! 104: char *cp, *ep, *name; ! 105: int resid; ! 106: ! 107: /* XXX - THIS ENTIRE FUCTION SHOULD BE REWRITTEN - cgd */ ! 108: ! 109: /* first get the vnode */ ! 110: if (error = namei(ndp,p)) ! 111: return error; ! 112: *vpp = vp = ndp->ni_vp; ! 113: ! 114: /* check for regular file */ ! 115: if (vp->v_type != VREG) { ! 116: error = EACCES; ! 117: goto bad1; ! 118: } ! 119: ! 120: /* get attributes */ ! 121: if (error = VOP_GETATTR(vp,ap,p->p_ucred,p)) ! 122: goto bad1; ! 123: ! 124: /* Check mount point */ ! 125: if (vp->v_mount->mnt_flag&MNT_NOEXEC) { ! 126: error = ENOEXEC; ! 127: goto bad1; ! 128: } ! 129: if ((vp->v_mount->mnt_flag&MNT_NOSUID) || (p->p_flag&STRC)) ! 130: ap->va_mode &= ~(VSUID|VSGID); ! 131: ! 132: /* for root we have to check for any exec bit on */ ! 133: /* doing it always doesn't hurt) */ ! 134: if (!(ap->va_mode&0111)) { ! 135: error = EACCES; ! 136: goto bad1; ! 137: } ! 138: ! 139: /* check access */ ! 140: if ((error = VOP_ACCESS(vp,VEXEC,p->p_ucred,p)) ! 141: || (error = VOP_OPEN(vp,FREAD,p->p_ucred,p))) ! 142: goto bad1; ! 143: ! 144: /* now we have the file, get the exec header */ ! 145: if (error = vn_rdwr(UIO_READ,vp,(caddr_t)hdr,sizeof(*hdr),0, ! 146: UIO_SYSSPACE,IO_NODELOCKED,p->p_ucred,&resid,p)) ! 147: goto bad2; ! 148: ! 149: if (!resid && !(hdr->a_text&PGOFSET) && !(hdr->a_data&PGOFSET)) { ! 150: /* sanity check: if it could get by the above, and still be a ! 151: * shell script. if so, don't try the vmcmd tricks. ! 152: */ ! 153: cp = (char *)hdr; ! 154: if (!(*cp == '#' && cp[1] == '!')) { ! 155: /* set up the vmcmds for creation of the process address space */ ! 156: epp->ep_execp = hdr; ! 157: epp->ep_vp = vp; ! 158: epp->ep_vap = ap; ! 159: if (error = exec_makecmds(p, epp)) ! 160: goto bad2; ! 161: ! 162: if (epp->ep_entry > VM_MAXUSER_ADDRESS) { ! 163: error = ENOEXEC; ! 164: goto bad2; ! 165: } ! 166: ! 167: /* check limits */ ! 168: if ((epp->ep_tsize > MAXTSIZ) || ! 169: (epp->ep_dsize > p->p_rlimit[RLIMIT_DATA].rlim_cur) || ! 170: (epp->ep_ssize > p->p_rlimit[RLIMIT_STACK].rlim_cur)) { ! 171: error = ENOMEM; ! 172: goto bad2; ! 173: } ! 174: ! 175: return 0; ! 176: } ! 177: } ! 178: ! 179: /* scripts only if it's the first round */ ! 180: cp = (char *)hdr; ! 181: ep = (char *)(hdr + 1) - resid; ! 182: if (ndp->ni_segflg == UIO_USERSPACE && *cp == '#' && cp[1] == '!') { ! 183: #ifdef SETUIDSCRIPTS ! 184: struct vattr attr; ! 185: #define ATTRP &attr ! 186: #else ! 187: #define ATTRP ap ! 188: #endif ! 189: #ifdef FDSCRIPTS ! 190: struct file *fp; ! 191: int fd; ! 192: extern struct fileops vnops; ! 193: char fdscripts = 0; ! 194: ! 195: /* we want to give the interpreter /dev/fd/xxx if the script is: ! 196: set[ug]id or ! 197: execute only */ ! 198: ! 199: if (VOP_ACCESS(vp,VREAD,p->p_ucred,p) == EACCES ! 200: || (ap->va_mode&(VSUID|VSGID))) ! 201: fdscripts = 1; ! 202: ! 203: if (fdscripts) { ! 204: if (error = falloc(p,&fp,&fd)) ! 205: goto bad2; ! 206: ! 207: VOP_UNLOCK(vp); ! 208: fp->f_type = DTYPE_VNODE; ! 209: fp->f_ops = &vnops; ! 210: fp->f_data = (caddr_t)vp; ! 211: fp->f_flag = FREAD; ! 212: } else { ! 213: #endif ! 214: VOP_UNLOCK(vp); ! 215: vn_close(vp,FREAD,p->p_ucred,p); ! 216: #ifdef FDSCRIPTS ! 217: } ! 218: #endif ! 219: ! 220: for (cp += 2; cp < ep; cp++) { ! 221: switch (*cp) { ! 222: case ' ': ! 223: case '\t': ! 224: continue; ! 225: } ! 226: break; ! 227: } ! 228: if (cp >= ep) ! 229: error = EACCES; ! 230: ! 231: ++*argc; ! 232: for (name = cp; cp < ep; cp++) { ! 233: switch (*cp) { ! 234: default: ! 235: *(*argp)++ = *cp; ! 236: continue; ! 237: case '\0': ! 238: case '\n': ! 239: ep = cp; ! 240: case ' ': ! 241: case '\t': ! 242: *(*argp)++ = *cp++ = 0; ! 243: goto out1; ! 244: } ! 245: break; ! 246: } ! 247: out1: ! 248: for (; cp < ep; cp++) { ! 249: switch (*cp) { ! 250: case ' ': ! 251: case '\t': ! 252: continue; ! 253: case '\0': ! 254: case '\n': ! 255: ep = cp; ! 256: } ! 257: break; ! 258: } ! 259: if (cp < ep) { ! 260: ++*argc; ! 261: for (; cp < ep; cp++) { ! 262: switch (*cp) { ! 263: default: ! 264: *(*argp)++ = *cp; ! 265: continue; ! 266: case '\0': ! 267: case '\n': ! 268: *(*argp)++ = 0; ! 269: goto out2; ! 270: } ! 271: break; ! 272: } ! 273: } ! 274: out2: ! 275: ! 276: #ifdef FDSCRIPTS ! 277: if (fdscripts) { ! 278: sprintf(*argp,"/dev/fd/%d",fd); ! 279: *fdp = fd; ! 280: } else ! 281: #endif ! 282: strcpy(*argp,ndp->ni_pnbuf); ! 283: while (*(*argp)++); ! 284: ++*argc; ! 285: ! 286: ndp->ni_dirp = name; ! 287: ndp->ni_segflg = UIO_SYSSPACE; ! 288: #ifdef FDSCRIPTS ! 289: if (!error && !(error = checkaout(p,ndp,vpp,ATTRP,hdr,&fd,argp, ! 290: argc,epp))) { ! 291: #else ! 292: if (!error && !(error = checkaout(p,ndp,vpp,ATTRP,hdr,argp, ! 293: argc,epp))) { ! 294: #endif ! 295: #ifdef SETUIDSCRIPTS ! 296: if (!(ap->va_mode&VSUID)) ! 297: ap->va_uid = attr.va_uid; ! 298: if (!(ap->va_mode&VSGID)) ! 299: ap->va_gid = attr.va_gid; ! 300: ap->va_mode |= attr.va_mode&(VSUID|VSGID); ! 301: #endif ! 302: return 0; ! 303: } ! 304: ! 305: #ifdef FDSCRIPTS ! 306: if (fdscripts) { ! 307: closefd(p,fd); ! 308: goto bad2; ! 309: } ! 310: #endif ! 311: return error; ! 312: } ! 313: ! 314: error = ENOEXEC; ! 315: ! 316: bad2: ! 317: VOP_UNLOCK(vp); ! 318: vn_close(vp,FREAD,p->p_ucred,p); ! 319: FREE(ndp->ni_pnbuf,M_NAMEI); ! 320: return error; ! 321: bad1: ! 322: FREE(ndp->ni_pnbuf,M_NAMEI); ! 323: vput(vp); ! 324: return error; ! 325: } ! 326: ! 327: #ifdef FDSCRIPTS ! 328: static closefd(p,fd) ! 329: struct proc *p; ! 330: { ! 331: /* have to close file again */ ! 332: if (p->p_fd->fd_lastfile == fd) ! 333: p->p_fd->fd_lastfile--; ! 334: if (p->p_fd->fd_freefile > fd) ! 335: p->p_fd->fd_freefile = fd; ! 336: closef(p->p_fd->fd_ofiles[fd],p); ! 337: p->p_fd->fd_ofiles[fd] = 0; ! 338: } ! 339: #endif ! 340: ! 341: #ifdef EXEC_DEBUG ! 342: exec_print_vmspaceinfo(struct proc *p) ! 343: { ! 344: printf("process vmspace:\n"); ! 345: printf("\tvm_taddr: 0x%x\n", p->p_vmspace->vm_taddr); ! 346: printf("\tvm_tsize: 0x%x\n", p->p_vmspace->vm_tsize); ! 347: printf("\tvm_daddr: 0x%x\n", p->p_vmspace->vm_daddr); ! 348: printf("\tvm_dsize: 0x%x\n", p->p_vmspace->vm_dsize); ! 349: printf("\tvm_ssize: 0x%x\n", p->p_vmspace->vm_ssize); ! 350: printf("\tvm_maxsaddr: 0x%x\n", p->p_vmspace->vm_maxsaddr); ! 351: ! 352: /* handy place for debugger breakpoint, but name is too long... */ ! 353: asm(".globl _exec_print_vmspaceinfo_leave ; _exec_print_vmspaceinfo_leave:"); ! 354: } ! 355: #endif ! 356: ! 357: #ifdef EXEC_DEBUG ! 358: exec_print_argstring(char *str, int len, char **ap, char *a) ! 359: { ! 360: printf("(0x%x)-> \t0x%x \t: %s (%d)\n", ap, a, str, len); ! 361: } ! 362: #endif ! 363: 1.1 root 364: /* 365: * exec system call 366: */ 1.1.1.2 ! root 367: ! 368: struct execve_args { ! 369: char *fname; ! 370: char **argp; ! 371: char **envp; ! 372: }; ! 373: 1.1 root 374: /* ARGSUSED */ 375: execve(p, uap, retval) 376: register struct proc *p; 1.1.1.2 ! root 377: register struct execve_args *uap; 1.1 root 378: int *retval; 379: { 380: 381: /* 382: * Body deleted. 383: */ 1.1.1.2 ! root 384: /* ! 385: * And reimplemented by ws. ! 386: * I think this should be vastly more machine dependent ! 387: * (e.g. stack up/down, startup stack format etc.) ! 388: */ ! 389: int error; ! 390: struct vnode *vp; ! 391: struct nameidata nid; ! 392: struct ucred *cred = p->p_ucred; ! 393: char *argp; ! 394: struct exec hdr; ! 395: char **cpp, *dp, *sp, *np; ! 396: int argc, envc, len; ! 397: char *stack; ! 398: struct vattr attr; ! 399: struct ps_strings arginfo; ! 400: struct exec_package pack; ! 401: #ifdef FDSCRIPTS ! 402: int fd; ! 403: #endif ! 404: ! 405: /* get space for argv & environment */ ! 406: /* was: if(!(dp = argp = (char *)kmem_alloc_wait(exec_map,ARG_MAX))) - cgd */ ! 407: MALLOC(argp, char *, ARG_MAX, M_EXEC, M_WAITOK); ! 408: if(!argp) ! 409: panic("exec: can't allocate ARG_MAX"); ! 410: dp = argp; ! 411: argc = 0; ! 412: #ifdef FDSCRIPTS ! 413: fd = -1; ! 414: #endif ! 415: ! 416: nid.ni_dirp = uap->fname; ! 417: nid.ni_segflg = UIO_USERSPACE; ! 418: nid.ni_nameiop = LOOKUP|FOLLOW|LOCKLEAF|SAVENAME; ! 419: /* checkaout possibly copies arguments for scripts */ ! 420: #ifdef FDSCRIPTS ! 421: if (error = checkaout(p,&nid,&vp,&attr,&hdr,&fd,&dp,&argc,&pack)) ! 422: #else ! 423: if (error = checkaout(p,&nid,&vp,&attr,&hdr,&dp,&argc,&pack)) ! 424: #endif ! 425: goto freeargs; ! 426: ! 427: /* Now get argv & environment */ ! 428: if (!(cpp = uap->argp)) { ! 429: error = EINVAL; ! 430: goto bad; ! 431: } ! 432: ! 433: if (argc > 0) { ! 434: /* it is a script, so we have to skip the 0th arg */ ! 435: cpp++; ! 436: /* check access to arg here? */ ! 437: } ! 438: ! 439: #ifdef EXEC_DEBUG ! 440: printf("start of args = 0x%x\n", dp); ! 441: #endif ! 442: while (1) { ! 443: len = argp + ARG_MAX - dp; ! 444: if (error = copyin(cpp,&sp,sizeof(sp))) ! 445: goto bad; ! 446: if (!sp) ! 447: break; ! 448: if (error = copyinstr(sp,dp,len,(u_int *)&len)) { ! 449: if (error == ENAMETOOLONG) ! 450: error = E2BIG; ! 451: goto bad; ! 452: } ! 453: dp += len; ! 454: cpp++; ! 455: argc++; ! 456: } ! 457: #ifdef EXEC_DEBUG ! 458: printf("end of args = 0x%x\n", dp); ! 459: #endif ! 460: ! 461: envc = 0; ! 462: if (cpp = uap->envp) { /* environment need not be there */ ! 463: while (1) { ! 464: len = argp + ARG_MAX - dp; ! 465: if (error = copyin(cpp,&sp,sizeof(sp))) ! 466: goto bad; ! 467: if (!sp) ! 468: break; ! 469: if (error = copyinstr(sp,dp,len,(u_int *)&len)) { ! 470: if (error == ENAMETOOLONG) ! 471: error = E2BIG; ! 472: goto bad; ! 473: } ! 474: dp += len; ! 475: cpp++; ! 476: envc++; ! 477: } ! 478: dp = (char *)ALIGN(dp); ! 479: } ! 480: #ifdef EXEC_DEBUG ! 481: printf("end of env = 0x%x\n", dp); ! 482: printf("argc/envc = %d/%d\n", argc, envc); ! 483: #endif ! 484: ! 485: /* Now check if args & environ fit into new stack */ ! 486: len = ((argc + envc + 2) * sizeof(char *) + sizeof(int) + ! 487: dp + sizeof(struct ps_strings) + szsigcode) - argp; ! 488: len = roundup(len, sizeof(char *)); ! 489: if (len > p->p_rlimit[RLIMIT_STACK].rlim_cur) { ! 490: error = ENOMEM; ! 491: goto bad; ! 492: } ! 493: ! 494: /* Unmap old program */ ! 495: vm_deallocate(&p->p_vmspace->vm_map,0,USRSTACK); ! 496: ! 497: /* Now map address space */ ! 498: p->p_vmspace->vm_taddr = (char *) pack.ep_taddr; ! 499: p->p_vmspace->vm_tsize = btoc(pack.ep_tsize); ! 500: p->p_vmspace->vm_daddr = (char *) pack.ep_daddr; ! 501: p->p_vmspace->vm_dsize = btoc(pack.ep_dsize); ! 502: p->p_vmspace->vm_ssize = btoc(pack.ep_ssize); ! 503: p->p_vmspace->vm_maxsaddr = (char *) pack.ep_maxsaddr; ! 504: if (error = exec_runcmds(p, &pack)) ! 505: goto exec_abort; ! 506: kill_vmcmd(&pack.ep_vcp); ! 507: ! 508: /* remember information about the process */ ! 509: arginfo.ps_nargvstr = argc; ! 510: arginfo.ps_nenvstr = envc; ! 511: ! 512: /* Now copy argc, args & environ to new stack */ ! 513: stack = (char *)(USRSTACK - len); ! 514: #ifdef EXEC_DEBUG ! 515: printf("stack wants to live at: 0x%x\n", stack); ! 516: #endif ! 517: cpp = (char **)stack; ! 518: ! 519: if (copyout(&argc,cpp++,sizeof(argc))) ! 520: goto exec_abort; ! 521: #ifdef EXEC_DEBUG ! 522: printf("0x%x \targ count: %d\n", (cpp - 1), argc); ! 523: #endif ! 524: dp = (char *)(cpp + argc + envc + 2); ! 525: ! 526: arginfo.ps_argvstr = dp; /* remember location of argv for later */ ! 527: for (sp = argp; --argc >= 0; sp += len, dp += len) { ! 528: len = strlen(sp) + 1; ! 529: if (copyout(&dp,cpp++,sizeof(dp)) ! 530: || copyoutstr(sp,dp,len,0)) ! 531: goto exec_abort; ! 532: #ifdef EXEC_DEBUG ! 533: exec_print_argstring(sp, len, (cpp - 1), dp); ! 534: #endif ! 535: } ! 536: np = 0; ! 537: if (copyout(&np,cpp++,sizeof(np))) ! 538: goto exec_abort; ! 539: ! 540: arginfo.ps_envstr = dp; /* remember location of env for later */ ! 541: for (; --envc >= 0; sp += len, dp += len) { ! 542: len = strlen(sp) + 1; ! 543: if (copyout(&dp,cpp++,sizeof(dp)) ! 544: || copyoutstr(sp,dp,len,0)) ! 545: goto exec_abort; ! 546: #ifdef EXEC_DEBUG ! 547: exec_print_argstring(sp, len, (cpp - 1), dp); ! 548: #endif ! 549: } ! 550: if (copyout(&np,cpp,sizeof(np))) ! 551: goto exec_abort; ! 552: ! 553: /* copy out the process's ps_strings structure */ ! 554: if (copyout(&arginfo, (char *)PS_STRINGS, sizeof(arginfo))) ! 555: goto exec_abort; ! 556: ! 557: #ifdef COPY_SIGCODE ! 558: /* copy out the process's signal trapoline code */ ! 559: if (copyout((char *)sigcode, ((char *)PS_STRINGS) - szsigcode, ! 560: szsigcode)) { ! 561: goto exec_abort; ! 562: } ! 563: #endif ! 564: ! 565: fdcloseexec(p); /* handle close on exec */ ! 566: execsigs(p); /* reset catched signals */ ! 567: ! 568: /* set command name & other accounting info */ ! 569: len = MIN(nid.ni_namelen,MAXCOMLEN); ! 570: bcopy(nid.ni_ptr,p->p_comm,len); ! 571: p->p_comm[len] = 0; ! 572: p->p_acflag &= ~AFORK; ! 573: ! 574: p->p_flag |= SEXEC; ! 575: if (p->p_flag&SPPWAIT) { ! 576: p->p_flag &= ~SPPWAIT; ! 577: wakeup((caddr_t)p->p_pptr); ! 578: } ! 579: ! 580: /* ! 581: *deal with set[ug]id ! 582: * MNT_NOEXEC and STRC have already been used to disable s[ug]id ! 583: */ ! 584: if (attr.va_mode&VSUID) { ! 585: p->p_ucred = crcopy(cred); ! 586: p->p_ucred->cr_uid = attr.va_uid; ! 587: } ! 588: p->p_cred->p_svuid = p->p_ucred->cr_uid; ! 589: if (attr.va_mode&VSGID) { ! 590: p->p_ucred = crcopy(p->p_ucred); ! 591: p->p_ucred->cr_gid = attr.va_gid; ! 592: } ! 593: p->p_cred->p_svgid = p->p_ucred->cr_gid; ! 594: /* what else? */ ! 595: ! 596: /* was: kmem_free_wakeup(exec_map,argp,ARG_MAX); - cgd */ ! 597: FREE(argp, M_EXEC); ! 598: ! 599: FREE(nid.ni_pnbuf,M_NAMEI); ! 600: VOP_CLOSE(vp,FREAD,cred,p); ! 601: vput(vp); ! 602: ! 603: /* setup new registers */ ! 604: setregs(p, hdr.a_entry, (u_long) stack, retval); ! 605: #ifdef EXEC_DEBUG ! 606: printf("exec returning normally\n"); ! 607: #endif ! 608: ! 609: if (p->p_flag & STRC) ! 610: psignal(p, SIGTRAP); ! 611: ! 612: return EJUSTRETURN; ! 613: ! 614: bad: ! 615: FREE(nid.ni_pnbuf,M_NAMEI); ! 616: VOP_CLOSE(vp,FREAD,cred,p); ! 617: vput(vp); ! 618: #ifdef FDSCRIPTS ! 619: if (fd) ! 620: closefd(p,fd); ! 621: #endif ! 622: freeargs: ! 623: /* was: kmem_free_wakeup(exec_map,argp,ARG_MAX); - cgd */ ! 624: FREE(argp, M_EXEC); ! 625: #ifdef EXEC_DEBUG ! 626: printf("exec returning on error\n"); ! 627: #endif ! 628: return error; ! 629: ! 630: exec_abort: ! 631: /* the old process doesn't exist anymore. exit gracefully. ! 632: * ! 633: * get rid of the (new) address space we have created, if any, ! 634: * get rid of our namei data and vnode, and exit noting failure ! 635: */ ! 636: #ifdef EXEC_DEBUG ! 637: printf("exec bailing out (abort)\n"); ! 638: #endif ! 639: vm_deallocate(&p->p_vmspace->vm_map,0,USRSTACK); ! 640: FREE(nid.ni_pnbuf,M_NAMEI); ! 641: VOP_CLOSE(vp,FREAD,cred,p); ! 642: vput(vp); ! 643: kexit(p, W_EXITCODE(0, SIGABRT)); ! 644: kexit(p, -1); ! 645: ! 646: /* NOTREACHED */ ! 647: return 0; ! 648: } ! 649: ! 650: int ! 651: exec_runcmds(p, epp) ! 652: struct proc *p; ! 653: struct exec_package *epp; ! 654: { ! 655: struct exec_vmcmd *cur = epp->ep_vcp; ! 656: int error; ! 657: ! 658: while (cur && !(error = (*cur->ev_proc)(p, cur))) ! 659: cur = cur->ev_next; ! 660: ! 661: return error; ! 662: } ! 663: ! 664: int ! 665: exec_makecmds(p, epp) ! 666: struct proc *p; ! 667: struct exec_package *epp; ! 668: { ! 669: u_long midmag, magic; ! 670: u_short mid; ! 671: int error; ! 672: ! 673: epp->ep_vcp = NULL; ! 674: ! 675: midmag = ntohl(epp->ep_execp->a_midmag); ! 676: mid = (midmag >> 16 ) & 0x3ff; ! 677: magic = midmag & 0xffff; ! 678: ! 679: #ifdef EXEC_DEBUG ! 680: printf("exec_makecmds: a_midmag is %x, magic=%x mid=%x\n", ! 681: epp->ep_execp->a_midmag, magic, mid); ! 682: #endif ! 683: ! 684: midmag = mid<<16 | magic; ! 685: ! 686: switch (midmag) { ! 687: case (MID_MACHINE << 16) | ZMAGIC: ! 688: error = exec_prep_zmagic(p, epp); ! 689: break; ! 690: case (MID_MACHINE << 16) | OMAGIC: ! 691: case (MID_MACHINE << 16) | NMAGIC: ! 692: default: ! 693: error = cpu_exec_makecmds(p, epp); ! 694: } ! 695: ! 696: if (error && epp->ep_vcp) ! 697: kill_vmcmd(&epp->ep_vcp); ! 698: ! 699: bad: ! 700: ! 701: #ifdef EXEC_DEBUG ! 702: printf("exec_makecmds returning with error = %d\n", error); ! 703: #endif ! 704: return error; ! 705: } ! 706: ! 707: void ! 708: kill_vmcmd(vcpp) ! 709: struct exec_vmcmd **vcpp; ! 710: { ! 711: struct exec_vmcmd *cur, *next; ! 712: ! 713: cur = *vcpp; ! 714: *vcpp = NULL; ! 715: while (cur != NULL) { ! 716: if (cur->ev_vp != NULL) ! 717: vrele(cur->ev_vp); ! 718: next = cur->ev_next; ! 719: FREE(cur, M_EXEC); ! 720: cur = next; ! 721: } ! 722: } ! 723: ! 724: inline struct exec_vmcmd * ! 725: new_vmcmd(proc, len, addr, vp, offset, prot) ! 726: int (*proc) __P((struct proc *p, struct exec_vmcmd *)); ! 727: unsigned long len; ! 728: unsigned long addr; ! 729: struct vnode *vp; ! 730: unsigned long offset; ! 731: unsigned long prot; ! 732: { ! 733: struct exec_vmcmd *tmpcmdp; ! 734: ! 735: MALLOC(tmpcmdp, struct exec_vmcmd *, sizeof(struct exec_vmcmd), ! 736: M_EXEC, M_WAITOK); ! 737: tmpcmdp->ev_next = NULL; ! 738: tmpcmdp->ev_proc = proc; ! 739: tmpcmdp->ev_len = len; ! 740: tmpcmdp->ev_addr = addr; ! 741: if ((tmpcmdp->ev_vp = vp) != NULL) ! 742: vref(vp); ! 743: tmpcmdp->ev_offset = offset; ! 744: tmpcmdp->ev_prot = prot; ! 745: ! 746: return tmpcmdp; ! 747: } ! 748: ! 749: int ! 750: exec_prep_zmagic(p, epp) ! 751: struct proc *p; ! 752: struct exec_package *epp; ! 753: { ! 754: struct exec *execp = epp->ep_execp; ! 755: struct exec_vmcmd *ccmdp; ! 756: ! 757: epp->ep_taddr = USRTEXT; ! 758: epp->ep_tsize = execp->a_text; ! 759: epp->ep_daddr = epp->ep_taddr + execp->a_text; ! 760: epp->ep_dsize = execp->a_data + execp->a_bss; ! 761: epp->ep_maxsaddr = USRSTACK - MAXSSIZ; ! 762: epp->ep_minsaddr = USRSTACK; ! 763: epp->ep_ssize = p->p_rlimit[RLIMIT_STACK].rlim_cur; ! 764: epp->ep_entry = execp->a_entry; ! 765: ! 766: /* check if vnode is in open for writing, because we want to demand-page ! 767: * out of it. if it is, don't do it, for various reasons ! 768: */ ! 769: if ((execp->a_text != 0 || execp->a_data != 0) && ! 770: (epp->ep_vp->v_flag & VTEXT) == 0 && epp->ep_vp->v_writecount != 0) { ! 771: #ifdef DIAGNOSTIC ! 772: if (epp->ep_vp->v_flag & VTEXT) ! 773: panic("exec: a VTEXT vnode has writecount != 0\n"); ! 774: #endif ! 775: epp->ep_vcp = NULL; ! 776: return ETXTBSY; ! 777: } ! 778: epp->ep_vp->v_flag |= VTEXT; ! 779: ! 780: /* set up command for text segment */ ! 781: epp->ep_vcp = new_vmcmd(vmcmd_map_pagedvn, ! 782: execp->a_text, ! 783: epp->ep_taddr, ! 784: epp->ep_vp, ! 785: 0, ! 786: VM_PROT_READ|VM_PROT_EXECUTE); ! 787: ccmdp = epp->ep_vcp; ! 788: ! 789: /* set up command for data segment */ ! 790: ccmdp->ev_next = new_vmcmd(vmcmd_map_pagedvn, ! 791: execp->a_data, ! 792: epp->ep_daddr, ! 793: epp->ep_vp, ! 794: execp->a_text, ! 795: VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE); ! 796: ccmdp = ccmdp->ev_next; ! 797: ! 798: /* set up command for bss segment */ ! 799: ccmdp->ev_next = new_vmcmd(vmcmd_map_zero, ! 800: execp->a_bss, ! 801: epp->ep_daddr + execp->a_data, ! 802: 0, ! 803: 0, ! 804: VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE); ! 805: ccmdp = ccmdp->ev_next; ! 806: ! 807: /* set up commands for stack. note that this takes *two*, one ! 808: * to map the part of the stack which we can access, and one ! 809: * to map the part which we can't. ! 810: * ! 811: * arguably, it could be made into one, but that would require ! 812: * the addition of another mapping proc, which is unnecessary ! 813: * ! 814: * note that in memory, thigns assumed to be: ! 815: * 0 ....... ep_maxsaddr <stack> ep_minsaddr ! 816: */ ! 817: ccmdp->ev_next = new_vmcmd(vmcmd_map_zero, ! 818: ((epp->ep_minsaddr - epp->ep_ssize) - ! 819: epp->ep_maxsaddr), ! 820: epp->ep_maxsaddr, ! 821: 0, ! 822: 0, ! 823: VM_PROT_NONE); ! 824: ccmdp = ccmdp->ev_next; ! 825: ccmdp->ev_next = new_vmcmd(vmcmd_map_zero, ! 826: epp->ep_ssize, ! 827: (epp->ep_minsaddr - epp->ep_ssize), ! 828: 0, ! 829: 0, ! 830: VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE); ! 831: ! 832: return 0; ! 833: } ! 834: ! 835: int vmcmd_map_pagedvn(p,cmd ) ! 836: struct proc *p; ! 837: struct exec_vmcmd *cmd; ! 838: { ! 839: /* note that if you're going to map part of an process as being paged from ! 840: * a vnode, that vnode had damn well better be marked as VTEXT. that's ! 841: * handled in the routine which sets up the vmcmd to call this routine. ! 842: */ ! 843: #ifdef EXEC_DEBUG ! 844: printf("vmcmd_map_pagedvn: mapping into addr %x for len %x (%x/%x)\n", ! 845: cmd->ev_addr, cmd->ev_len, cmd->ev_prot, VM_PROT_DEFAULT); ! 846: #endif ! 847: return vm_mmap(&p->p_vmspace->vm_map, ! 848: &cmd->ev_addr, ! 849: cmd->ev_len, ! 850: cmd->ev_prot, ! 851: VM_PROT_DEFAULT, ! 852: MAP_FIXED|MAP_FILE|MAP_COPY, ! 853: cmd->ev_vp, ! 854: cmd->ev_offset); ! 855: } ! 856: ! 857: int vmcmd_map_zero(p, cmd) ! 858: struct proc *p; ! 859: struct exec_vmcmd *cmd; ! 860: { ! 861: int error; ! 862: ! 863: #ifdef EXEC_DEBUG ! 864: printf("vmcmd_map_zero: mapping into addr %x for len %x (%x/%x)\n", ! 865: cmd->ev_addr, cmd->ev_len, cmd->ev_prot, VM_PROT_DEFAULT); ! 866: #endif ! 867: error = vm_allocate(&p->p_vmspace->vm_map, ! 868: &cmd->ev_addr, ! 869: cmd->ev_len, ! 870: 0); ! 871: if (error) ! 872: return error; ! 873: ! 874: return vm_protect(&p->p_vmspace->vm_map, ! 875: cmd->ev_addr, ! 876: cmd->ev_len, ! 877: FALSE, ! 878: cmd->ev_prot); 1.1 root 879: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.