tty-ldisc: be more careful in 'put_ldisc' locking
Use 'atomic_dec_and_lock()' to make sure that we always hold the tty_ldisc_lock when the ldisc count goes to zero. That way we can never race against 'tty_ldisc_try()' increasing the count again. Reported-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Tested-by: Sergey Senozhatsky <sergey.senozhatsky@mail.by> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
65b770468e
commit
cbe9352fa0
1 changed files with 12 additions and 5 deletions
|
@ -55,25 +55,32 @@ static inline struct tty_ldisc *get_ldisc(struct tty_ldisc *ld)
|
||||||
return ld;
|
return ld;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void put_ldisc(struct tty_ldisc *ld)
|
static void put_ldisc(struct tty_ldisc *ld)
|
||||||
{
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
if (WARN_ON_ONCE(!ld))
|
if (WARN_ON_ONCE(!ld))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If this is the last user, free the ldisc, and
|
* If this is the last user, free the ldisc, and
|
||||||
* release the ldisc ops.
|
* release the ldisc ops.
|
||||||
|
*
|
||||||
|
* We really want an "atomic_dec_and_lock_irqsave()",
|
||||||
|
* but we don't have it, so this does it by hand.
|
||||||
*/
|
*/
|
||||||
if (atomic_dec_and_test(&ld->users)) {
|
local_irq_save(flags);
|
||||||
unsigned long flags;
|
if (atomic_dec_and_lock(&ld->users, &tty_ldisc_lock)) {
|
||||||
struct tty_ldisc_ops *ldo = ld->ops;
|
struct tty_ldisc_ops *ldo = ld->ops;
|
||||||
|
|
||||||
kfree(ld);
|
|
||||||
spin_lock_irqsave(&tty_ldisc_lock, flags);
|
|
||||||
ldo->refcount--;
|
ldo->refcount--;
|
||||||
module_put(ldo->owner);
|
module_put(ldo->owner);
|
||||||
spin_unlock_irqrestore(&tty_ldisc_lock, flags);
|
spin_unlock_irqrestore(&tty_ldisc_lock, flags);
|
||||||
|
|
||||||
|
kfree(ld);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
local_irq_restore(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Add table
Reference in a new issue