diff options
author | Mateusz Guzik <mjg@FreeBSD.org> | 2020-07-04 06:27:28 +0000 |
---|---|---|
committer | Mateusz Guzik <mjg@FreeBSD.org> | 2020-07-04 06:27:28 +0000 |
commit | 11c345b18f0005e709111e7544372be0aa80441a (patch) | |
tree | 4cf6997e7277bdf48f6606d0c15c3a1e93ac945e /sys/fs/devfs | |
parent | d6d9ddd41f9ae8986dc7a12af776edce44fe3863 (diff) | |
download | src-11c345b18f0005e709111e7544372be0aa80441a.tar.gz src-11c345b18f0005e709111e7544372be0aa80441a.zip |
devfs: fix a vnode use-after-free in devfs_ioctl
The vnode to be replaced was read with a shared lock, meaning 2 racing threads
can find the same one.
While here clean it up a little bit.
Notes
Notes:
svn path=/head/; revision=362923
Diffstat (limited to 'sys/fs/devfs')
-rw-r--r-- | sys/fs/devfs/devfs_vnops.c | 17 |
1 files changed, 9 insertions, 8 deletions
diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c index e7e524d2f0b9..c21c1128543e 100644 --- a/sys/fs/devfs/devfs_vnops.c +++ b/sys/fs/devfs/devfs_vnops.c @@ -787,6 +787,7 @@ devfs_ioctl(struct vop_ioctl_args *ap) struct vnode *vpold, *vp; struct cdevsw *dsw; struct thread *td; + struct session *sess; struct cdev *dev; int error, ref, i; const char *p; @@ -836,18 +837,18 @@ devfs_ioctl(struct vop_ioctl_args *ap) * nothing left to do. */ sx_slock(&proctree_lock); - if (td->td_proc->p_session->s_ttyvp == vp || - td->td_proc->p_session->s_ttyp == NULL) { + sess = td->td_proc->p_session; + if (sess->s_ttyvp == vp || sess->s_ttyp == NULL) { sx_sunlock(&proctree_lock); return (0); } - vpold = td->td_proc->p_session->s_ttyvp; - VREF(vp); - SESS_LOCK(td->td_proc->p_session); - td->td_proc->p_session->s_ttyvp = vp; - td->td_proc->p_session->s_ttydp = cdev2priv(dev); - SESS_UNLOCK(td->td_proc->p_session); + vrefact(vp); + SESS_LOCK(sess); + vpold = sess->s_ttyvp; + sess->s_ttyvp = vp; + sess->s_ttydp = cdev2priv(dev); + SESS_UNLOCK(sess); sx_sunlock(&proctree_lock); |