summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Cox <alan@redhat.com>2008-10-13 10:40:30 +0100
committerLinus Torvalds <torvalds@linux-foundation.org>2008-10-13 09:51:41 -0700
commit2cb5998b5f0ccc886fdda3509059eef297b49577 (patch)
tree9113731d3f892c2e164bfd05a7cf1a4b1713a619
parent216ba023a96c04e8d3aabf83d5931c35b6e2dbbb (diff)
tty: the vhangup syscall is racy
We now have the infrastructure to sort this out but rather than teaching the syscall tty lock rules we move the hard work into a tty helper Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/char/tty_io.c19
-rw-r--r--fs/open.c3
-rw-r--r--include/linux/tty.h1
3 files changed, 21 insertions, 2 deletions
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 913b50258f90..b5f57d0b30ee 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -730,6 +730,25 @@ void tty_vhangup(struct tty_struct *tty)
EXPORT_SYMBOL(tty_vhangup);
/**
+ * tty_vhangup_self - process vhangup for own ctty
+ *
+ * Perform a vhangup on the current controlling tty
+ */
+
+void tty_vhangup_self(void)
+{
+ struct tty_struct *tty;
+
+ mutex_lock(&tty_mutex);
+ tty = get_current_tty();
+ if (tty) {
+ tty_vhangup(tty);
+ tty_kref_put(tty);
+ }
+ mutex_unlock(&tty_mutex);
+}
+
+/**
* tty_hung_up_p - was tty hung up
* @filp: file pointer of tty
*
diff --git a/fs/open.c b/fs/open.c
index 07da9359481c..5596049863bf 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -1141,8 +1141,7 @@ EXPORT_SYMBOL(sys_close);
asmlinkage long sys_vhangup(void)
{
if (capable(CAP_SYS_TTY_CONFIG)) {
- /* XXX: this needs locking */
- tty_vhangup(current->signal->tty);
+ tty_vhangup_self();
return 0;
}
return -EPERM;
diff --git a/include/linux/tty.h b/include/linux/tty.h
index c30ed8d3bcbd..e00393a3d1c9 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -361,6 +361,7 @@ extern int is_ignored(int sig);
extern int tty_signal(int sig, struct tty_struct *tty);
extern void tty_hangup(struct tty_struct *tty);
extern void tty_vhangup(struct tty_struct *tty);
+extern void tty_vhangup_self(void);
extern void tty_unhangup(struct file *filp);
extern int tty_hung_up_p(struct file *filp);
extern void do_SAK(struct tty_struct *tty);