svn commit: r274000 - head/sys/fs/devfs
Mateusz Guzik
mjg at FreeBSD.org
Mon Nov 3 03:12:16 UTC 2014
Author: mjg
Date: Mon Nov 3 03:12:15 2014
New Revision: 274000
URL: https://svnweb.freebsd.org/changeset/base/274000
Log:
Fix up some session-related races in devfs.
One was introduced with r272596, the rest was there to begin with.
Noted by: jhb
Modified:
head/sys/fs/devfs/devfs_vnops.c
Modified: head/sys/fs/devfs/devfs_vnops.c
==============================================================================
--- head/sys/fs/devfs/devfs_vnops.c Mon Nov 3 00:37:39 2014 (r273999)
+++ head/sys/fs/devfs/devfs_vnops.c Mon Nov 3 03:12:15 2014 (r274000)
@@ -499,6 +499,7 @@ devfs_access(struct vop_access_args *ap)
{
struct vnode *vp = ap->a_vp;
struct devfs_dirent *de;
+ struct proc *p;
int error;
de = vp->v_data;
@@ -511,11 +512,16 @@ devfs_access(struct vop_access_args *ap)
return (0);
if (error != EACCES)
return (error);
+ p = ap->a_td->td_proc;
/* We do, however, allow access to the controlling terminal */
- if (!(ap->a_td->td_proc->p_flag & P_CONTROLT))
+ PROC_LOCK(p);
+ if (!(p->p_flag & P_CONTROLT)) {
+ PROC_UNLOCK(p);
return (error);
- if (ap->a_td->td_proc->p_session->s_ttydp == de->de_cdp)
- return (0);
+ }
+ if (p->p_session->s_ttydp == de->de_cdp)
+ error = 0;
+ PROC_UNLOCK(p);
return (error);
}
@@ -525,6 +531,7 @@ devfs_close(struct vop_close_args *ap)
{
struct vnode *vp = ap->a_vp, *oldvp;
struct thread *td = ap->a_td;
+ struct proc *p;
struct cdev *dev = vp->v_rdev;
struct cdevsw *dsw;
int vp_locked, error, ref;
@@ -545,24 +552,30 @@ devfs_close(struct vop_close_args *ap)
* if the reference count is 2 (this last descriptor
* plus the session), release the reference from the session.
*/
- if (td && vp == td->td_proc->p_session->s_ttyvp) {
- oldvp = NULL;
- sx_xlock(&proctree_lock);
- if (vp == td->td_proc->p_session->s_ttyvp) {
- SESS_LOCK(td->td_proc->p_session);
- VI_LOCK(vp);
- if (count_dev(dev) == 2 &&
- (vp->v_iflag & VI_DOOMED) == 0) {
- td->td_proc->p_session->s_ttyvp = NULL;
- td->td_proc->p_session->s_ttydp = NULL;
- oldvp = vp;
+ if (td != NULL) {
+ p = td->td_proc;
+ PROC_LOCK(p);
+ if (vp == p->p_session->s_ttyvp) {
+ PROC_UNLOCK(p);
+ oldvp = NULL;
+ sx_xlock(&proctree_lock);
+ if (vp == p->p_session->s_ttyvp) {
+ SESS_LOCK(p->p_session);
+ VI_LOCK(vp);
+ if (count_dev(dev) == 2 &&
+ (vp->v_iflag & VI_DOOMED) == 0) {
+ p->p_session->s_ttyvp = NULL;
+ p->p_session->s_ttydp = NULL;
+ oldvp = vp;
+ }
+ VI_UNLOCK(vp);
+ SESS_UNLOCK(p->p_session);
}
- VI_UNLOCK(vp);
- SESS_UNLOCK(td->td_proc->p_session);
- }
- sx_xunlock(&proctree_lock);
- if (oldvp != NULL)
- vrele(oldvp);
+ sx_xunlock(&proctree_lock);
+ if (oldvp != NULL)
+ vrele(oldvp);
+ } else
+ PROC_UNLOCK(p);
}
/*
* We do not want to really close the device if it
@@ -816,6 +829,7 @@ devfs_prison_check(struct devfs_dirent *
{
struct cdev_priv *cdp;
struct ucred *dcr;
+ struct proc *p;
int error;
cdp = de->de_cdp;
@@ -829,10 +843,15 @@ devfs_prison_check(struct devfs_dirent *
if (error == 0)
return (0);
/* We do, however, allow access to the controlling terminal */
- if (!(td->td_proc->p_flag & P_CONTROLT))
+ p = td->td_proc;
+ PROC_LOCK(p);
+ if (!(p->p_flag & P_CONTROLT)) {
+ PROC_UNLOCK(p);
return (error);
- if (td->td_proc->p_session->s_ttydp == cdp)
- return (0);
+ }
+ if (p->p_session->s_ttydp == cdp)
+ error = 0;
+ PROC_UNLOCK(p);
return (error);
}
More information about the svn-src-all
mailing list