aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/tty_io.c
diff options
context:
space:
mode:
authorPeter Hurley <peter@hurleysoftware.com>2013-03-06 07:20:56 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-03-15 17:02:32 -0400
commitf91e2590410bd992e3f065d17c55329bdaa51b1d (patch)
tree9f815911a08f725c05c5f30c83e60d900fb1ba9a /drivers/tty/tty_io.c
parentbc30c3b23bb953fc6eb59e7ac6ecb48d92962bb0 (diff)
tty: Signal foreground group processes in hangup
When the session leader is exiting, signal the foreground group processes as part of the hangup sequence, instead of after the hangup is complete. This prepares for hanging up the line discipline _after_ signalling processes which may be blocking on ldisc i/o. Parameterize __tty_hangup() to distinguish between when the session leader is exiting and all other hangups; signal the foreground group after signalling the session leader and its process group, which preserves the original signal order. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Acked-by: Jiri Slaby <jslaby@suse.cz> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/tty_io.c')
-rw-r--r--drivers/tty/tty_io.c65
1 files changed, 48 insertions, 17 deletions
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 2661e86a2272..3feca406dc36 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -534,18 +534,21 @@ EXPORT_SYMBOL_GPL(tty_wakeup);
534 534
535/** 535/**
536 * tty_signal_session_leader - sends SIGHUP to session leader 536 * tty_signal_session_leader - sends SIGHUP to session leader
537 * @tty controlling tty
538 * @exit_session if non-zero, signal all foreground group processes
537 * 539 *
538 * Send SIGHUP and SIGCONT to the session leader and its 540 * Send SIGHUP and SIGCONT to the session leader and its process group.
539 * process group. 541 * Optionally, signal all processes in the foreground process group.
540 * 542 *
541 * Returns the number of processes in the session with this tty 543 * Returns the number of processes in the session with this tty
542 * as their controlling terminal. This value is used to drop 544 * as their controlling terminal. This value is used to drop
543 * tty references for those processes. 545 * tty references for those processes.
544 */ 546 */
545static int tty_signal_session_leader(struct tty_struct *tty) 547static int tty_signal_session_leader(struct tty_struct *tty, int exit_session)
546{ 548{
547 struct task_struct *p; 549 struct task_struct *p;
548 int refs = 0; 550 int refs = 0;
551 struct pid *tty_pgrp = NULL;
549 552
550 read_lock(&tasklist_lock); 553 read_lock(&tasklist_lock);
551 if (tty->session) { 554 if (tty->session) {
@@ -565,6 +568,7 @@ static int tty_signal_session_leader(struct tty_struct *tty)
565 __group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p); 568 __group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p);
566 put_pid(p->signal->tty_old_pgrp); /* A noop */ 569 put_pid(p->signal->tty_old_pgrp); /* A noop */
567 spin_lock(&tty->ctrl_lock); 570 spin_lock(&tty->ctrl_lock);
571 tty_pgrp = get_pid(tty->pgrp);
568 if (tty->pgrp) 572 if (tty->pgrp)
569 p->signal->tty_old_pgrp = get_pid(tty->pgrp); 573 p->signal->tty_old_pgrp = get_pid(tty->pgrp);
570 spin_unlock(&tty->ctrl_lock); 574 spin_unlock(&tty->ctrl_lock);
@@ -573,6 +577,12 @@ static int tty_signal_session_leader(struct tty_struct *tty)
573 } 577 }
574 read_unlock(&tasklist_lock); 578 read_unlock(&tasklist_lock);
575 579
580 if (tty_pgrp) {
581 if (exit_session)
582 kill_pgrp(tty_pgrp, SIGHUP, exit_session);
583 put_pid(tty_pgrp);
584 }
585
576 return refs; 586 return refs;
577} 587}
578 588
@@ -598,7 +608,7 @@ static int tty_signal_session_leader(struct tty_struct *tty)
598 * tasklist_lock to walk task list for hangup event 608 * tasklist_lock to walk task list for hangup event
599 * ->siglock to protect ->signal/->sighand 609 * ->siglock to protect ->signal/->sighand
600 */ 610 */
601static void __tty_hangup(struct tty_struct *tty) 611static void __tty_hangup(struct tty_struct *tty, int exit_session)
602{ 612{
603 struct file *cons_filp = NULL; 613 struct file *cons_filp = NULL;
604 struct file *filp, *f = NULL; 614 struct file *filp, *f = NULL;
@@ -647,7 +657,7 @@ static void __tty_hangup(struct tty_struct *tty)
647 */ 657 */
648 tty_ldisc_hangup(tty); 658 tty_ldisc_hangup(tty);
649 659
650 refs = tty_signal_session_leader(tty); 660 refs = tty_signal_session_leader(tty, exit_session);
651 /* Account for the p->signal references we killed */ 661 /* Account for the p->signal references we killed */
652 while (refs--) 662 while (refs--)
653 tty_kref_put(tty); 663 tty_kref_put(tty);
@@ -696,7 +706,7 @@ static void do_tty_hangup(struct work_struct *work)
696 struct tty_struct *tty = 706 struct tty_struct *tty =
697 container_of(work, struct tty_struct, hangup_work); 707 container_of(work, struct tty_struct, hangup_work);
698 708
699 __tty_hangup(tty); 709 __tty_hangup(tty, 0);
700} 710}
701 711
702/** 712/**
@@ -734,7 +744,7 @@ void tty_vhangup(struct tty_struct *tty)
734 744
735 printk(KERN_DEBUG "%s vhangup...\n", tty_name(tty, buf)); 745 printk(KERN_DEBUG "%s vhangup...\n", tty_name(tty, buf));
736#endif 746#endif
737 __tty_hangup(tty); 747 __tty_hangup(tty, 0);
738} 748}
739 749
740EXPORT_SYMBOL(tty_vhangup); 750EXPORT_SYMBOL(tty_vhangup);
@@ -758,6 +768,27 @@ void tty_vhangup_self(void)
758} 768}
759 769
760/** 770/**
771 * tty_vhangup_session - hangup session leader exit
772 * @tty: tty to hangup
773 *
774 * The session leader is exiting and hanging up its controlling terminal.
775 * Every process in the foreground process group is signalled SIGHUP.
776 *
777 * We do this synchronously so that when the syscall returns the process
778 * is complete. That guarantee is necessary for security reasons.
779 */
780
781void tty_vhangup_session(struct tty_struct *tty)
782{
783#ifdef TTY_DEBUG_HANGUP
784 char buf[64];
785
786 printk(KERN_DEBUG "%s vhangup session...\n", tty_name(tty, buf));
787#endif
788 __tty_hangup(tty, 1);
789}
790
791/**
761 * tty_hung_up_p - was tty hung up 792 * tty_hung_up_p - was tty hung up
762 * @filp: file pointer of tty 793 * @filp: file pointer of tty
763 * 794 *
@@ -814,18 +845,18 @@ void disassociate_ctty(int on_exit)
814 845
815 tty = get_current_tty(); 846 tty = get_current_tty();
816 if (tty) { 847 if (tty) {
817 struct pid *tty_pgrp = get_pid(tty->pgrp); 848 if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY) {
818 if (on_exit) { 849 tty_vhangup_session(tty);
819 if (tty->driver->type != TTY_DRIVER_TYPE_PTY) 850 } else {
820 tty_vhangup(tty); 851 struct pid *tty_pgrp = tty_get_pgrp(tty);
821 } 852 if (tty_pgrp) {
822 tty_kref_put(tty); 853 kill_pgrp(tty_pgrp, SIGHUP, on_exit);
823 if (tty_pgrp) {
824 kill_pgrp(tty_pgrp, SIGHUP, on_exit);
825 if (!on_exit)
826 kill_pgrp(tty_pgrp, SIGCONT, on_exit); 854 kill_pgrp(tty_pgrp, SIGCONT, on_exit);
827 put_pid(tty_pgrp); 855 put_pid(tty_pgrp);
856 }
828 } 857 }
858 tty_kref_put(tty);
859
829 } else if (on_exit) { 860 } else if (on_exit) {
830 struct pid *old_pgrp; 861 struct pid *old_pgrp;
831 spin_lock_irq(&current->sighand->siglock); 862 spin_lock_irq(&current->sighand->siglock);