exec vnode locking protocol changes: in a nutshell, don't keep vnodes

locked for any longer than we have to.
This commit is contained in:
cgd 1996-09-30 23:18:43 +00:00
parent 6f5b5cefc7
commit 3b34cba879
4 changed files with 59 additions and 31 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: exec_elf32.c,v 1.11 1996/09/30 23:02:14 cgd Exp $ */
/* $NetBSD: exec_elf32.c,v 1.12 1996/09/30 23:18:43 cgd Exp $ */
/*
* Copyright (c) 1996 Christopher G. Demetriou
@ -304,7 +304,7 @@ ELFNAME(read_from)(p, vp, off, buf, size)
int resid;
if ((error = vn_rdwr(UIO_READ, vp, buf, size,
off, UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred,
off, UIO_SYSSPACE, 0, p->p_ucred,
&resid, p)) != 0)
return error;
/*
@ -345,10 +345,17 @@ ELFNAME(load_file)(p, path, vcset, entry, ap, last)
* 2. read filehdr
* 3. map text, data, and bss out of it using VM_*
*/
NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, path, p);
if ((error = namei(&nd)) != 0) {
NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, path, p);
if ((error = namei(&nd)) != 0)
return error;
}
#ifdef notyet /* XXX cgd 960926 */
XXX cgd 960926: check vnode type
XXX cgd 960926: check mount point for MNT_NOEXEC
XXX cgd 960926: check VOP_ACCESS on it.
XXX cgd 960926: (maybe) VOP_OPEN it (and VOP_CLOSE in copyargs?)
#endif
VOP_UNLOCK(nd.ni_vp);
if ((error = ELFNAME(read_from)(p, nd.ni_vp, 0, (caddr_t) &eh,
sizeof(eh))) != 0)
goto bad;
@ -393,11 +400,17 @@ ELFNAME(load_file)(p, path, vcset, entry, ap, last)
}
}
free((char *) ph, M_TEMP);
*last = addr;
vrele(nd.ni_vp);
return 0;
bad:
if (ph != NULL)
free((char *) ph, M_TEMP);
*last = addr;
#ifdef notyet /* XXX cgd 960926 */
(maybe) VOP_CLOSE it
#endif
vrele(nd.ni_vp);
return error;
}

View File

@ -1,7 +1,7 @@
/* $NetBSD: exec_script.c,v 1.13 1996/02/04 02:15:06 christos Exp $ */
/* $NetBSD: exec_script.c,v 1.14 1996/09/30 23:18:44 cgd Exp $ */
/*
* Copyright (c) 1993, 1994 Christopher G. Demetriou
* Copyright (c) 1993, 1994, 1996 Christopher G. Demetriou
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -159,7 +159,10 @@ check_shell:
* close all open fd's when the start. That kills this
* method of implementing "safe" set-id and x-only scripts.
*/
if (VOP_ACCESS(epp->ep_vp, VREAD, p->p_ucred, p) == EACCES
VOP_LOCK(epp->ep_vp);
error = VOP_ACCESS(epp->ep_vp, VREAD, p->p_ucred, p);
VOP_UNLOCK(epp->ep_vp);
if (error == EACCES
#ifdef SETUIDSCRIPTS
|| script_sbits
#endif
@ -227,8 +230,6 @@ check_shell:
scriptvp = epp->ep_vp;
oldpnbuf = epp->ep_ndp->ni_cnd.cn_pnbuf;
VOP_UNLOCK(scriptvp);
if ((error = check_exec(p, epp)) == 0) {
/* note that we've clobbered the header */
epp->ep_flags |= EXEC_DESTR;
@ -239,8 +240,10 @@ check_shell:
* Also, set things up so that the fake args
* list will be used.
*/
if ((epp->ep_flags & EXEC_HASFD) == 0)
vn_close(scriptvp, FREAD, p->p_ucred, p);
if ((epp->ep_flags & EXEC_HASFD) == 0) {
VOP_CLOSE(scriptvp, FREAD, p->p_ucred, p);
vrele(scriptvp);
}
/* free the old pathname buffer */
FREE(oldpnbuf, M_NAMEI);
@ -273,8 +276,10 @@ fail:
if (epp->ep_flags & EXEC_HASFD) {
epp->ep_flags &= ~EXEC_HASFD;
(void) fdrelease(p, epp->ep_fd);
} else
vn_close(scriptvp, FREAD, p->p_ucred, p);
} else {
VOP_CLOSE(scriptvp, FREAD, p->p_ucred, p);
vrele(scriptvp);
}
FREE(epp->ep_ndp->ni_cnd.cn_pnbuf, M_NAMEI);

View File

@ -1,7 +1,7 @@
/* $NetBSD: exec_subr.c,v 1.9 1994/12/04 03:10:42 mycroft Exp $ */
/* $NetBSD: exec_subr.c,v 1.10 1996/09/30 23:18:45 cgd Exp $ */
/*
* Copyright (c) 1993, 1994 Christopher G. Demetriou
* Copyright (c) 1993, 1994, 1996 Christopher G. Demetriou
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -41,6 +41,11 @@
#include <vm/vm.h>
/*
* XXX cgd 960926: this module should collect simple statistics
* (calls, extends, kills).
*/
#ifdef DEBUG
/*
* new_vmcmd():
@ -164,7 +169,7 @@ vmcmd_map_readvn(p, cmd)
return error;
error = vn_rdwr(UIO_READ, cmd->ev_vp, (caddr_t)cmd->ev_addr,
cmd->ev_len, cmd->ev_offset, UIO_USERSPACE, IO_UNIT|IO_NODELOCKED,
cmd->ev_len, cmd->ev_offset, UIO_USERSPACE, IO_UNIT,
p->p_ucred, (int *)0, p);
if (error)
return error;

View File

@ -1,7 +1,7 @@
/* $NetBSD: kern_exec.c,v 1.76 1996/09/26 23:34:47 cgd Exp $ */
/* $NetBSD: kern_exec.c,v 1.77 1996/09/30 23:18:46 cgd Exp $ */
/*-
* Copyright (C) 1993, 1994 Christopher G. Demetriou
* Copyright (C) 1993, 1994, 1996 Christopher G. Demetriou
* Copyright (C) 1992 Wolfgang Solfrank.
* Copyright (C) 1992 TooLs GmbH.
* All rights reserved.
@ -74,17 +74,17 @@
*
* ON EXIT:
* error: nothing held, etc. exec header still allocated.
* ok: filled exec package, executable's vnode (locked).
* ok: filled exec package, executable's vnode (unlocked).
*
* EXEC SWITCH ENTRY:
* Locked vnode to check, exec package, proc.
*
* EXEC SWITCH EXIT:
* ok: return 0, filled exec package, executable's vnode (locked).
* ok: return 0, filled exec package, executable's vnode (unlocked).
* error: destructive:
* everything deallocated execept exec header.
* non-destructive:
* error code, executable's vnode (locked),
* error code, executable's vnode (unlocked),
* exec header unmodified.
*/
int
@ -135,9 +135,12 @@ check_exec(p, epp)
if ((error = VOP_OPEN(vp, FREAD, p->p_ucred, p)) != 0)
goto bad1;
/* unlock vp, since we don't need it locked from here on out. */
VOP_UNLOCK(vp);
/* now we have the file, get the exec header */
error = vn_rdwr(UIO_READ, vp, epp->ep_hdr, epp->ep_hdrlen, 0,
UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p);
UIO_SYSSPACE, 0, p->p_ucred, &resid, p);
if (error)
goto bad2;
epp->ep_hdrvalid = epp->ep_hdrlen - resid;
@ -185,8 +188,8 @@ bad2:
* unlock and close the vnode, restore the old one, free the
* pathname buf, and punt.
*/
VOP_UNLOCK(vp);
vn_close(vp, FREAD, p->p_ucred, p);
VOP_CLOSE(vp, FREAD, p->p_ucred, p);
vrele(vp);
FREE(ndp->ni_cnd.cn_pnbuf, M_NAMEI);
return error;
@ -195,8 +198,8 @@ bad1:
* free the namei pathname buffer, and put the vnode
* (which we don't yet have open).
*/
vput(vp); /* was still locked */
FREE(ndp->ni_cnd.cn_pnbuf, M_NAMEI);
vput(vp);
return error;
}
@ -244,6 +247,7 @@ sys_execve(p, v, retval)
}
/* init the namei data to point the file user's program name */
/* XXX cgd 960926: why do this here? most will be clobbered. */
NDINIT(&nid, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
/*
@ -359,6 +363,7 @@ sys_execve(p, v, retval)
pack.ep_ssize = len; /* maybe should go elsewhere, but... */
/* Unmap old program */
/* XXX cgd 960926: the sparc #ifdef should be a MD hook */
#ifdef sparc
kill_user_windows(p); /* before stack addresses go away */
#endif
@ -469,7 +474,7 @@ sys_execve(p, v, retval)
FREE(nid.ni_cnd.cn_pnbuf, M_NAMEI);
VOP_CLOSE(pack.ep_vp, FREAD, cred, p);
vput(pack.ep_vp);
vrele(pack.ep_vp);
/* setup new registers and do misc. setup. */
(*pack.ep_emul->e_setregs)(p, &pack, (u_long) stack, retval);
@ -496,7 +501,7 @@ bad:
}
/* close and put the exec'd file */
VOP_CLOSE(pack.ep_vp, FREAD, cred, p);
vput(pack.ep_vp);
vrele(pack.ep_vp);
FREE(nid.ni_cnd.cn_pnbuf, M_NAMEI);
kmem_free_wakeup(exec_map, (vm_offset_t) argp, NCARGS);
@ -516,7 +521,7 @@ exec_abort:
FREE(pack.ep_emul_arg, M_TEMP);
FREE(nid.ni_cnd.cn_pnbuf, M_NAMEI);
VOP_CLOSE(pack.ep_vp, FREAD, cred, p);
vput(pack.ep_vp);
vrele(pack.ep_vp);
kmem_free_wakeup(exec_map, (vm_offset_t) argp, NCARGS);
FREE(pack.ep_hdr, M_EXEC);
exit1(p, W_EXITCODE(0, SIGABRT));