tty/ldsem: Add lockdep asserts for ldisc_sem
Make sure under CONFIG_LOCKDEP that each change to line discipline is done with held write semaphor. Otherwise potential reader will have a good time dereferencing incomplete/uninitialized ldisc. An exception here is tty_ldisc_open(), as it's called without ldisc_sem locked by tty_init_dev() => tty_ldisc_setup() for the tty->link. It seem valid as tty_init_dev() will call tty_driver_install_tty() which will find ops->install(). Install will establish tty->link in pty_common_install(), just after allocation of slave tty with alloc_tty_struct(). So, no one should have a reference to slave pty yet. Cc: Jiri Slaby <jslaby@suse.com> Cc: Peter Zijlstra <peterz@infradead.org> Signed-off-by: Dmitry Safonov <dima@arista.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Родитель
c18ad0cf9c
Коммит
110b89282f
|
@ -478,6 +478,7 @@ static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld)
|
|||
|
||||
static void tty_ldisc_close(struct tty_struct *tty, struct tty_ldisc *ld)
|
||||
{
|
||||
lockdep_assert_held_exclusive(&tty->ldisc_sem);
|
||||
WARN_ON(!test_bit(TTY_LDISC_OPEN, &tty->flags));
|
||||
clear_bit(TTY_LDISC_OPEN, &tty->flags);
|
||||
if (ld->ops->close)
|
||||
|
@ -499,6 +500,7 @@ static int tty_ldisc_failto(struct tty_struct *tty, int ld)
|
|||
struct tty_ldisc *disc = tty_ldisc_get(tty, ld);
|
||||
int r;
|
||||
|
||||
lockdep_assert_held_exclusive(&tty->ldisc_sem);
|
||||
if (IS_ERR(disc))
|
||||
return PTR_ERR(disc);
|
||||
tty->ldisc = disc;
|
||||
|
@ -622,6 +624,7 @@ EXPORT_SYMBOL_GPL(tty_set_ldisc);
|
|||
*/
|
||||
static void tty_ldisc_kill(struct tty_struct *tty)
|
||||
{
|
||||
lockdep_assert_held_exclusive(&tty->ldisc_sem);
|
||||
if (!tty->ldisc)
|
||||
return;
|
||||
/*
|
||||
|
@ -669,6 +672,7 @@ int tty_ldisc_reinit(struct tty_struct *tty, int disc)
|
|||
struct tty_ldisc *ld;
|
||||
int retval;
|
||||
|
||||
lockdep_assert_held_exclusive(&tty->ldisc_sem);
|
||||
ld = tty_ldisc_get(tty, disc);
|
||||
if (IS_ERR(ld)) {
|
||||
BUG_ON(disc == N_TTY);
|
||||
|
@ -767,6 +771,10 @@ int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty)
|
|||
return retval;
|
||||
|
||||
if (o_tty) {
|
||||
/*
|
||||
* Called without o_tty->ldisc_sem held, as o_tty has been
|
||||
* just allocated and no one has a reference to it.
|
||||
*/
|
||||
retval = tty_ldisc_open(o_tty, o_tty->ldisc);
|
||||
if (retval) {
|
||||
tty_ldisc_close(tty, tty->ldisc);
|
||||
|
@ -832,6 +840,7 @@ int tty_ldisc_init(struct tty_struct *tty)
|
|||
*/
|
||||
void tty_ldisc_deinit(struct tty_struct *tty)
|
||||
{
|
||||
/* no ldisc_sem, tty is being destroyed */
|
||||
if (tty->ldisc)
|
||||
tty_ldisc_put(tty->ldisc);
|
||||
tty->ldisc = NULL;
|
||||
|
|
Загрузка…
Ссылка в новой задаче