diff options
| author | David Greenman <dg@FreeBSD.org> | 1996-06-04 02:11:37 +0000 | 
|---|---|---|
| committer | David Greenman <dg@FreeBSD.org> | 1996-06-04 02:11:37 +0000 | 
| commit | 1b7cb109d3888be4b0aa77aea9b683de24f59719 (patch) | |
| tree | da45028d30162fa35130c1ef72f68792678f8c99 | |
| parent | 49d406e6462e14b12ea7c8c8f51bcbb8552fde93 (diff) | |
Notes
| -rw-r--r-- | sys/kern/kern_exec.c | 216 | 
1 files changed, 104 insertions, 112 deletions
| diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index 08668808dd32..c3235137f4f1 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -23,7 +23,7 @@   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF   * SUCH DAMAGE.   * - *	$Id: kern_exec.c,v 1.21.4.4 1996/05/31 08:04:07 peter Exp $ + *	$Id: kern_exec.c,v 1.21.4.5 1996/06/03 04:09:36 davidg Exp $   */  #include <sys/param.h> @@ -32,7 +32,7 @@  #include <sys/kernel.h>  #include <sys/mount.h>  #include <sys/filedesc.h> -#include <sys/file.h> +#include <sys/fcntl.h>  #include <sys/acct.h>  #include <sys/exec.h>  #include <sys/imgact.h> @@ -75,40 +75,35 @@ 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, -	    ARG_MAX, TRUE); -	if (error) { -		log(LOG_WARNING, "execve: failed to allocate string space\n"); -		return (error); -	} - -	if (!iparams->stringbase) { +	imgp->stringbase = (char *)kmem_alloc_wait(exec_map, ARG_MAX); +	if (imgp->stringbase == NULL) {  		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 @@ -122,14 +117,12 @@ interpret:  	error = namei(ndp);  	if (error) { -		vm_map_remove(exec_map, (vm_offset_t)iparams->stringbase, -		    (vm_offset_t)iparams->stringbase + ARG_MAX); +		kmem_free_wakeup(exec_map, (vm_offset_t)imgp->stringbase, ARG_MAX);  		goto exec_fail;  	} -	iparams->vnodep = vnodep = ndp->ni_vp; - -	if (vnodep == NULL) { +	imgp->vnodep = ndp->ni_vp; +	if (imgp->vnodep == NULL) {  		error = ENOEXEC;  		goto exec_fail_dealloc;  	} @@ -137,13 +130,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->vnodep);  	if (error)  		goto exec_fail_dealloc; @@ -153,18 +146,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->vnodep,		/* 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. @@ -176,7 +168,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; @@ -184,17 +176,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; @@ -208,7 +200,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;  	/* @@ -217,9 +209,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); @@ -242,32 +234,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; @@ -291,16 +287,14 @@ 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)) -		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)) +	kmem_free_wakeup(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); @@ -308,20 +302,18 @@ 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)) -			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->stringbase != NULL) +		kmem_free_wakeup(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 (iparams->vmspace_destroyed) { +	if (imgp->vmspace_destroyed) {  		/* sorry, no more process anymore. exit gracefully */  		exit1(p, W_EXITCODE(0, SIGABRT));  		/* NOT REACHED */ @@ -337,19 +329,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); @@ -372,8 +364,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; @@ -383,21 +375,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++;  		}  	} @@ -405,21 +397,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++;  		}  	} @@ -432,8 +424,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; @@ -446,28 +438,28 @@ exec_copyout_strings(iparams)  	 */  	arginfo = PS_STRINGS;  	destp =	(caddr_t)arginfo - SPARE_USRSPACE - -		roundup((ARG_MAX - iparams->stringspace), sizeof(char *)); +		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. @@ -512,24 +504,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->vnodep; +	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); @@ -541,7 +533,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); @@ -557,7 +549,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);  	/* @@ -565,11 +557,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); | 
