diff options
author | dg <dg@FreeBSD.org> | 1995-11-06 12:52:37 +0000 |
---|---|---|
committer | dg <dg@FreeBSD.org> | 1995-11-06 12:52:37 +0000 |
commit | b0e92e3fe4280bcb3c077c4b792fd4b49023a90e (patch) | |
tree | b1085bc2d506b9f9ebbc0763719203202ce8d6a6 /sys/kern/kern_exec.c | |
parent | 70e33173922ad4e39017ab578a3fe083ecc6b794 (diff) | |
download | FreeBSD-src-b0e92e3fe4280bcb3c077c4b792fd4b49023a90e.zip FreeBSD-src-b0e92e3fe4280bcb3c077c4b792fd4b49023a90e.tar.gz |
All:
Changed vnodep -> vp for consistency with the rest of the kernel, and
changed iparams -> imgp for brevity.
kern_exec.c:
Explicitly initialized some additional parts of the image_params struct
to avoid bzeroing it. Rewrote the set-id code to reduce the number of
logical tests. The rewrite exposed a mostly benign bug in the algorithm:
traced set-id images would get ktracing disabled even if the set-id didn't
happen for other reasons.
Diffstat (limited to 'sys/kern/kern_exec.c')
-rw-r--r-- | sys/kern/kern_exec.c | 210 |
1 files changed, 107 insertions, 103 deletions
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index eb956f5..e827ac9 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -28,7 +28,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: kern_exec.c,v 1.23 1995/10/08 00:06:01 swallace Exp $ + * $Id: kern_exec.c,v 1.24 1995/10/21 08:38:11 davidg Exp $ */ #include <sys/param.h> @@ -80,40 +80,42 @@ execve(p, uap, retval) struct nameidata nd, *ndp; int *stack_base; int error, len, i; - struct image_params image_params, *iparams; - struct vnode *vnodep; + struct image_params image_params, *imgp; struct vattr attr; - char *image_header; - iparams = &image_params; - bzero((caddr_t)iparams, sizeof(struct image_params)); - image_header = (char *)0; + imgp = &image_params; /* - * Initialize a few constants in the common area + * Initialize part of the common data */ - iparams->proc = p; - iparams->uap = uap; - iparams->attr = &attr; + 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 */ - iparams->stringbase = (char *)vm_map_min(exec_map); - error = vm_map_find(exec_map, NULL, 0, (vm_offset_t *)&iparams->stringbase, + imgp->stringbase = (char *)vm_map_min(exec_map); + error = vm_map_find(exec_map, NULL, 0, (vm_offset_t *)&imgp->stringbase, ARG_MAX, TRUE); if (error) { log(LOG_WARNING, "execve: failed to allocate string space\n"); return (error); } - if (!iparams->stringbase) { + if (!imgp->stringbase) { error = ENOMEM; goto exec_fail; } - iparams->stringp = iparams->stringbase; - iparams->stringspace = ARG_MAX; + imgp->stringp = imgp->stringbase; + imgp->stringspace = ARG_MAX; /* * Translate the file name. namei() returns a vnode pointer @@ -127,14 +129,13 @@ interpret: error = namei(ndp); if (error) { - vm_map_remove(exec_map, (vm_offset_t)iparams->stringbase, - (vm_offset_t)iparams->stringbase + ARG_MAX); + vm_map_remove(exec_map, (vm_offset_t)imgp->stringbase, + (vm_offset_t)imgp->stringbase + ARG_MAX); goto exec_fail; } - iparams->vnodep = vnodep = ndp->ni_vp; - - if (vnodep == NULL) { + imgp->vp = ndp->ni_vp; + if (imgp->vp == NULL) { error = ENOEXEC; goto exec_fail_dealloc; } @@ -142,13 +143,13 @@ interpret: /* * Check file permissions (also 'opens' file) */ - error = exec_check_permissions(iparams); + 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(vnodep); + VOP_UNLOCK(imgp->vp); if (error) goto exec_fail_dealloc; @@ -158,18 +159,17 @@ interpret: * kernel address space */ error = vm_mmap(kernel_map, /* map */ - (vm_offset_t *)&image_header, /* address */ + (vm_offset_t *)&imgp->image_header, /* address */ PAGE_SIZE, /* size */ VM_PROT_READ, /* protection */ VM_PROT_READ, /* max protection */ 0, /* flags */ - (caddr_t)vnodep, /* vnode */ + (caddr_t)imgp->vp, /* vnode */ 0); /* offset */ if (error) { uprintf("mmap failed: %d\n",error); goto exec_fail_dealloc; } - iparams->image_header = image_header; /* * Loop through list of image activators, calling each one. @@ -181,7 +181,7 @@ interpret: */ for (i = 0; execsw[i]; ++i) { if (execsw[i]->ex_imgact) - error = (*execsw[i]->ex_imgact)(iparams); + error = (*execsw[i]->ex_imgact)(imgp); else continue; @@ -189,17 +189,17 @@ interpret: continue; if (error) goto exec_fail_dealloc; - if (iparams->interpreted) { + 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)image_header, - (vm_offset_t)image_header + PAGE_SIZE)) + 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, iparams->interpreter_name, p); + UIO_SYSSPACE, imgp->interpreter_name, p); goto interpret; } break; @@ -213,7 +213,7 @@ interpret: /* * Copy out strings (args and env) and initialize stack base */ - stack_base = exec_copyout_strings(iparams); + stack_base = exec_copyout_strings(imgp); p->p_vmspace->vm_minsaddr = (char *)stack_base; /* @@ -222,9 +222,9 @@ interpret: * Else stuff argument count as first item on stack */ if (p->p_sysent->sv_fixup) - (*p->p_sysent->sv_fixup)(&stack_base, iparams); + (*p->p_sysent->sv_fixup)(&stack_base, imgp); else - suword(--stack_base, iparams->argc); + suword(--stack_base, imgp->argc); /* close files on exec */ fdcloseexec(p); @@ -247,32 +247,36 @@ interpret: wakeup((caddr_t)p->p_pptr); } - /* implement set userid/groupid */ - p->p_flag &= ~P_SUGID; - /* - * Turn off kernel tracing for set-id programs, except for - * root. + * Implement image setuid/setgid. Disallow if the process is + * being traced. */ - if (p->p_tracep && (attr.va_mode & (VSUID | VSGID)) && - suser(p->p_ucred, &p->p_acflag)) { - p->p_traceflag = 0; - vrele(p->p_tracep); - p->p_tracep = 0; - } - if ((attr.va_mode & VSUID) && (p->p_flag & P_TRACED) == 0) { - p->p_ucred = crcopy(p->p_ucred); - p->p_ucred->cr_uid = attr.va_uid; - p->p_flag |= P_SUGID; - } - if ((attr.va_mode & VSGID) && (p->p_flag & P_TRACED) == 0) { + 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); - p->p_ucred->cr_groups[0] = attr.va_gid; + 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 uid behavior. + * 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; @@ -296,16 +300,16 @@ interpret: p->p_acflag &= ~AFORK; /* Set entry address */ - setregs(p, iparams->entry_addr, (u_long)stack_base); + setregs(p, imgp->entry_addr, (u_long)stack_base); /* * free various allocated resources */ - if (vm_map_remove(exec_map, (vm_offset_t)iparams->stringbase, - (vm_offset_t)iparams->stringbase + ARG_MAX)) + if (vm_map_remove(exec_map, (vm_offset_t)imgp->stringbase, + (vm_offset_t)imgp->stringbase + ARG_MAX)) panic("execve: string buffer dealloc failed (1)"); - if (vm_map_remove(kernel_map, (vm_offset_t)image_header, - (vm_offset_t)image_header + PAGE_SIZE)) + 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); @@ -313,20 +317,20 @@ interpret: return (0); exec_fail_dealloc: - if (iparams->stringbase && iparams->stringbase != (char *)-1) - if (vm_map_remove(exec_map, (vm_offset_t)iparams->stringbase, - (vm_offset_t)iparams->stringbase + ARG_MAX)) + if (imgp->stringbase && imgp->stringbase != (char *)-1) + if (vm_map_remove(exec_map, (vm_offset_t)imgp->stringbase, + (vm_offset_t)imgp->stringbase + ARG_MAX)) panic("execve: string buffer dealloc failed (2)"); - if (iparams->image_header && iparams->image_header != (char *)-1) - if (vm_map_remove(kernel_map, (vm_offset_t)image_header, - (vm_offset_t)image_header + PAGE_SIZE)) + 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 (iparams->vmspace_destroyed) { + if (imgp->vmspace_destroyed) { /* sorry, no more process anymore. exit gracefully */ exit1(p, W_EXITCODE(0, SIGABRT)); /* NOT REACHED */ @@ -342,19 +346,19 @@ exec_fail: * automatically in trap.c. */ int -exec_new_vmspace(iparams) - struct image_params *iparams; +exec_new_vmspace(imgp) + struct image_params *imgp; { int error; - struct vmspace *vmspace = iparams->proc->p_vmspace; + struct vmspace *vmspace = imgp->proc->p_vmspace; caddr_t stack_addr = (caddr_t) (USRSTACK - SGROWSIZ); - iparams->vmspace_destroyed = 1; + imgp->vmspace_destroyed = 1; /* Blow away entire process VM */ #ifdef SYSVSHM if (vmspace->vm_shm) - shmexit(iparams->proc); + shmexit(imgp->proc); #endif vm_map_remove(&vmspace->vm_map, 0, USRSTACK); @@ -377,8 +381,8 @@ exec_new_vmspace(iparams) * address space into the temporary string buffer. */ int -exec_extract_strings(iparams) - struct image_params *iparams; +exec_extract_strings(imgp) + struct image_params *imgp; { char **argv, **envv; char *argp, *envp; @@ -388,21 +392,21 @@ exec_extract_strings(iparams) * extract arguments first */ - argv = iparams->uap->argv; + argv = imgp->uap->argv; if (argv) { while ((argp = (caddr_t) fuword(argv++))) { if (argp == (caddr_t) -1) return (EFAULT); - if ((error = copyinstr(argp, iparams->stringp, - iparams->stringspace, &length))) { + if ((error = copyinstr(argp, imgp->stringp, + imgp->stringspace, &length))) { if (error == ENAMETOOLONG) return(E2BIG); return (error); } - iparams->stringspace -= length; - iparams->stringp += length; - iparams->argc++; + imgp->stringspace -= length; + imgp->stringp += length; + imgp->argc++; } } @@ -410,21 +414,21 @@ exec_extract_strings(iparams) * extract environment strings */ - envv = iparams->uap->envv; + envv = imgp->uap->envv; if (envv) { while ((envp = (caddr_t) fuword(envv++))) { if (envp == (caddr_t) -1) return (EFAULT); - if ((error = copyinstr(envp, iparams->stringp, - iparams->stringspace, &length))) { + if ((error = copyinstr(envp, imgp->stringp, + imgp->stringspace, &length))) { if (error == ENAMETOOLONG) return(E2BIG); return (error); } - iparams->stringspace -= length; - iparams->stringp += length; - iparams->envc++; + imgp->stringspace -= length; + imgp->stringp += length; + imgp->envc++; } } @@ -437,8 +441,8 @@ exec_extract_strings(iparams) * so that it can be used as the initial stack pointer. */ int * -exec_copyout_strings(iparams) - struct image_params *iparams; +exec_copyout_strings(imgp) + struct image_params *imgp; { int argc, envc; char **vectp; @@ -450,27 +454,27 @@ exec_copyout_strings(iparams) * Calculate string base and vector table pointers. */ arginfo = PS_STRINGS; - destp = (caddr_t)arginfo - roundup((ARG_MAX - iparams->stringspace), sizeof(char *)); + destp = (caddr_t)arginfo - 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 - - (iparams->argc + iparams->envc + 2) * sizeof(char *)); + (imgp->argc + imgp->envc + 2) * sizeof(char *)); /* * vectp also becomes our initial stack base */ stack_base = (int *)vectp; - stringp = iparams->stringbase; - argc = iparams->argc; - envc = iparams->envc; + stringp = imgp->stringbase; + argc = imgp->argc; + envc = imgp->envc; /* * Copy out strings - arguments and environment. */ - copyout(stringp, destp, ARG_MAX - iparams->stringspace); + copyout(stringp, destp, ARG_MAX - imgp->stringspace); /* * Fill in "ps_strings" struct for ps, w, etc. @@ -515,24 +519,24 @@ exec_copyout_strings(iparams) * Return 0 for success or error code on failure. */ static int -exec_check_permissions(iparams) - struct image_params *iparams; +exec_check_permissions(imgp) + struct image_params *imgp; { - struct proc *p = iparams->proc; - struct vnode *vnodep = iparams->vnodep; - struct vattr *attr = iparams->attr; + 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 (vnodep->v_writecount) { + if (vp->v_writecount) { return (ETXTBSY); } /* Get file attributes */ - error = VOP_GETATTR(vnodep, attr, p->p_ucred, p); + error = VOP_GETATTR(vp, attr, p->p_ucred, p); if (error) return (error); @@ -544,7 +548,7 @@ exec_check_permissions(iparams) * file really is executable. * 3) Insure that the file is a regular file. */ - if ((vnodep->v_mount->mnt_flag & MNT_NOEXEC) || + if ((vp->v_mount->mnt_flag & MNT_NOEXEC) || ((attr->va_mode & 0111) == 0) || (attr->va_type != VREG)) { return (EACCES); @@ -560,7 +564,7 @@ exec_check_permissions(iparams) * Disable setuid/setgid if the filesystem prohibits it or if * the process is being traced. */ - if ((vnodep->v_mount->mnt_flag & MNT_NOSUID) || (p->p_flag & P_TRACED)) + if ((vp->v_mount->mnt_flag & MNT_NOSUID) || (p->p_flag & P_TRACED)) attr->va_mode &= ~(VSUID | VSGID); /* @@ -568,11 +572,11 @@ exec_check_permissions(iparams) * Then call filesystem specific open routine (which does nothing * in the general case). */ - error = VOP_ACCESS(vnodep, VEXEC, p->p_ucred, p); + error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); if (error) return (error); - error = VOP_OPEN(vnodep, FREAD, p->p_ucred, p); + error = VOP_OPEN(vp, FREAD, p->p_ucred, p); if (error) return (error); |