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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'tty-5.10-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty

Pull tty fixes from Greg KH:
"Here are two tty core fixes for 5.10-rc7.

They resolve some reported locking issues in the tty core. While they
have not been in a released linux-next yet, they have passed all of
the 0-day bot testing as well as the submitter's testing"

* tag 'tty-5.10-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty:
tty: Fix ->session locking
tty: Fix ->pgrp locking in tiocspgrp()

+41 -14
+6 -1
drivers/tty/tty_io.c
··· 2897 2897 struct task_struct *g, *p; 2898 2898 struct pid *session; 2899 2899 int i; 2900 + unsigned long flags; 2900 2901 2901 2902 if (!tty) 2902 2903 return; 2903 - session = tty->session; 2904 + 2905 + spin_lock_irqsave(&tty->ctrl_lock, flags); 2906 + session = get_pid(tty->session); 2907 + spin_unlock_irqrestore(&tty->ctrl_lock, flags); 2904 2908 2905 2909 tty_ldisc_flush(tty); 2906 2910 ··· 2936 2932 task_unlock(p); 2937 2933 } while_each_thread(g, p); 2938 2934 read_unlock(&tasklist_lock); 2935 + put_pid(session); 2939 2936 #endif 2940 2937 } 2941 2938
+31 -13
drivers/tty/tty_jobctrl.c
··· 103 103 put_pid(tty->session); 104 104 put_pid(tty->pgrp); 105 105 tty->pgrp = get_pid(task_pgrp(current)); 106 - spin_unlock_irqrestore(&tty->ctrl_lock, flags); 107 106 tty->session = get_pid(task_session(current)); 107 + spin_unlock_irqrestore(&tty->ctrl_lock, flags); 108 108 if (current->signal->tty) { 109 109 tty_debug(tty, "current tty %s not NULL!!\n", 110 110 current->signal->tty->name); ··· 293 293 spin_lock_irq(&current->sighand->siglock); 294 294 put_pid(current->signal->tty_old_pgrp); 295 295 current->signal->tty_old_pgrp = NULL; 296 - 297 296 tty = tty_kref_get(current->signal->tty); 297 + spin_unlock_irq(&current->sighand->siglock); 298 + 298 299 if (tty) { 299 300 unsigned long flags; 301 + 302 + tty_lock(tty); 300 303 spin_lock_irqsave(&tty->ctrl_lock, flags); 301 304 put_pid(tty->session); 302 305 put_pid(tty->pgrp); 303 306 tty->session = NULL; 304 307 tty->pgrp = NULL; 305 308 spin_unlock_irqrestore(&tty->ctrl_lock, flags); 309 + tty_unlock(tty); 306 310 tty_kref_put(tty); 307 311 } 308 312 309 - spin_unlock_irq(&current->sighand->siglock); 310 313 /* Now clear signal->tty under the lock */ 311 314 read_lock(&tasklist_lock); 312 315 session_clear_tty(task_session(current)); ··· 480 477 return -ENOTTY; 481 478 if (retval) 482 479 return retval; 483 - if (!current->signal->tty || 484 - (current->signal->tty != real_tty) || 485 - (real_tty->session != task_session(current))) 486 - return -ENOTTY; 480 + 487 481 if (get_user(pgrp_nr, p)) 488 482 return -EFAULT; 489 483 if (pgrp_nr < 0) 490 484 return -EINVAL; 485 + 486 + spin_lock_irq(&real_tty->ctrl_lock); 487 + if (!current->signal->tty || 488 + (current->signal->tty != real_tty) || 489 + (real_tty->session != task_session(current))) { 490 + retval = -ENOTTY; 491 + goto out_unlock_ctrl; 492 + } 491 493 rcu_read_lock(); 492 494 pgrp = find_vpid(pgrp_nr); 493 495 retval = -ESRCH; ··· 502 494 if (session_of_pgrp(pgrp) != task_session(current)) 503 495 goto out_unlock; 504 496 retval = 0; 505 - spin_lock_irq(&tty->ctrl_lock); 506 497 put_pid(real_tty->pgrp); 507 498 real_tty->pgrp = get_pid(pgrp); 508 - spin_unlock_irq(&tty->ctrl_lock); 509 499 out_unlock: 510 500 rcu_read_unlock(); 501 + out_unlock_ctrl: 502 + spin_unlock_irq(&real_tty->ctrl_lock); 511 503 return retval; 512 504 } 513 505 ··· 519 511 * 520 512 * Obtain the session id of the tty. If there is no session 521 513 * return an error. 522 - * 523 - * Locking: none. Reference to current->signal->tty is safe. 524 514 */ 525 515 static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p) 526 516 { 517 + unsigned long flags; 518 + pid_t sid; 519 + 527 520 /* 528 521 * (tty == real_tty) is a cheap way of 529 522 * testing if the tty is NOT a master pty. 530 523 */ 531 524 if (tty == real_tty && current->signal->tty != real_tty) 532 525 return -ENOTTY; 526 + 527 + spin_lock_irqsave(&real_tty->ctrl_lock, flags); 533 528 if (!real_tty->session) 534 - return -ENOTTY; 535 - return put_user(pid_vnr(real_tty->session), p); 529 + goto err; 530 + sid = pid_vnr(real_tty->session); 531 + spin_unlock_irqrestore(&real_tty->ctrl_lock, flags); 532 + 533 + return put_user(sid, p); 534 + 535 + err: 536 + spin_unlock_irqrestore(&real_tty->ctrl_lock, flags); 537 + return -ENOTTY; 536 538 } 537 539 538 540 /*
+4
include/linux/tty.h
··· 306 306 struct termiox *termiox; /* May be NULL for unsupported */ 307 307 char name[64]; 308 308 struct pid *pgrp; /* Protected by ctrl lock */ 309 + /* 310 + * Writes protected by both ctrl lock and legacy mutex, readers must use 311 + * at least one of them. 312 + */ 309 313 struct pid *session; 310 314 unsigned long flags; 311 315 int count;