diff options
author | Peter Hurley <peter@hurleysoftware.com> | 2013-03-06 08:38:20 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-03-18 19:13:59 -0400 |
commit | 01a5e440c91dc6065cf3dbc38aa7276fc4ce2f26 (patch) | |
tree | 681cd21901b56dca6046fbc9516bb74221fa8b7a | |
parent | 8c985d18b136c5d511445d15f0c6650003a8946b (diff) |
n_tty: Lock access to tty->pgrp for POSIX job control
Concurrent access to tty->pgrp must be protected with tty->ctrl_lock.
Also, as noted in the comments, reading current->signal->tty is
safe because either,
1) current->signal->tty is assigned by current, or
2) current->signal->tty is set to NULL.
NB: for reference, tty_check_change() implements a similar POSIX
check for the ioctls corresponding to tcflush(), tcdrain(),
tcsetattr(), tcsetpgrp(), tcflow() and tcsendbreak().
Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/tty/n_tty.c | 34 |
1 files changed, 18 insertions, 16 deletions
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 61f1bc97ccd9..68865d9af8a0 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c | |||
@@ -1719,10 +1719,9 @@ extern ssize_t redirected_tty_write(struct file *, const char __user *, | |||
1719 | * and if appropriate send any needed signals and return a negative | 1719 | * and if appropriate send any needed signals and return a negative |
1720 | * error code if action should be taken. | 1720 | * error code if action should be taken. |
1721 | * | 1721 | * |
1722 | * FIXME: | 1722 | * Locking: redirected write test is safe |
1723 | * Locking: None - redirected write test is safe, testing | 1723 | * current->signal->tty check is safe |
1724 | * current->signal should possibly lock current->sighand | 1724 | * ctrl_lock to safely reference tty->pgrp |
1725 | * pgrp locking ? | ||
1726 | */ | 1725 | */ |
1727 | 1726 | ||
1728 | static int job_control(struct tty_struct *tty, struct file *file) | 1727 | static int job_control(struct tty_struct *tty, struct file *file) |
@@ -1732,19 +1731,22 @@ static int job_control(struct tty_struct *tty, struct file *file) | |||
1732 | /* NOTE: not yet done after every sleep pending a thorough | 1731 | /* NOTE: not yet done after every sleep pending a thorough |
1733 | check of the logic of this change. -- jlc */ | 1732 | check of the logic of this change. -- jlc */ |
1734 | /* don't stop on /dev/console */ | 1733 | /* don't stop on /dev/console */ |
1735 | if (file->f_op->write != redirected_tty_write && | 1734 | if (file->f_op->write == redirected_tty_write || |
1736 | current->signal->tty == tty) { | 1735 | current->signal->tty != tty) |
1737 | if (!tty->pgrp) | 1736 | return 0; |
1738 | printk(KERN_ERR "n_tty_read: no tty->pgrp!\n"); | 1737 | |
1739 | else if (task_pgrp(current) != tty->pgrp) { | 1738 | spin_lock_irq(&tty->ctrl_lock); |
1740 | if (is_ignored(SIGTTIN) || | 1739 | if (!tty->pgrp) |
1741 | is_current_pgrp_orphaned()) | 1740 | printk(KERN_ERR "n_tty_read: no tty->pgrp!\n"); |
1742 | return -EIO; | 1741 | else if (task_pgrp(current) != tty->pgrp) { |
1743 | kill_pgrp(task_pgrp(current), SIGTTIN, 1); | 1742 | spin_unlock_irq(&tty->ctrl_lock); |
1744 | set_thread_flag(TIF_SIGPENDING); | 1743 | if (is_ignored(SIGTTIN) || is_current_pgrp_orphaned()) |
1745 | return -ERESTARTSYS; | 1744 | return -EIO; |
1746 | } | 1745 | kill_pgrp(task_pgrp(current), SIGTTIN, 1); |
1746 | set_thread_flag(TIF_SIGPENDING); | ||
1747 | return -ERESTARTSYS; | ||
1747 | } | 1748 | } |
1749 | spin_unlock_irq(&tty->ctrl_lock); | ||
1748 | return 0; | 1750 | return 0; |
1749 | } | 1751 | } |
1750 | 1752 | ||