summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_exec.c
diff options
context:
space:
mode:
authordg <dg@FreeBSD.org>1995-11-06 12:52:37 +0000
committerdg <dg@FreeBSD.org>1995-11-06 12:52:37 +0000
commitb0e92e3fe4280bcb3c077c4b792fd4b49023a90e (patch)
treeb1085bc2d506b9f9ebbc0763719203202ce8d6a6 /sys/kern/kern_exec.c
parent70e33173922ad4e39017ab578a3fe083ecc6b794 (diff)
downloadFreeBSD-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.c210
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);
OpenPOWER on IntegriCloud