Skip to content

Commit d49248e

Browse files
committed
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()
2 parents f5226f1 + c8bcd9c commit d49248e

File tree

3 files changed

+41
-14
lines changed

3 files changed

+41
-14
lines changed

drivers/tty/tty_io.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2897,10 +2897,14 @@ void __do_SAK(struct tty_struct *tty)
28972897
struct task_struct *g, *p;
28982898
struct pid *session;
28992899
int i;
2900+
unsigned long flags;
29002901

29012902
if (!tty)
29022903
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);
29042908

29052909
tty_ldisc_flush(tty);
29062910

@@ -2932,6 +2936,7 @@ void __do_SAK(struct tty_struct *tty)
29322936
task_unlock(p);
29332937
} while_each_thread(g, p);
29342938
read_unlock(&tasklist_lock);
2939+
put_pid(session);
29352940
#endif
29362941
}
29372942

drivers/tty/tty_jobctrl.c

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,8 @@ static void __proc_set_tty(struct tty_struct *tty)
103103
put_pid(tty->session);
104104
put_pid(tty->pgrp);
105105
tty->pgrp = get_pid(task_pgrp(current));
106-
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
107106
tty->session = get_pid(task_session(current));
107+
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
108108
if (current->signal->tty) {
109109
tty_debug(tty, "current tty %s not NULL!!\n",
110110
current->signal->tty->name);
@@ -293,20 +293,23 @@ void disassociate_ctty(int on_exit)
293293
spin_lock_irq(&current->sighand->siglock);
294294
put_pid(current->signal->tty_old_pgrp);
295295
current->signal->tty_old_pgrp = NULL;
296-
297296
tty = tty_kref_get(current->signal->tty);
297+
spin_unlock_irq(&current->sighand->siglock);
298+
298299
if (tty) {
299300
unsigned long flags;
301+
302+
tty_lock(tty);
300303
spin_lock_irqsave(&tty->ctrl_lock, flags);
301304
put_pid(tty->session);
302305
put_pid(tty->pgrp);
303306
tty->session = NULL;
304307
tty->pgrp = NULL;
305308
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
309+
tty_unlock(tty);
306310
tty_kref_put(tty);
307311
}
308312

309-
spin_unlock_irq(&current->sighand->siglock);
310313
/* Now clear signal->tty under the lock */
311314
read_lock(&tasklist_lock);
312315
session_clear_tty(task_session(current));
@@ -477,14 +480,19 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
477480
return -ENOTTY;
478481
if (retval)
479482
return retval;
480-
if (!current->signal->tty ||
481-
(current->signal->tty != real_tty) ||
482-
(real_tty->session != task_session(current)))
483-
return -ENOTTY;
483+
484484
if (get_user(pgrp_nr, p))
485485
return -EFAULT;
486486
if (pgrp_nr < 0)
487487
return -EINVAL;
488+
489+
spin_lock_irq(&real_tty->ctrl_lock);
490+
if (!current->signal->tty ||
491+
(current->signal->tty != real_tty) ||
492+
(real_tty->session != task_session(current))) {
493+
retval = -ENOTTY;
494+
goto out_unlock_ctrl;
495+
}
488496
rcu_read_lock();
489497
pgrp = find_vpid(pgrp_nr);
490498
retval = -ESRCH;
@@ -494,12 +502,12 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
494502
if (session_of_pgrp(pgrp) != task_session(current))
495503
goto out_unlock;
496504
retval = 0;
497-
spin_lock_irq(&tty->ctrl_lock);
498505
put_pid(real_tty->pgrp);
499506
real_tty->pgrp = get_pid(pgrp);
500-
spin_unlock_irq(&tty->ctrl_lock);
501507
out_unlock:
502508
rcu_read_unlock();
509+
out_unlock_ctrl:
510+
spin_unlock_irq(&real_tty->ctrl_lock);
503511
return retval;
504512
}
505513

@@ -511,20 +519,30 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
511519
*
512520
* Obtain the session id of the tty. If there is no session
513521
* return an error.
514-
*
515-
* Locking: none. Reference to current->signal->tty is safe.
516522
*/
517523
static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
518524
{
525+
unsigned long flags;
526+
pid_t sid;
527+
519528
/*
520529
* (tty == real_tty) is a cheap way of
521530
* testing if the tty is NOT a master pty.
522531
*/
523532
if (tty == real_tty && current->signal->tty != real_tty)
524533
return -ENOTTY;
534+
535+
spin_lock_irqsave(&real_tty->ctrl_lock, flags);
525536
if (!real_tty->session)
526-
return -ENOTTY;
527-
return put_user(pid_vnr(real_tty->session), p);
537+
goto err;
538+
sid = pid_vnr(real_tty->session);
539+
spin_unlock_irqrestore(&real_tty->ctrl_lock, flags);
540+
541+
return put_user(sid, p);
542+
543+
err:
544+
spin_unlock_irqrestore(&real_tty->ctrl_lock, flags);
545+
return -ENOTTY;
528546
}
529547

530548
/*

include/linux/tty.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,10 @@ struct tty_struct {
306306
struct termiox *termiox; /* May be NULL for unsupported */
307307
char name[64];
308308
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+
*/
309313
struct pid *session;
310314
unsigned long flags;
311315
int count;

0 commit comments

Comments
 (0)