Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+2 −6
Original line number Diff line number Diff line
@@ -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))
	if (dev && !tty_port_get(&dev->port))
		dev = NULL;
		else
			tty_port_get(&dev->port);
	}

	spin_unlock(&rfcomm_dev_lock);