diff options
author | kib <kib@FreeBSD.org> | 2007-07-03 17:46:37 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2007-07-03 17:46:37 +0000 |
commit | 764028016fb7c8690eca612fc2105107e23ed996 (patch) | |
tree | 55a187ec386c3dc03049b96e7265897c950251c9 /sys/kern | |
parent | a1bd6e4f521b174d396ccbdef6bd171a2e37d5ae (diff) | |
download | FreeBSD-src-764028016fb7c8690eca612fc2105107e23ed996.zip FreeBSD-src-764028016fb7c8690eca612fc2105107e23ed996.tar.gz |
Lock Giant and proctree lock around dereferencing p_session->s_ttyvp->v_rdev.
Lock cdev mutex too to close the race with tty being freed.
Relock clone_drain_lock to prevent the LOR with proctree lock, thus
add #include <fs/devfs/devfs_int.h>.
Suggested by: tegge
Debugging help and testing by: Peter Holm
Approved by: re (kensmith)
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/tty_tty.c | 14 |
1 files changed, 13 insertions, 1 deletions
diff --git a/sys/kern/tty_tty.c b/sys/kern/tty_tty.c index 8a04185..0b10f83 100644 --- a/sys/kern/tty_tty.c +++ b/sys/kern/tty_tty.c @@ -31,8 +31,12 @@ __FBSDID("$FreeBSD$"); #include <sys/conf.h> #include <sys/kernel.h> #include <sys/proc.h> +#include <sys/sx.h> #include <sys/vnode.h> +#include <fs/devfs/devfs.h> +#include <fs/devfs/devfs_int.h> + static d_open_t cttyopen; static struct cdevsw ctty_cdevsw = { @@ -60,6 +64,11 @@ ctty_clone(void *arg, struct ucred *cred, char *name, int namelen, return; if (strcmp(name, "tty")) return; + sx_sunlock(&clone_drain_lock); + mtx_lock(&Giant); + sx_slock(&proctree_lock); + sx_slock(&clone_drain_lock); + dev_lock(); if (!(curthread->td_proc->p_flag & P_CONTROLT)) *dev = ctty; else if (curthread->td_proc->p_session->s_ttyvp == NULL) @@ -70,7 +79,10 @@ ctty_clone(void *arg, struct ucred *cred, char *name, int namelen, *dev = ctty; } else *dev = curthread->td_proc->p_session->s_ttyvp->v_rdev; - dev_ref(*dev); + dev_refl(*dev); + dev_unlock(); + sx_sunlock(&proctree_lock); + mtx_unlock(&Giant); } static void |