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.
This commit is contained in:
parent
81f645ca10
commit
f03e89de68
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=86278
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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));
|
||||
|
Loading…
Reference in New Issue
Block a user