aboutsummaryrefslogtreecommitdiff
path: root/sys/fs/devfs
diff options
context:
space:
mode:
authorMateusz Guzik <mjg@FreeBSD.org>2020-07-04 06:27:28 +0000
committerMateusz Guzik <mjg@FreeBSD.org>2020-07-04 06:27:28 +0000
commit11c345b18f0005e709111e7544372be0aa80441a (patch)
tree4cf6997e7277bdf48f6606d0c15c3a1e93ac945e /sys/fs/devfs
parentd6d9ddd41f9ae8986dc7a12af776edce44fe3863 (diff)
downloadsrc-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.c17
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);