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

Commit 5b899241 authored by Gianluca Anzolin's avatar Gianluca Anzolin Committed by Marcel Holtmann
Browse files

Bluetooth: Release RFCOMM port when the last user closes the TTY



This patch fixes a userspace regression introduced by the commit
29cd718b.

If the rfcomm device was created with the flag RFCOMM_RELEASE_ONHUP the
user space expects that the tty_port is released as soon as the last
process closes the tty.

The current code attempts to release the port in the function
rfcomm_dev_state_change(). However it won't get a reference to the
relevant tty to send a HUP: at that point the tty is already destroyed
and therefore NULL.

This patch fixes the regression by taking over the tty refcount in the
tty install method(). This way the tty_port is automatically released as
soon as the tty is destroyed.

As a consequence the check for RFCOMM_RELEASE_ONHUP flag in the hangup()
method is now redundant. Instead we have to be careful with the reference
counting in the rfcomm_release_dev() function.

Signed-off-by: default avatarGianluca Anzolin <gianluca@sottospazio.it>
Reported-by: default avatarAlexander Holler <holler@ahsoftware.de>
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
parent cb6ca8e1
Loading
Loading
Loading
Loading
+14 −7
Original line number Diff line number Diff line
@@ -437,7 +437,8 @@ static int rfcomm_release_dev(void __user *arg)
		tty_kref_put(tty);
	}

	if (!test_and_set_bit(RFCOMM_TTY_RELEASED, &dev->flags))
	if (!test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags) &&
	    !test_and_set_bit(RFCOMM_TTY_RELEASED, &dev->flags))
		tty_port_put(&dev->port);

	tty_port_put(&dev->port);
@@ -670,12 +671,22 @@ static int rfcomm_tty_install(struct tty_driver *driver, struct tty_struct *tty)

	/* install the tty_port */
	err = tty_port_install(&dev->port, driver, tty);
	if (err)
	if (err) {
		rfcomm_tty_cleanup(tty);

		return err;
	}

	/* take over the tty_port reference if the port was created with the
	 * flag RFCOMM_RELEASE_ONHUP. This will force the release of the port
	 * when the last process closes the tty. The behaviour is expected by
	 * userspace.
	 */
	if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags))
		tty_port_put(&dev->port);

	return 0;
}

static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
{
	struct rfcomm_dev *dev = tty->driver_data;
@@ -1010,10 +1021,6 @@ static void rfcomm_tty_hangup(struct tty_struct *tty)
	BT_DBG("tty %p dev %p", tty, dev);

	tty_port_hangup(&dev->port);

	if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags) &&
	    !test_and_set_bit(RFCOMM_TTY_RELEASED, &dev->flags))
		tty_port_put(&dev->port);
}

static int rfcomm_tty_tiocmget(struct tty_struct *tty)