Index: head/sys/kern/init_sysent.c =================================================================== --- head/sys/kern/init_sysent.c (revision 13522) +++ head/sys/kern/init_sysent.c (revision 13523) @@ -1,281 +1,280 @@ /* * System call switch table. * * DO NOT EDIT-- this file is automatically generated. * created from Id: syscalls.master,v 1.23 1996/01/08 04:13:25 peter Exp */ -#include "opt_sysvipc.h" #include #include #include #include #include #ifdef COMPAT_43 #define compat(n, name) n, (sy_call_t *)__CONCAT(o,name) #else #define compat(n, name) 0, (sy_call_t *)nosys #endif /* The casts are bogus but will do for now. */ struct sysent sysent[] = { { 0, (sy_call_t *)nosys }, /* 0 = syscall */ { 1, (sy_call_t *)exit }, /* 1 = exit */ { 0, (sy_call_t *)fork }, /* 2 = fork */ { 3, (sy_call_t *)read }, /* 3 = read */ { 3, (sy_call_t *)write }, /* 4 = write */ { 3, (sy_call_t *)open }, /* 5 = open */ { 1, (sy_call_t *)close }, /* 6 = close */ { 4, (sy_call_t *)wait4 }, /* 7 = wait4 */ { compat(2,creat) }, /* 8 = old creat */ { 2, (sy_call_t *)link }, /* 9 = link */ { 1, (sy_call_t *)unlink }, /* 10 = unlink */ { 0, (sy_call_t *)nosys }, /* 11 = obsolete execv */ { 1, (sy_call_t *)chdir }, /* 12 = chdir */ { 1, (sy_call_t *)fchdir }, /* 13 = fchdir */ { 3, (sy_call_t *)mknod }, /* 14 = mknod */ { 2, (sy_call_t *)chmod }, /* 15 = chmod */ { 3, (sy_call_t *)chown }, /* 16 = chown */ { 1, (sy_call_t *)obreak }, /* 17 = break */ { 3, (sy_call_t *)getfsstat }, /* 18 = getfsstat */ { compat(3,lseek) }, /* 19 = old lseek */ { 0, (sy_call_t *)getpid }, /* 20 = getpid */ { 4, (sy_call_t *)mount }, /* 21 = mount */ { 2, (sy_call_t *)unmount }, /* 22 = unmount */ { 1, (sy_call_t *)setuid }, /* 23 = setuid */ { 0, (sy_call_t *)getuid }, /* 24 = getuid */ { 0, (sy_call_t *)geteuid }, /* 25 = geteuid */ { 4, (sy_call_t *)ptrace }, /* 26 = ptrace */ { 3, (sy_call_t *)recvmsg }, /* 27 = recvmsg */ { 3, (sy_call_t *)sendmsg }, /* 28 = sendmsg */ { 6, (sy_call_t *)recvfrom }, /* 29 = recvfrom */ { 3, (sy_call_t *)accept }, /* 30 = accept */ { 3, (sy_call_t *)getpeername }, /* 31 = getpeername */ { 3, (sy_call_t *)getsockname }, /* 32 = getsockname */ { 2, (sy_call_t *)access }, /* 33 = access */ { 2, (sy_call_t *)chflags }, /* 34 = chflags */ { 2, (sy_call_t *)fchflags }, /* 35 = fchflags */ { 0, (sy_call_t *)sync }, /* 36 = sync */ { 2, (sy_call_t *)kill }, /* 37 = kill */ { compat(2,stat) }, /* 38 = old stat */ { 0, (sy_call_t *)getppid }, /* 39 = getppid */ { compat(2,lstat) }, /* 40 = old lstat */ { 1, (sy_call_t *)dup }, /* 41 = dup */ { 0, (sy_call_t *)pipe }, /* 42 = pipe */ { 0, (sy_call_t *)getegid }, /* 43 = getegid */ { 4, (sy_call_t *)profil }, /* 44 = profil */ { 4, (sy_call_t *)ktrace }, /* 45 = ktrace */ { 3, (sy_call_t *)sigaction }, /* 46 = sigaction */ { 0, (sy_call_t *)getgid }, /* 47 = getgid */ { 2, (sy_call_t *)sigprocmask }, /* 48 = sigprocmask */ { 2, (sy_call_t *)getlogin }, /* 49 = getlogin */ { 1, (sy_call_t *)setlogin }, /* 50 = setlogin */ { 1, (sy_call_t *)acct }, /* 51 = acct */ { 0, (sy_call_t *)sigpending }, /* 52 = sigpending */ { 2, (sy_call_t *)sigaltstack }, /* 53 = sigaltstack */ { 3, (sy_call_t *)ioctl }, /* 54 = ioctl */ { 1, (sy_call_t *)reboot }, /* 55 = reboot */ { 1, (sy_call_t *)revoke }, /* 56 = revoke */ { 2, (sy_call_t *)symlink }, /* 57 = symlink */ { 3, (sy_call_t *)readlink }, /* 58 = readlink */ { 3, (sy_call_t *)execve }, /* 59 = execve */ { 1, (sy_call_t *)umask }, /* 60 = umask */ { 1, (sy_call_t *)chroot }, /* 61 = chroot */ { compat(2,fstat) }, /* 62 = old fstat */ { compat(4,getkerninfo) }, /* 63 = old getkerninfo */ { compat(0,getpagesize) }, /* 64 = old getpagesize */ { 3, (sy_call_t *)msync }, /* 65 = msync */ { 0, (sy_call_t *)vfork }, /* 66 = vfork */ { 0, (sy_call_t *)nosys }, /* 67 = obsolete vread */ { 0, (sy_call_t *)nosys }, /* 68 = obsolete vwrite */ { 1, (sy_call_t *)sbrk }, /* 69 = sbrk */ { 1, (sy_call_t *)sstk }, /* 70 = sstk */ { compat(6,mmap) }, /* 71 = old mmap */ { 1, (sy_call_t *)ovadvise }, /* 72 = vadvise */ { 2, (sy_call_t *)munmap }, /* 73 = munmap */ { 3, (sy_call_t *)mprotect }, /* 74 = mprotect */ { 3, (sy_call_t *)madvise }, /* 75 = madvise */ { 0, (sy_call_t *)nosys }, /* 76 = obsolete vhangup */ { 0, (sy_call_t *)nosys }, /* 77 = obsolete vlimit */ { 3, (sy_call_t *)mincore }, /* 78 = mincore */ { 2, (sy_call_t *)getgroups }, /* 79 = getgroups */ { 2, (sy_call_t *)setgroups }, /* 80 = setgroups */ { 0, (sy_call_t *)getpgrp }, /* 81 = getpgrp */ { 2, (sy_call_t *)setpgid }, /* 82 = setpgid */ { 3, (sy_call_t *)setitimer }, /* 83 = setitimer */ { compat(0,wait) }, /* 84 = old wait */ { 1, (sy_call_t *)swapon }, /* 85 = swapon */ { 2, (sy_call_t *)getitimer }, /* 86 = getitimer */ { compat(2,gethostname) }, /* 87 = old gethostname */ { compat(2,sethostname) }, /* 88 = old sethostname */ { 0, (sy_call_t *)getdtablesize }, /* 89 = getdtablesize */ { 2, (sy_call_t *)dup2 }, /* 90 = dup2 */ { 0, (sy_call_t *)nosys }, /* 91 = getdopt */ { 3, (sy_call_t *)fcntl }, /* 92 = fcntl */ { 5, (sy_call_t *)select }, /* 93 = select */ { 0, (sy_call_t *)nosys }, /* 94 = setdopt */ { 1, (sy_call_t *)fsync }, /* 95 = fsync */ { 3, (sy_call_t *)setpriority }, /* 96 = setpriority */ { 3, (sy_call_t *)socket }, /* 97 = socket */ { 3, (sy_call_t *)connect }, /* 98 = connect */ { compat(3,accept) }, /* 99 = old accept */ { 2, (sy_call_t *)getpriority }, /* 100 = getpriority */ { compat(4,send) }, /* 101 = old send */ { compat(4,recv) }, /* 102 = old recv */ { 1, (sy_call_t *)sigreturn }, /* 103 = sigreturn */ { 3, (sy_call_t *)bind }, /* 104 = bind */ { 5, (sy_call_t *)setsockopt }, /* 105 = setsockopt */ { 2, (sy_call_t *)listen }, /* 106 = listen */ { 0, (sy_call_t *)nosys }, /* 107 = obsolete vtimes */ { compat(3,sigvec) }, /* 108 = old sigvec */ { compat(1,sigblock) }, /* 109 = old sigblock */ { compat(1,sigsetmask) }, /* 110 = old sigsetmask */ { 1, (sy_call_t *)sigsuspend }, /* 111 = sigsuspend */ { compat(2,sigstack) }, /* 112 = old sigstack */ { compat(3,recvmsg) }, /* 113 = old recvmsg */ { compat(3,sendmsg) }, /* 114 = old sendmsg */ { 0, (sy_call_t *)nosys }, /* 115 = obsolete vtrace */ { 2, (sy_call_t *)gettimeofday }, /* 116 = gettimeofday */ { 2, (sy_call_t *)getrusage }, /* 117 = getrusage */ { 5, (sy_call_t *)getsockopt }, /* 118 = getsockopt */ { 0, (sy_call_t *)nosys }, /* 119 = nosys */ { 3, (sy_call_t *)readv }, /* 120 = readv */ { 3, (sy_call_t *)writev }, /* 121 = writev */ { 2, (sy_call_t *)settimeofday }, /* 122 = settimeofday */ { 3, (sy_call_t *)fchown }, /* 123 = fchown */ { 2, (sy_call_t *)fchmod }, /* 124 = fchmod */ { compat(6,recvfrom) }, /* 125 = old recvfrom */ { 2, (sy_call_t *)setreuid }, /* 126 = setreuid */ { 2, (sy_call_t *)setregid }, /* 127 = setregid */ { 2, (sy_call_t *)rename }, /* 128 = rename */ { compat(2,truncate) }, /* 129 = old truncate */ { compat(2,ftruncate) }, /* 130 = old ftruncate */ { 2, (sy_call_t *)flock }, /* 131 = flock */ { 2, (sy_call_t *)mkfifo }, /* 132 = mkfifo */ { 6, (sy_call_t *)sendto }, /* 133 = sendto */ { 2, (sy_call_t *)shutdown }, /* 134 = shutdown */ { 4, (sy_call_t *)socketpair }, /* 135 = socketpair */ { 2, (sy_call_t *)mkdir }, /* 136 = mkdir */ { 1, (sy_call_t *)rmdir }, /* 137 = rmdir */ { 2, (sy_call_t *)utimes }, /* 138 = utimes */ { 0, (sy_call_t *)nosys }, /* 139 = obsolete 4.2 sigreturn */ { 2, (sy_call_t *)adjtime }, /* 140 = adjtime */ { compat(3,getpeername) }, /* 141 = old getpeername */ { compat(0,gethostid) }, /* 142 = old gethostid */ { compat(1,sethostid) }, /* 143 = old sethostid */ { compat(2,getrlimit) }, /* 144 = old getrlimit */ { compat(2,setrlimit) }, /* 145 = old setrlimit */ { compat(2,killpg) }, /* 146 = old killpg */ { 0, (sy_call_t *)setsid }, /* 147 = setsid */ { 4, (sy_call_t *)quotactl }, /* 148 = quotactl */ { compat(0,quota) }, /* 149 = old quota */ { compat(3,getsockname) }, /* 150 = old getsockname */ { 0, (sy_call_t *)nosys }, /* 151 = nosys */ { 0, (sy_call_t *)nosys }, /* 152 = nosys */ { 0, (sy_call_t *)nosys }, /* 153 = nosys */ { 0, (sy_call_t *)nosys }, /* 154 = nosys */ #ifdef NFS { 2, (sy_call_t *)nfssvc }, /* 155 = nfssvc */ #else { 0, (sy_call_t *)nosys }, /* 155 = nosys */ #endif { compat(4,getdirentries) }, /* 156 = old getdirentries */ { 2, (sy_call_t *)statfs }, /* 157 = statfs */ { 2, (sy_call_t *)fstatfs }, /* 158 = fstatfs */ { 0, (sy_call_t *)nosys }, /* 159 = nosys */ { 0, (sy_call_t *)nosys }, /* 160 = nosys */ #if defined(NFS) && !defined (NFS_NOSERVER) { 2, (sy_call_t *)getfh }, /* 161 = getfh */ #else { 0, (sy_call_t *)nosys }, /* 161 = nosys */ #endif { 2, (sy_call_t *)getdomainname }, /* 162 = getdomainname */ { 2, (sy_call_t *)setdomainname }, /* 163 = setdomainname */ { 1, (sy_call_t *)uname }, /* 164 = uname */ { 2, (sy_call_t *)sysarch }, /* 165 = sysarch */ { 3, (sy_call_t *)rtprio }, /* 166 = rtprio */ { 0, (sy_call_t *)nosys }, /* 167 = nosys */ { 0, (sy_call_t *)nosys }, /* 168 = nosys */ { 5, (sy_call_t *)semsys }, /* 169 = semsys */ { 6, (sy_call_t *)msgsys }, /* 170 = msgsys */ { 4, (sy_call_t *)shmsys }, /* 171 = shmsys */ { 0, (sy_call_t *)nosys }, /* 172 = nosys */ { 0, (sy_call_t *)nosys }, /* 173 = nosys */ { 0, (sy_call_t *)nosys }, /* 174 = nosys */ { 0, (sy_call_t *)nosys }, /* 175 = nosys */ { 1, (sy_call_t *)ntp_adjtime }, /* 176 = ntp_adjtime */ { 0, (sy_call_t *)nosys }, /* 177 = nosys */ { 0, (sy_call_t *)nosys }, /* 178 = nosys */ { 0, (sy_call_t *)nosys }, /* 179 = nosys */ { 0, (sy_call_t *)nosys }, /* 180 = nosys */ { 1, (sy_call_t *)setgid }, /* 181 = setgid */ { 1, (sy_call_t *)setegid }, /* 182 = setegid */ { 1, (sy_call_t *)seteuid }, /* 183 = seteuid */ #ifdef LFS { 3, (sy_call_t *)lfs_bmapv }, /* 184 = lfs_bmapv */ { 3, (sy_call_t *)lfs_markv }, /* 185 = lfs_markv */ { 2, (sy_call_t *)lfs_segclean }, /* 186 = lfs_segclean */ { 2, (sy_call_t *)lfs_segwait }, /* 187 = lfs_segwait */ #else { 0, (sy_call_t *)nosys }, /* 184 = nosys */ { 0, (sy_call_t *)nosys }, /* 185 = nosys */ { 0, (sy_call_t *)nosys }, /* 186 = nosys */ { 0, (sy_call_t *)nosys }, /* 187 = nosys */ #endif { 2, (sy_call_t *)stat }, /* 188 = stat */ { 2, (sy_call_t *)fstat }, /* 189 = fstat */ { 2, (sy_call_t *)lstat }, /* 190 = lstat */ { 2, (sy_call_t *)pathconf }, /* 191 = pathconf */ { 2, (sy_call_t *)fpathconf }, /* 192 = fpathconf */ { 0, (sy_call_t *)nosys }, /* 193 = nosys */ { 2, (sy_call_t *)getrlimit }, /* 194 = getrlimit */ { 2, (sy_call_t *)setrlimit }, /* 195 = setrlimit */ { 4, (sy_call_t *)getdirentries }, /* 196 = getdirentries */ { 8, (sy_call_t *)mmap }, /* 197 = mmap */ { 0, (sy_call_t *)nosys }, /* 198 = __syscall */ { 5, (sy_call_t *)lseek }, /* 199 = lseek */ { 4, (sy_call_t *)truncate }, /* 200 = truncate */ { 4, (sy_call_t *)ftruncate }, /* 201 = ftruncate */ { 6, (sy_call_t *)__sysctl }, /* 202 = __sysctl */ { 2, (sy_call_t *)mlock }, /* 203 = mlock */ { 2, (sy_call_t *)munlock }, /* 204 = munlock */ { 0, (sy_call_t *)nosys }, /* 205 = nosys */ { 0, (sy_call_t *)nosys }, /* 206 = nosys */ { 0, (sy_call_t *)nosys }, /* 207 = nosys */ { 0, (sy_call_t *)nosys }, /* 208 = nosys */ { 0, (sy_call_t *)nosys }, /* 209 = nosys */ { 0, (sy_call_t *)lkmnosys }, /* 210 = lkmnosys */ { 0, (sy_call_t *)lkmnosys }, /* 211 = lkmnosys */ { 0, (sy_call_t *)lkmnosys }, /* 212 = lkmnosys */ { 0, (sy_call_t *)lkmnosys }, /* 213 = lkmnosys */ { 0, (sy_call_t *)lkmnosys }, /* 214 = lkmnosys */ { 0, (sy_call_t *)lkmnosys }, /* 215 = lkmnosys */ { 0, (sy_call_t *)lkmnosys }, /* 216 = lkmnosys */ { 0, (sy_call_t *)lkmnosys }, /* 217 = lkmnosys */ { 0, (sy_call_t *)lkmnosys }, /* 218 = lkmnosys */ { 0, (sy_call_t *)lkmnosys }, /* 219 = lkmnosys */ { 4, (sy_call_t *)__semctl }, /* 220 = __semctl */ { 3, (sy_call_t *)semget }, /* 221 = semget */ { 3, (sy_call_t *)semop }, /* 222 = semop */ { 1, (sy_call_t *)semconfig }, /* 223 = semconfig */ { 3, (sy_call_t *)msgctl }, /* 224 = msgctl */ { 2, (sy_call_t *)msgget }, /* 225 = msgget */ { 4, (sy_call_t *)msgsnd }, /* 226 = msgsnd */ { 5, (sy_call_t *)msgrcv }, /* 227 = msgrcv */ { 3, (sy_call_t *)shmat }, /* 228 = shmat */ { 3, (sy_call_t *)shmctl }, /* 229 = shmctl */ { 1, (sy_call_t *)shmdt }, /* 230 = shmdt */ { 3, (sy_call_t *)shmget }, /* 231 = shmget */ }; struct sysentvec aout_sysvec = { sizeof (sysent) / sizeof (sysent[0]), sysent, 0, 0, 0, 0, 0, 0 }; Index: head/sys/kern/kern_exec.c =================================================================== --- head/sys/kern/kern_exec.c (revision 13522) +++ head/sys/kern/kern_exec.c (revision 13523) @@ -1,584 +1,582 @@ /* * Copyright (c) 1993, David Greenman * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by David Greenman * 4. The name of the developer may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: kern_exec.c,v 1.32 1996/01/08 04:30:41 peter Exp $ + * $Id: kern_exec.c,v 1.33 1996/01/19 03:58:01 dyson Exp $ */ - -#include "opt_sysvipc.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static int *exec_copyout_strings __P((struct image_params *)); static int exec_check_permissions(struct image_params *); /* * execsw_set is constructed for us by the linker. Each of the items * is a pointer to a `const struct execsw', hence the double pointer here. */ static const struct execsw **execsw = (const struct execsw **)&execsw_set.ls_items[0]; #ifndef _SYS_SYSPROTO_H_ struct execve_args { char *fname; char **argv; char **envv; }; #endif /* * execve() system call. */ int execve(p, uap, retval) struct proc *p; register struct execve_args *uap; int *retval; { struct nameidata nd, *ndp; int *stack_base; int error, len, i; struct image_params image_params, *imgp; struct vattr attr; imgp = &image_params; /* * Initialize part of the common data */ imgp->proc = p; imgp->uap = uap; imgp->attr = &attr; imgp->image_header = NULL; imgp->argc = imgp->envc = 0; imgp->entry_addr = 0; imgp->vmspace_destroyed = 0; imgp->interpreted = 0; imgp->interpreter_name[0] = '\0'; /* * Allocate temporary demand zeroed space for argument and * environment strings */ imgp->stringbase = (char *)kmem_alloc_pageable(exec_map, ARG_MAX); if (imgp->stringbase == NULL) { error = ENOMEM; goto exec_fail; } imgp->stringp = imgp->stringbase; imgp->stringspace = ARG_MAX; /* * Translate the file name. namei() returns a vnode pointer * in ni_vp amoung other things. */ ndp = &nd; NDINIT(ndp, LOOKUP, LOCKLEAF | FOLLOW | SAVENAME, UIO_USERSPACE, uap->fname, p); interpret: error = namei(ndp); if (error) { kmem_free(exec_map, (vm_offset_t)imgp->stringbase, ARG_MAX); goto exec_fail; } imgp->vp = ndp->ni_vp; if (imgp->vp == NULL) { error = ENOEXEC; goto exec_fail_dealloc; } /* * Check file permissions (also 'opens' file) */ error = exec_check_permissions(imgp); /* * Lose the lock on the vnode. It's no longer needed, and must not * exist for the pagefault paging to work below. */ VOP_UNLOCK(imgp->vp); if (error) goto exec_fail_dealloc; /* * Map the image header (first page) of the file into * kernel address space */ error = vm_mmap(kernel_map, /* map */ (vm_offset_t *)&imgp->image_header, /* address */ PAGE_SIZE, /* size */ VM_PROT_READ, /* protection */ VM_PROT_READ, /* max protection */ 0, /* flags */ (caddr_t)imgp->vp, /* vnode */ 0); /* offset */ if (error) { uprintf("mmap failed: %d\n",error); goto exec_fail_dealloc; } /* * Loop through list of image activators, calling each one. * If there is no match, the activator returns -1. If there * is a match, but there was an error during the activation, * the error is returned. Otherwise 0 means success. If the * image is interpreted, loop back up and try activating * the interpreter. */ for (i = 0; execsw[i]; ++i) { if (execsw[i]->ex_imgact) error = (*execsw[i]->ex_imgact)(imgp); else continue; if (error == -1) continue; if (error) goto exec_fail_dealloc; if (imgp->interpreted) { /* free old vnode and name buffer */ vrele(ndp->ni_vp); FREE(ndp->ni_cnd.cn_pnbuf, M_NAMEI); if (vm_map_remove(kernel_map, (vm_offset_t)imgp->image_header, (vm_offset_t)imgp->image_header + PAGE_SIZE)) panic("execve: header dealloc failed (1)"); /* set new name to that of the interpreter */ NDINIT(ndp, LOOKUP, LOCKLEAF | FOLLOW | SAVENAME, UIO_SYSSPACE, imgp->interpreter_name, p); goto interpret; } break; } /* If we made it through all the activators and none matched, exit. */ if (error == -1) { error = ENOEXEC; goto exec_fail_dealloc; } /* * Copy out strings (args and env) and initialize stack base */ stack_base = exec_copyout_strings(imgp); p->p_vmspace->vm_minsaddr = (char *)stack_base; /* * If custom stack fixup routine present for this process * let it do the stack setup. * Else stuff argument count as first item on stack */ if (p->p_sysent->sv_fixup) (*p->p_sysent->sv_fixup)(&stack_base, imgp); else suword(--stack_base, imgp->argc); /* close files on exec */ fdcloseexec(p); /* reset caught signals */ execsigs(p); /* name this process - nameiexec(p, ndp) */ len = min(ndp->ni_cnd.cn_namelen,MAXCOMLEN); bcopy(ndp->ni_cnd.cn_nameptr, p->p_comm, len); p->p_comm[len] = 0; /* * mark as executable, wakeup any process that was vforked and tell * it that it now has it's own resources back */ p->p_flag |= P_EXEC; if (p->p_pptr && (p->p_flag & P_PPWAIT)) { p->p_flag &= ~P_PPWAIT; wakeup((caddr_t)p->p_pptr); } /* * Implement image setuid/setgid. Disallow if the process is * being traced. */ if ((attr.va_mode & (VSUID | VSGID)) && (p->p_flag & P_TRACED) == 0) { /* * Turn off syscall tracing for set-id programs, except for * root. */ if (p->p_tracep && suser(p->p_ucred, &p->p_acflag)) { p->p_traceflag = 0; vrele(p->p_tracep); p->p_tracep = NULL; } /* * Set the new credentials. */ p->p_ucred = crcopy(p->p_ucred); if (attr.va_mode & VSUID) p->p_ucred->cr_uid = attr.va_uid; if (attr.va_mode & VSGID) p->p_ucred->cr_groups[0] = attr.va_gid; p->p_flag |= P_SUGID; } else { p->p_flag &= ~P_SUGID; } /* * Implement correct POSIX saved-id behavior. */ p->p_cred->p_svuid = p->p_ucred->cr_uid; p->p_cred->p_svgid = p->p_ucred->cr_gid; /* * Store the vp for use in procfs */ if (p->p_textvp) /* release old reference */ vrele(p->p_textvp); VREF(ndp->ni_vp); p->p_textvp = ndp->ni_vp; /* * If tracing the process, trap to debugger so breakpoints * can be set before the program executes. */ if (p->p_flag & P_TRACED) psignal(p, SIGTRAP); /* clear "fork but no exec" flag, as we _are_ execing */ p->p_acflag &= ~AFORK; /* Set entry address */ setregs(p, imgp->entry_addr, (u_long)stack_base); /* * free various allocated resources */ kmem_free(exec_map, (vm_offset_t)imgp->stringbase, ARG_MAX); if (vm_map_remove(kernel_map, (vm_offset_t)imgp->image_header, (vm_offset_t)imgp->image_header + PAGE_SIZE)) panic("execve: header dealloc failed (2)"); vrele(ndp->ni_vp); FREE(ndp->ni_cnd.cn_pnbuf, M_NAMEI); return (0); exec_fail_dealloc: if (imgp->stringbase != NULL) kmem_free(exec_map, (vm_offset_t)imgp->stringbase, ARG_MAX); if (imgp->image_header && imgp->image_header != (char *)-1) if (vm_map_remove(kernel_map, (vm_offset_t)imgp->image_header, (vm_offset_t)imgp->image_header + PAGE_SIZE)) panic("execve: header dealloc failed (3)"); if (ndp->ni_vp) vrele(ndp->ni_vp); FREE(ndp->ni_cnd.cn_pnbuf, M_NAMEI); exec_fail: if (imgp->vmspace_destroyed) { /* sorry, no more process anymore. exit gracefully */ exit1(p, W_EXITCODE(0, SIGABRT)); /* NOT REACHED */ return(0); } else { return(error); } } /* * Destroy old address space, and allocate a new stack * The new stack is only SGROWSIZ large because it is grown * automatically in trap.c. */ int exec_new_vmspace(imgp) struct image_params *imgp; { int error; struct vmspace *vmspace = imgp->proc->p_vmspace; caddr_t stack_addr = (caddr_t) (USRSTACK - SGROWSIZ); imgp->vmspace_destroyed = 1; /* Blow away entire process VM */ if (vmspace->vm_shm) shmexit(imgp->proc); vm_map_remove(&vmspace->vm_map, 0, USRSTACK); /* Allocate a new stack */ error = vm_map_find(&vmspace->vm_map, NULL, 0, (vm_offset_t *)&stack_addr, SGROWSIZ, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0); if (error) return(error); vmspace->vm_ssize = SGROWSIZ >> PAGE_SHIFT; /* Initialize maximum stack address */ vmspace->vm_maxsaddr = (char *)USRSTACK - MAXSSIZ; return(0); } /* * Copy out argument and environment strings from the old process * address space into the temporary string buffer. */ int exec_extract_strings(imgp) struct image_params *imgp; { char **argv, **envv; char *argp, *envp; int error, length; /* * extract arguments first */ argv = imgp->uap->argv; if (argv) { while ((argp = (caddr_t) fuword(argv++))) { if (argp == (caddr_t) -1) return (EFAULT); if ((error = copyinstr(argp, imgp->stringp, imgp->stringspace, &length))) { if (error == ENAMETOOLONG) return(E2BIG); return (error); } imgp->stringspace -= length; imgp->stringp += length; imgp->argc++; } } /* * extract environment strings */ envv = imgp->uap->envv; if (envv) { while ((envp = (caddr_t) fuword(envv++))) { if (envp == (caddr_t) -1) return (EFAULT); if ((error = copyinstr(envp, imgp->stringp, imgp->stringspace, &length))) { if (error == ENAMETOOLONG) return(E2BIG); return (error); } imgp->stringspace -= length; imgp->stringp += length; imgp->envc++; } } return (0); } /* * Copy strings out to the new process address space, constructing * new arg and env vector tables. Return a pointer to the base * so that it can be used as the initial stack pointer. */ int * exec_copyout_strings(imgp) struct image_params *imgp; { int argc, envc; char **vectp; char *stringp, *destp; int *stack_base; struct ps_strings *arginfo; /* * Calculate string base and vector table pointers. */ arginfo = PS_STRINGS; destp = (caddr_t)arginfo - SPARE_USRSPACE - roundup((ARG_MAX - imgp->stringspace), sizeof(char *)); /* * The '+ 2' is for the null pointers at the end of each of the * arg and env vector sets */ vectp = (char **) (destp - (imgp->argc + imgp->envc + 2) * sizeof(char *)); /* * vectp also becomes our initial stack base */ stack_base = (int *)vectp; stringp = imgp->stringbase; argc = imgp->argc; envc = imgp->envc; /* * Copy out strings - arguments and environment. */ copyout(stringp, destp, ARG_MAX - imgp->stringspace); /* * Fill in "ps_strings" struct for ps, w, etc. */ suword(&arginfo->ps_argvstr, (int)vectp); suword(&arginfo->ps_nargvstr, argc); /* * Fill in argument portion of vector table. */ for (; argc > 0; --argc) { suword(vectp++, (int)destp); while (*stringp++ != 0) destp++; destp++; } /* a null vector table pointer seperates the argp's from the envp's */ suword(vectp++, NULL); suword(&arginfo->ps_envstr, (int)vectp); suword(&arginfo->ps_nenvstr, envc); /* * Fill in environment portion of vector table. */ for (; envc > 0; --envc) { suword(vectp++, (int)destp); while (*stringp++ != 0) destp++; destp++; } /* end of vector table is a null pointer */ suword(vectp, NULL); return (stack_base); } /* * Check permissions of file to execute. * Return 0 for success or error code on failure. */ static int exec_check_permissions(imgp) struct image_params *imgp; { struct proc *p = imgp->proc; struct vnode *vp = imgp->vp; struct vattr *attr = imgp->attr; int error; /* * Check number of open-for-writes on the file and deny execution * if there are any. */ if (vp->v_writecount) { return (ETXTBSY); } /* Get file attributes */ error = VOP_GETATTR(vp, attr, p->p_ucred, p); if (error) return (error); /* * 1) Check if file execution is disabled for the filesystem that this * file resides on. * 2) Insure that at least one execute bit is on - otherwise root * will always succeed, and we don't want to happen unless the * file really is executable. * 3) Insure that the file is a regular file. */ if ((vp->v_mount->mnt_flag & MNT_NOEXEC) || ((attr->va_mode & 0111) == 0) || (attr->va_type != VREG)) { return (EACCES); } /* * Zero length files can't be exec'd */ if (attr->va_size == 0) return (ENOEXEC); /* * Disable setuid/setgid if the filesystem prohibits it or if * the process is being traced. */ if ((vp->v_mount->mnt_flag & MNT_NOSUID) || (p->p_flag & P_TRACED)) attr->va_mode &= ~(VSUID | VSGID); /* * Check for execute permission to file based on current credentials. * Then call filesystem specific open routine (which does nothing * in the general case). */ error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); if (error) return (error); error = VOP_OPEN(vp, FREAD, p->p_ucred, p); if (error) return (error); return (0); } Index: head/sys/kern/kern_exit.c =================================================================== --- head/sys/kern/kern_exit.c (revision 13522) +++ head/sys/kern/kern_exit.c (revision 13523) @@ -1,516 +1,515 @@ /*- * Copyright (c) 1982, 1986, 1989, 1991, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)kern_exit.c 8.7 (Berkeley) 2/12/94 - * $Id: kern_exit.c,v 1.26 1996/01/08 04:30:44 peter Exp $ + * $Id: kern_exit.c,v 1.27 1996/01/19 03:58:03 dyson Exp $ */ #include "opt_ktrace.h" -#include "opt_sysvipc.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef COMPAT_43 #include #include #endif #include #include #include #include #include #include #include static int wait1 __P((struct proc *, struct wait_args *, int [], int)); /* * exit -- * Death of process. */ __dead void exit(p, uap, retval) struct proc *p; struct rexit_args /* { int rval; } */ *uap; int *retval; { exit1(p, W_EXITCODE(uap->rval, 0)); /* NOTREACHED */ } /* * Exit: deallocate address space and other resources, change proc state * to zombie, and unlink proc from allproc and parent's lists. Save exit * status and rusage for wait(). Check for child processes and orphan them. */ __dead void exit1(p, rv) register struct proc *p; int rv; { register struct proc *q, *nq; register struct proc **pp; register struct vmspace *vm; if (p->p_pid == 1) { printf("init died (signal %d, exit %d)\n", WTERMSIG(rv), WEXITSTATUS(rv)); panic("Going nowhere without my init!"); } #ifdef PGINPROF vmsizmon(); #endif if (p->p_flag & P_PROFIL) stopprofclock(p); MALLOC(p->p_ru, struct rusage *, sizeof(struct rusage), M_ZOMBIE, M_WAITOK); /* * If parent is waiting for us to exit or exec, * P_PPWAIT is set; we will wakeup the parent below. */ p->p_flag &= ~(P_TRACED | P_PPWAIT); p->p_flag |= P_WEXIT; p->p_sigignore = ~0; p->p_siglist = 0; untimeout(realitexpire, (caddr_t)p); /* * Close open files and release open-file table. * This may block! */ fdfree(p); /* * XXX Shutdown SYSV semaphores */ semexit(p); /* The next two chunks should probably be moved to vmspace_exit. */ vm = p->p_vmspace; if (vm->vm_shm) shmexit(p); /* * Release user portion of address space. * This releases references to vnodes, * which could cause I/O if the file has been unlinked. * Need to do this early enough that we can still sleep. * Can't free the entire vmspace as the kernel stack * may be mapped within that space also. */ if (vm->vm_refcnt == 1) (void) vm_map_remove(&vm->vm_map, VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS); if (SESS_LEADER(p)) { register struct session *sp = p->p_session; if (sp->s_ttyvp) { /* * Controlling process. * Signal foreground pgrp, * drain controlling terminal * and revoke access to controlling terminal. */ if (sp->s_ttyp->t_session == sp) { if (sp->s_ttyp->t_pgrp) pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1); (void) ttywait(sp->s_ttyp); /* * The tty could have been revoked * if we blocked. */ if (sp->s_ttyvp) vgoneall(sp->s_ttyvp); } if (sp->s_ttyvp) vrele(sp->s_ttyvp); sp->s_ttyvp = NULL; /* * s_ttyp is not zero'd; we use this to indicate * that the session once had a controlling terminal. * (for logging and informational purposes) */ } sp->s_leader = NULL; } fixjobc(p, p->p_pgrp, 0); p->p_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY; (void)acct_process(p); #ifdef KTRACE /* * release trace file */ p->p_traceflag = 0; /* don't trace the vrele() */ if (p->p_tracep) vrele(p->p_tracep); #endif /* * Remove proc from allproc queue and pidhash chain. * Place onto zombproc. Unlink from parent's child list. */ if ((*p->p_prev = p->p_next)) p->p_next->p_prev = p->p_prev; if ((p->p_next = zombproc)) p->p_next->p_prev = &p->p_next; p->p_prev = &zombproc; zombproc = p; p->p_stat = SZOMB; for (pp = &pidhash[PIDHASH(p->p_pid)]; *pp; pp = &(*pp)->p_hash) if (*pp == p) { *pp = p->p_hash; goto done; } panic("exit"); done: if (p->p_cptr) /* only need this if any child is S_ZOMB */ wakeup((caddr_t) initproc); for (q = p->p_cptr; q != NULL; q = nq) { nq = q->p_osptr; if (nq != NULL) nq->p_ysptr = NULL; if (initproc->p_cptr) initproc->p_cptr->p_ysptr = q; q->p_osptr = initproc->p_cptr; q->p_ysptr = NULL; initproc->p_cptr = q; q->p_pptr = initproc; /* * Traced processes are killed * since their existence means someone is screwing up. */ if (q->p_flag & P_TRACED) { q->p_flag &= ~P_TRACED; psignal(q, SIGKILL); } } p->p_cptr = NULL; /* * Save exit status and final rusage info, adding in child rusage * info and self times. */ p->p_xstat = rv; *p->p_ru = p->p_stats->p_ru; calcru(p, &p->p_ru->ru_utime, &p->p_ru->ru_stime, NULL); ruadd(p->p_ru, &p->p_stats->p_cru); /* * Notify parent that we're gone. */ psignal(p->p_pptr, SIGCHLD); wakeup((caddr_t)p->p_pptr); #if defined(tahoe) /* move this to cpu_exit */ p->p_addr->u_pcb.pcb_savacc.faddr = (float *)NULL; #endif /* * Clear curproc after we've done all operations * that could block, and before tearing down the rest * of the process state that might be used from clock, etc. * Also, can't clear curproc while we're still runnable, * as we're not on a run queue (we are current, just not * a proper proc any longer!). * * Other substructures are freed from wait(). */ curproc = NULL; if (--p->p_limit->p_refcnt == 0) { FREE(p->p_limit, M_SUBPROC); p->p_limit = NULL; } /* * Finally, call machine-dependent code to release the remaining * resources including address space, the kernel stack and pcb. * The address space is released by "vmspace_free(p->p_vmspace)"; * This is machine-dependent, as we may have to change stacks * or ensure that the current one isn't reallocated before we * finish. cpu_exit will end with a call to cpu_swtch(), finishing * our execution (pun intended). */ cpu_exit(p); } #ifdef COMPAT_43 #if defined(hp300) || defined(luna68k) #include #define GETPS(rp) ((struct frame *)(rp))->f_sr #else #define GETPS(rp) (rp)[PS] #endif int owait(p, uap, retval) struct proc *p; register struct owait_args /* { int dummy; } */ *uap; int *retval; { struct wait_args w; #ifdef PSL_ALLCC if ((GETPS(p->p_md.md_regs) & PSL_ALLCC) != PSL_ALLCC) { w.options = 0; w.rusage = NULL; } else { w.options = p->p_md.md_regs[R0]; w.rusage = (struct rusage *)p->p_md.md_regs[R1]; } #else w.options = 0; w.rusage = NULL; #endif w.pid = WAIT_ANY; w.status = NULL; return (wait1(p, &w, retval, 1)); } #endif /* COMPAT_43 */ int wait4(p, uap, retval) struct proc *p; struct wait_args *uap; int *retval; { return (wait1(p, uap, retval, 0)); } static int wait1(q, uap, retval, compat) register struct proc *q; register struct wait_args /* { int pid; int *status; int options; struct rusage *rusage; } */ *uap; int retval[]; int compat; { register int nfound; register struct proc *p, *t; int status, error; if (uap->pid == 0) uap->pid = -q->p_pgid; #ifdef notyet if (uap->options &~ (WUNTRACED|WNOHANG)) return (EINVAL); #endif loop: nfound = 0; for (p = q->p_cptr; p; p = p->p_osptr) { if (uap->pid != WAIT_ANY && p->p_pid != uap->pid && p->p_pgid != -uap->pid) continue; nfound++; if (p->p_stat == SZOMB) { /* charge childs scheduling cpu usage to parent */ if (curproc->p_pid != 1) { curproc->p_estcpu = min(curproc->p_estcpu + p->p_estcpu, UCHAR_MAX); } retval[0] = p->p_pid; #ifdef COMPAT_43 if (compat) retval[1] = p->p_xstat; else #endif if (uap->status) { status = p->p_xstat; /* convert to int */ if ((error = copyout((caddr_t)&status, (caddr_t)uap->status, sizeof(status)))) return (error); } if (uap->rusage && (error = copyout((caddr_t)p->p_ru, (caddr_t)uap->rusage, sizeof (struct rusage)))) return (error); /* * If we got the child via a ptrace 'attach', * we need to give it back to the old parent. */ if (p->p_oppid && (t = pfind(p->p_oppid))) { p->p_oppid = 0; proc_reparent(p, t); psignal(t, SIGCHLD); wakeup((caddr_t)t); return (0); } p->p_xstat = 0; ruadd(&q->p_stats->p_cru, p->p_ru); FREE(p->p_ru, M_ZOMBIE); p->p_ru = NULL; /* * Decrement the count of procs running with this uid. */ (void)chgproccnt(p->p_cred->p_ruid, -1); /* * Release reference to text vnode */ if (p->p_textvp) vrele(p->p_textvp); /* * Free up credentials. */ if (--p->p_cred->p_refcnt == 0) { crfree(p->p_cred->pc_ucred); FREE(p->p_cred, M_SUBPROC); p->p_cred = NULL; } /* * Finally finished with old proc entry. * Unlink it from its process group and free it. */ leavepgrp(p); if ((*p->p_prev = p->p_next)) /* off zombproc */ p->p_next->p_prev = p->p_prev; if ((q = p->p_ysptr)) q->p_osptr = p->p_osptr; if ((q = p->p_osptr)) q->p_ysptr = p->p_ysptr; if ((q = p->p_pptr)->p_cptr == p) q->p_cptr = p->p_osptr; /* * Give machine-dependent layer a chance * to free anything that cpu_exit couldn't * release while still running in process context. */ cpu_wait(p); FREE(p, M_PROC); nprocs--; return (0); } if (p->p_stat == SSTOP && (p->p_flag & P_WAITED) == 0 && (p->p_flag & P_TRACED || uap->options & WUNTRACED)) { p->p_flag |= P_WAITED; retval[0] = p->p_pid; #ifdef COMPAT_43 if (compat) { retval[1] = W_STOPCODE(p->p_xstat); error = 0; } else #endif if (uap->status) { status = W_STOPCODE(p->p_xstat); error = copyout((caddr_t)&status, (caddr_t)uap->status, sizeof(status)); } else error = 0; return (error); } } if (nfound == 0) return (ECHILD); if (uap->options & WNOHANG) { retval[0] = 0; return (0); } if ((error = tsleep((caddr_t)q, PWAIT | PCATCH, "wait", 0))) return (error); goto loop; } /* * make process 'parent' the new parent of process 'child'. */ void proc_reparent(child, parent) register struct proc *child; register struct proc *parent; { register struct proc *o; register struct proc *y; if (child->p_pptr == parent) return; /* fix up the child linkage for the old parent */ o = child->p_osptr; y = child->p_ysptr; if (y) y->p_osptr = o; if (o) o->p_ysptr = y; if (child->p_pptr->p_cptr == child) child->p_pptr->p_cptr = o; /* fix up child linkage for new parent */ o = parent->p_cptr; if (o) o->p_ysptr = child; child->p_osptr = o; child->p_ysptr = NULL; parent->p_cptr = child; child->p_pptr = parent; }