diff options
Diffstat (limited to 'drivers/tty/tty_jobctrl.c')
-rw-r--r-- | drivers/tty/tty_jobctrl.c | 30 |
1 files changed, 20 insertions, 10 deletions
diff --git a/drivers/tty/tty_jobctrl.c b/drivers/tty/tty_jobctrl.c index 4b751b9285ad..7813dc910a19 100644 --- a/drivers/tty/tty_jobctrl.c +++ b/drivers/tty/tty_jobctrl.c @@ -11,6 +11,7 @@ #include <linux/tty.h> #include <linux/fcntl.h> #include <linux/uaccess.h> +#include "tty.h" static int is_ignored(int sig) { @@ -75,6 +76,7 @@ void proc_clear_tty(struct task_struct *p) { unsigned long flags; struct tty_struct *tty; + spin_lock_irqsave(&p->sighand->siglock, flags); tty = p->signal->tty; p->signal->tty = NULL; @@ -173,6 +175,7 @@ EXPORT_SYMBOL_GPL(get_current_tty); void session_clear_tty(struct pid *session) { struct task_struct *p; + do_each_pid_task(session, PIDTYPE_SID, p) { proc_clear_tty(p); } while_each_pid_task(session, PIDTYPE_SID, p); @@ -202,8 +205,10 @@ int tty_signal_session_leader(struct tty_struct *tty, int exit_session) spin_lock_irq(&p->sighand->siglock); if (p->signal->tty == tty) { p->signal->tty = NULL; - /* We defer the dereferences outside fo - the tasklist lock */ + /* + * We defer the dereferences outside of + * the tasklist lock. + */ refs++; } if (!p->signal->leader) { @@ -240,10 +245,10 @@ int tty_signal_session_leader(struct tty_struct *tty, int exit_session) * it wants to disassociate itself from its controlling tty. * * It performs the following functions: - * (1) Sends a SIGHUP and SIGCONT to the foreground process group - * (2) Clears the tty from being controlling the session - * (3) Clears the controlling tty for all processes in the - * session group. + * (1) Sends a SIGHUP and SIGCONT to the foreground process group + * (2) Clears the tty from being controlling the session + * (3) Clears the controlling tty for all processes in the + * session group. * * The argument on_exit is set to 1 if called when a process is * exiting; it is 0 if called by the ioctl TIOCNOTTY. @@ -269,6 +274,7 @@ void disassociate_ctty(int on_exit) tty_vhangup_session(tty); } else { struct pid *tty_pgrp = tty_get_pgrp(tty); + if (tty_pgrp) { kill_pgrp(tty_pgrp, SIGHUP, on_exit); if (!on_exit) @@ -280,6 +286,7 @@ void disassociate_ctty(int on_exit) } else if (on_exit) { struct pid *old_pgrp; + spin_lock_irq(¤t->sighand->siglock); old_pgrp = current->signal->tty_old_pgrp; current->signal->tty_old_pgrp = NULL; @@ -324,10 +331,13 @@ void disassociate_ctty(int on_exit) */ void no_tty(void) { - /* FIXME: Review locking here. The tty_lock never covered any race - between a new association and proc_clear_tty but possible we need - to protect against this anyway */ + /* + * FIXME: Review locking here. The tty_lock never covered any race + * between a new association and proc_clear_tty but possibly we need + * to protect against this anyway. + */ struct task_struct *tsk = current; + disassociate_ctty(0); proc_clear_tty(tsk); } @@ -531,7 +541,7 @@ static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t _ /* * (tty == real_tty) is a cheap way of * testing if the tty is NOT a master pty. - */ + */ if (tty == real_tty && current->signal->tty != real_tty) return -ENOTTY; |