Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6719693c authored by Patrick Donnelly's avatar Patrick Donnelly Committed by Greg Kroah-Hartman
Browse files

tty: add missing rcu_read_lock for task_pgrp



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: default avatarPatrick Donnelly <batrick@batbytes.com>
Reviewed-by: default avatarPeter Hurley <peter@hurleysoftware.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent da891641
Loading
Loading
Loading
Loading
+12 −3
Original line number Original line Diff line number Diff line
@@ -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)
static int job_control(struct tty_struct *tty, struct file *file)
{
{
	struct pid *pgrp;

	/* Job control check -- must be done at start and after
	/* Job control check -- must be done at start and after
	   every sleep (POSIX.1 7.1.1.4). */
	   every sleep (POSIX.1 7.1.1.4). */
	/* NOTE: not yet done after every sleep pending a thorough
	/* 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)
	    current->signal->tty != tty)
		return 0;
		return 0;


	rcu_read_lock();
	pgrp = task_pgrp(current);

	spin_lock_irq(&tty->ctrl_lock);
	spin_lock_irq(&tty->ctrl_lock);
	if (!tty->pgrp)
	if (!tty->pgrp)
		printk(KERN_ERR "n_tty_read: no tty->pgrp!\n");
		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);
		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;
			return -EIO;
		kill_pgrp(task_pgrp(current), SIGTTIN, 1);
		}
		kill_pgrp(pgrp, SIGTTIN, 1);
		rcu_read_unlock();
		set_thread_flag(TIF_SIGPENDING);
		set_thread_flag(TIF_SIGPENDING);
		return -ERESTARTSYS;
		return -ERESTARTSYS;
	}
	}
	spin_unlock_irq(&tty->ctrl_lock);
	spin_unlock_irq(&tty->ctrl_lock);
	rcu_read_unlock();
	return 0;
	return 0;
}
}


+12 −5
Original line number Original line Diff line number Diff line
@@ -388,33 +388,40 @@ EXPORT_SYMBOL_GPL(tty_find_polling_driver);
int tty_check_change(struct tty_struct *tty)
int tty_check_change(struct tty_struct *tty)
{
{
	unsigned long flags;
	unsigned long flags;
	struct pid *pgrp;
	int ret = 0;
	int ret = 0;


	if (current->signal->tty != tty)
	if (current->signal->tty != tty)
		return 0;
		return 0;


	rcu_read_lock();
	pgrp = task_pgrp(current);

	spin_lock_irqsave(&tty->ctrl_lock, flags);
	spin_lock_irqsave(&tty->ctrl_lock, flags);


	if (!tty->pgrp) {
	if (!tty->pgrp) {
		printk(KERN_WARNING "tty_check_change: tty->pgrp == NULL!\n");
		printk(KERN_WARNING "tty_check_change: tty->pgrp == NULL!\n");
		goto out_unlock;
		goto out_unlock;
	}
	}
	if (task_pgrp(current) == tty->pgrp)
	if (pgrp == tty->pgrp)
		goto out_unlock;
		goto out_unlock;
	spin_unlock_irqrestore(&tty->ctrl_lock, flags);
	spin_unlock_irqrestore(&tty->ctrl_lock, flags);

	if (is_ignored(SIGTTOU))
	if (is_ignored(SIGTTOU))
		goto out;
		goto out_rcuunlock;
	if (is_current_pgrp_orphaned()) {
	if (is_current_pgrp_orphaned()) {
		ret = -EIO;
		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);
	set_thread_flag(TIF_SIGPENDING);
	ret = -ERESTARTSYS;
	ret = -ERESTARTSYS;
out:
	return ret;
	return ret;
out_unlock:
out_unlock:
	spin_unlock_irqrestore(&tty->ctrl_lock, flags);
	spin_unlock_irqrestore(&tty->ctrl_lock, flags);
out_rcuunlock:
	rcu_read_unlock();
	return ret;
	return ret;
}
}