Fix up some session-related races in devfs.
One was introduced with r272596, the rest was there to begin with. Noted by: jhb
This commit is contained in:
parent
90a2b12f5f
commit
5c258fe4b9
@ -499,6 +499,7 @@ devfs_access(struct vop_access_args *ap)
|
|||||||
{
|
{
|
||||||
struct vnode *vp = ap->a_vp;
|
struct vnode *vp = ap->a_vp;
|
||||||
struct devfs_dirent *de;
|
struct devfs_dirent *de;
|
||||||
|
struct proc *p;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
de = vp->v_data;
|
de = vp->v_data;
|
||||||
@ -511,11 +512,16 @@ devfs_access(struct vop_access_args *ap)
|
|||||||
return (0);
|
return (0);
|
||||||
if (error != EACCES)
|
if (error != EACCES)
|
||||||
return (error);
|
return (error);
|
||||||
|
p = ap->a_td->td_proc;
|
||||||
/* We do, however, allow access to the controlling terminal */
|
/* 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);
|
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);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -525,6 +531,7 @@ devfs_close(struct vop_close_args *ap)
|
|||||||
{
|
{
|
||||||
struct vnode *vp = ap->a_vp, *oldvp;
|
struct vnode *vp = ap->a_vp, *oldvp;
|
||||||
struct thread *td = ap->a_td;
|
struct thread *td = ap->a_td;
|
||||||
|
struct proc *p;
|
||||||
struct cdev *dev = vp->v_rdev;
|
struct cdev *dev = vp->v_rdev;
|
||||||
struct cdevsw *dsw;
|
struct cdevsw *dsw;
|
||||||
int vp_locked, error, ref;
|
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
|
* if the reference count is 2 (this last descriptor
|
||||||
* plus the session), release the reference from the session.
|
* plus the session), release the reference from the session.
|
||||||
*/
|
*/
|
||||||
if (td && vp == td->td_proc->p_session->s_ttyvp) {
|
if (td != NULL) {
|
||||||
oldvp = NULL;
|
p = td->td_proc;
|
||||||
sx_xlock(&proctree_lock);
|
PROC_LOCK(p);
|
||||||
if (vp == td->td_proc->p_session->s_ttyvp) {
|
if (vp == p->p_session->s_ttyvp) {
|
||||||
SESS_LOCK(td->td_proc->p_session);
|
PROC_UNLOCK(p);
|
||||||
VI_LOCK(vp);
|
oldvp = NULL;
|
||||||
if (count_dev(dev) == 2 &&
|
sx_xlock(&proctree_lock);
|
||||||
(vp->v_iflag & VI_DOOMED) == 0) {
|
if (vp == p->p_session->s_ttyvp) {
|
||||||
td->td_proc->p_session->s_ttyvp = NULL;
|
SESS_LOCK(p->p_session);
|
||||||
td->td_proc->p_session->s_ttydp = NULL;
|
VI_LOCK(vp);
|
||||||
oldvp = 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);
|
sx_xunlock(&proctree_lock);
|
||||||
SESS_UNLOCK(td->td_proc->p_session);
|
if (oldvp != NULL)
|
||||||
}
|
vrele(oldvp);
|
||||||
sx_xunlock(&proctree_lock);
|
} else
|
||||||
if (oldvp != NULL)
|
PROC_UNLOCK(p);
|
||||||
vrele(oldvp);
|
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* We do not want to really close the device if it
|
* We do not want to really close the device if it
|
||||||
@ -816,6 +829,7 @@ devfs_prison_check(struct devfs_dirent *de, struct thread *td)
|
|||||||
{
|
{
|
||||||
struct cdev_priv *cdp;
|
struct cdev_priv *cdp;
|
||||||
struct ucred *dcr;
|
struct ucred *dcr;
|
||||||
|
struct proc *p;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
cdp = de->de_cdp;
|
cdp = de->de_cdp;
|
||||||
@ -829,10 +843,15 @@ devfs_prison_check(struct devfs_dirent *de, struct thread *td)
|
|||||||
if (error == 0)
|
if (error == 0)
|
||||||
return (0);
|
return (0);
|
||||||
/* We do, however, allow access to the controlling terminal */
|
/* 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);
|
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);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user