tty: add missing rcu_read_lock for task_pgrp
authorPatrick Donnelly <batrick@batbytes.com>
Sun, 12 Jul 2015 22:51:52 +0000 (18:51 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 24 Jul 2015 00:56:38 +0000 (17:56 -0700)
task_pgrp requires an rcu or tasklist lock to be obtained if the returned pid
is to be dereferenced, which kill_pgrp does. Obtain an RCU lock for the
duration of use.

Signed-off-by: Patrick Donnelly <batrick@batbytes.com>
Reviewed-by: Peter Hurley <peter@hurleysoftware.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/tty/n_tty.c
drivers/tty/tty_io.c

index c9c27f69e101cfc9246a81ed1f187148b08193e6..de67b2c88bfc68fab5ad717178eddd50306d7460 100644 (file)
@@ -2137,6 +2137,8 @@ extern ssize_t redirected_tty_write(struct file *, const char __user *,
 
 static int job_control(struct tty_struct *tty, struct file *file)
 {
+       struct pid *pgrp;
+
        /* Job control check -- must be done at start and after
           every sleep (POSIX.1 7.1.1.4). */
        /* NOTE: not yet done after every sleep pending a thorough
@@ -2146,18 +2148,25 @@ static int job_control(struct tty_struct *tty, struct file *file)
            current->signal->tty != tty)
                return 0;
 
+       rcu_read_lock();
+       pgrp = task_pgrp(current);
+
        spin_lock_irq(&tty->ctrl_lock);
        if (!tty->pgrp)
                printk(KERN_ERR "n_tty_read: no tty->pgrp!\n");
-       else if (task_pgrp(current) != tty->pgrp) {
+       else if (pgrp != tty->pgrp) {
                spin_unlock_irq(&tty->ctrl_lock);
-               if (is_ignored(SIGTTIN) || is_current_pgrp_orphaned())
+               if (is_ignored(SIGTTIN) || is_current_pgrp_orphaned()) {
+                       rcu_read_unlock();
                        return -EIO;
-               kill_pgrp(task_pgrp(current), SIGTTIN, 1);
+               }
+               kill_pgrp(pgrp, SIGTTIN, 1);
+               rcu_read_unlock();
                set_thread_flag(TIF_SIGPENDING);
                return -ERESTARTSYS;
        }
        spin_unlock_irq(&tty->ctrl_lock);
+       rcu_read_unlock();
        return 0;
 }
 
index 57fc6ee12332e6932472ac1cc1796d607f114e4f..6bdfb98bf020e70a3b8464550dc06326a18a2103 100644 (file)
@@ -388,33 +388,40 @@ EXPORT_SYMBOL_GPL(tty_find_polling_driver);
 int tty_check_change(struct tty_struct *tty)
 {
        unsigned long flags;
+       struct pid *pgrp;
        int ret = 0;
 
        if (current->signal->tty != tty)
                return 0;
 
+       rcu_read_lock();
+       pgrp = task_pgrp(current);
+
        spin_lock_irqsave(&tty->ctrl_lock, flags);
 
        if (!tty->pgrp) {
                printk(KERN_WARNING "tty_check_change: tty->pgrp == NULL!\n");
                goto out_unlock;
        }
-       if (task_pgrp(current) == tty->pgrp)
+       if (pgrp == tty->pgrp)
                goto out_unlock;
        spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+
        if (is_ignored(SIGTTOU))
-               goto out;
+               goto out_rcuunlock;
        if (is_current_pgrp_orphaned()) {
                ret = -EIO;
-               goto out;
+               goto out_rcuunlock;
        }
-       kill_pgrp(task_pgrp(current), SIGTTOU, 1);
+       kill_pgrp(pgrp, SIGTTOU, 1);
+       rcu_read_unlock();
        set_thread_flag(TIF_SIGPENDING);
        ret = -ERESTARTSYS;
-out:
        return ret;
 out_unlock:
        spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+out_rcuunlock:
+       rcu_read_unlock();
        return ret;
 }