Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Patrick Donnelly <batrick@batbytes.com>
Reviewed-by: Peter Hurley <peter@hurleysoftware.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Patrick Donnelly and committed by
Greg Kroah-Hartman
6719693c da891641

+24 -8
+12 -3
drivers/tty/n_tty.c
··· 2137 2137 2138 2138 static int job_control(struct tty_struct *tty, struct file *file) 2139 2139 { 2140 + struct pid *pgrp; 2141 + 2140 2142 /* Job control check -- must be done at start and after 2141 2143 every sleep (POSIX.1 7.1.1.4). */ 2142 2144 /* NOTE: not yet done after every sleep pending a thorough ··· 2148 2146 current->signal->tty != tty) 2149 2147 return 0; 2150 2148 2149 + rcu_read_lock(); 2150 + pgrp = task_pgrp(current); 2151 + 2151 2152 spin_lock_irq(&tty->ctrl_lock); 2152 2153 if (!tty->pgrp) 2153 2154 printk(KERN_ERR "n_tty_read: no tty->pgrp!\n"); 2154 - else if (task_pgrp(current) != tty->pgrp) { 2155 + else if (pgrp != tty->pgrp) { 2155 2156 spin_unlock_irq(&tty->ctrl_lock); 2156 - if (is_ignored(SIGTTIN) || is_current_pgrp_orphaned()) 2157 + if (is_ignored(SIGTTIN) || is_current_pgrp_orphaned()) { 2158 + rcu_read_unlock(); 2157 2159 return -EIO; 2158 - kill_pgrp(task_pgrp(current), SIGTTIN, 1); 2160 + } 2161 + kill_pgrp(pgrp, SIGTTIN, 1); 2162 + rcu_read_unlock(); 2159 2163 set_thread_flag(TIF_SIGPENDING); 2160 2164 return -ERESTARTSYS; 2161 2165 } 2162 2166 spin_unlock_irq(&tty->ctrl_lock); 2167 + rcu_read_unlock(); 2163 2168 return 0; 2164 2169 } 2165 2170
+12 -5
drivers/tty/tty_io.c
··· 388 388 int tty_check_change(struct tty_struct *tty) 389 389 { 390 390 unsigned long flags; 391 + struct pid *pgrp; 391 392 int ret = 0; 392 393 393 394 if (current->signal->tty != tty) 394 395 return 0; 396 + 397 + rcu_read_lock(); 398 + pgrp = task_pgrp(current); 395 399 396 400 spin_lock_irqsave(&tty->ctrl_lock, flags); 397 401 ··· 403 399 printk(KERN_WARNING "tty_check_change: tty->pgrp == NULL!\n"); 404 400 goto out_unlock; 405 401 } 406 - if (task_pgrp(current) == tty->pgrp) 402 + if (pgrp == tty->pgrp) 407 403 goto out_unlock; 408 404 spin_unlock_irqrestore(&tty->ctrl_lock, flags); 405 + 409 406 if (is_ignored(SIGTTOU)) 410 - goto out; 407 + goto out_rcuunlock; 411 408 if (is_current_pgrp_orphaned()) { 412 409 ret = -EIO; 413 - goto out; 410 + goto out_rcuunlock; 414 411 } 415 - kill_pgrp(task_pgrp(current), SIGTTOU, 1); 412 + kill_pgrp(pgrp, SIGTTOU, 1); 413 + rcu_read_unlock(); 416 414 set_thread_flag(TIF_SIGPENDING); 417 415 ret = -ERESTARTSYS; 418 - out: 419 416 return ret; 420 417 out_unlock: 421 418 spin_unlock_irqrestore(&tty->ctrl_lock, flags); 419 + out_rcuunlock: 420 + rcu_read_unlock(); 422 421 return ret; 423 422 } 424 423