Commit 082a1532 authored by Peter Hurley's avatar Peter Hurley Committed by Marcel Holtmann

Bluetooth: Fix racy acquire of rfcomm_dev reference

rfcomm_dev_get() can return a rfcomm_dev reference for a
device for which destruction may be commencing. This can happen
on tty destruction, which calls rfcomm_tty_cleanup(), the last
port reference may have been released but RFCOMM_TTY_RELEASED
was not set. The following race is also possible:

CPU 0                            | CPU 1
                                 | rfcomm_release_dev
rfcomm_dev_get                   |   .
  spin_lock                      |   .
    dev  = __rfcomm_dev_get      |   .
    if dev                       |   .
      if test_bit(TTY_RELEASED)  |   .
                                 |   !test_and_set_bit(TTY_RELEASED)
                                 |     tty_port_put   <<<< last reference
      else                       |
        tty_port_get             |

The reference acquire is bogus because destruction will commence
with the release of the last reference.

Ignore the external state change of TTY_RELEASED and instead rely
on the reference acquire itself to determine if the reference is
valid.

Cc: Jiri Slaby <jslaby@suse.cz>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarPeter Hurley <peter@hurleysoftware.com>
Tested-By: default avatarAlexander Holler <holler@ahsoftware.de>
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
parent c0fdfb80
......@@ -157,12 +157,8 @@ static struct rfcomm_dev *rfcomm_dev_get(int id)
dev = __rfcomm_dev_get(id);
if (dev) {
if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags))
dev = NULL;
else
tty_port_get(&dev->port);
}
if (dev && !tty_port_get(&dev->port))
dev = NULL;
spin_unlock(&rfcomm_dev_lock);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment