From f03e89de68bb0d72b655db4c40d4e35ef74c169b Mon Sep 17 00:00:00 2001 From: Alfred Perlstein Date: Sun, 11 Nov 2001 22:39:07 +0000 Subject: [PATCH] turn vn_open() into a wrapper around vn_open_cred() which allows one to perform a vn_open using temporary/other/fake credentials. Modify the nfs client side locking code to use vn_open_cred() passing proc0's ucred instead of the old way which was to temporary raise privs while running vn_open(). This should close the race hopefully. --- sys/kern/vfs_vnops.c | 14 ++++++++++++-- sys/nfsclient/nfs_lock.c | 16 +--------------- sys/sys/vnode.h | 2 ++ 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index 70d84a68059..84c3ae1911b 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -75,6 +75,16 @@ struct fileops vnops = { vn_statfile, vn_closefile }; +int +vn_open(ndp, flagp, cmode) + register struct nameidata *ndp; + int *flagp, cmode; +{ + struct thread *td = ndp->ni_cnd.cn_thread; + + return (vn_open_cred(ndp, flagp, cmode, td->td_proc->p_ucred)); +} + /* * Common code for vnode open operations. * Check permissions, and call the VOP_OPEN or VOP_CREATE routine. @@ -83,14 +93,14 @@ struct fileops vnops = { * due to the NDINIT being done elsewhere. */ int -vn_open(ndp, flagp, cmode) +vn_open_cred(ndp, flagp, cmode, cred) register struct nameidata *ndp; int *flagp, cmode; + struct ucred *cred; { struct vnode *vp; struct mount *mp; struct thread *td = ndp->ni_cnd.cn_thread; - struct ucred *cred = td->td_proc->p_ucred; struct vattr vat; struct vattr *vap = &vat; int mode, fmode, error; diff --git a/sys/nfsclient/nfs_lock.c b/sys/nfsclient/nfs_lock.c index f8ebb095c2c..dee4b6830e6 100644 --- a/sys/nfsclient/nfs_lock.c +++ b/sys/nfsclient/nfs_lock.c @@ -83,7 +83,6 @@ nfs_dolock(struct vop_advlock_args *ap) LOCKD_MSG msg; struct nameidata nd; struct thread *td; - uid_t saved_uid; struct vnode *vp, *wvp; int error, error1; struct flock *fl; @@ -156,21 +155,8 @@ nfs_dolock(struct vop_advlock_args *ap) */ NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, _PATH_LCKFIFO, td); - /* - * XXX Hack to temporarily allow this process (regardless of it's creds) - * to open the fifo we need to write to. vn_open() really should - * take a ucred (and once it does, this code should be fixed to use - * proc0's ucred. - * - * XXX: This introduces an exploitable race condition allowing - * a local attacker to gain root privilege. - */ - saved_uid = p->p_ucred->cr_uid; - p->p_ucred->cr_uid = 0; /* temporarly run the vn_open as root */ - fmode = FFLAGS(O_WRONLY); - error = vn_open(&nd, &fmode, 0); - p->p_ucred->cr_uid = saved_uid; + error = vn_open_cred(&nd, &fmode, 0, proc0.p_ucred); if (error != 0) { return (error == ENOENT ? EOPNOTSUPP : error); } diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index 9861f8ed667..4fc0c15d9c9 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -608,6 +608,8 @@ int debug_vn_lock __P((struct vnode *vp, int flags, struct thread *p, #endif int vn_mkdir __P((char *path, int mode, enum uio_seg segflg, struct thread *td)); int vn_open __P((struct nameidata *ndp, int *flagp, int cmode)); +int vn_open_cred __P((struct nameidata *ndp, int *flagp, int cmode, + struct ucred *cred)); void vn_pollevent __P((struct vnode *vp, int events)); void vn_pollgone __P((struct vnode *vp)); int vn_pollrecord __P((struct vnode *vp, struct thread *p, int events));