tty: Drop krefs for interrupted tty lock
When the tty lock is interrupted on attempted re-open, 2 tty krefs
are still held. Drop extra kref before returning failure from
tty_lock_interruptible(), and drop lookup kref before returning
failure from tty_open().
Fixes: 0bfd464d3f
("tty: Wait interruptibly for tty lock on reopen")
Reported-by: Dmitry Vyukov <dvyukov@google.com>
Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Родитель
36f90b0a2d
Коммит
e9036d0662
|
@ -2066,13 +2066,12 @@ retry_open:
|
||||||
if (tty) {
|
if (tty) {
|
||||||
mutex_unlock(&tty_mutex);
|
mutex_unlock(&tty_mutex);
|
||||||
retval = tty_lock_interruptible(tty);
|
retval = tty_lock_interruptible(tty);
|
||||||
|
tty_kref_put(tty); /* drop kref from tty_driver_lookup_tty() */
|
||||||
if (retval) {
|
if (retval) {
|
||||||
if (retval == -EINTR)
|
if (retval == -EINTR)
|
||||||
retval = -ERESTARTSYS;
|
retval = -ERESTARTSYS;
|
||||||
goto err_unref;
|
goto err_unref;
|
||||||
}
|
}
|
||||||
/* safe to drop the kref from tty_driver_lookup_tty() */
|
|
||||||
tty_kref_put(tty);
|
|
||||||
retval = tty_reopen(tty);
|
retval = tty_reopen(tty);
|
||||||
if (retval < 0) {
|
if (retval < 0) {
|
||||||
tty_unlock(tty);
|
tty_unlock(tty);
|
||||||
|
|
|
@ -21,10 +21,15 @@ EXPORT_SYMBOL(tty_lock);
|
||||||
|
|
||||||
int tty_lock_interruptible(struct tty_struct *tty)
|
int tty_lock_interruptible(struct tty_struct *tty)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (WARN(tty->magic != TTY_MAGIC, "L Bad %p\n", tty))
|
if (WARN(tty->magic != TTY_MAGIC, "L Bad %p\n", tty))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
tty_kref_get(tty);
|
tty_kref_get(tty);
|
||||||
return mutex_lock_interruptible(&tty->legacy_mutex);
|
ret = mutex_lock_interruptible(&tty->legacy_mutex);
|
||||||
|
if (ret)
|
||||||
|
tty_kref_put(tty);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void __lockfunc tty_unlock(struct tty_struct *tty)
|
void __lockfunc tty_unlock(struct tty_struct *tty)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче