aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorGianluca Anzolin <gianluca@sottospazio.it>2014-01-06 15:23:50 -0500
committerMarcel Holtmann <marcel@holtmann.org>2014-01-06 16:51:45 -0500
commit5b899241874dcc1a2b932a668731c80a3a869575 (patch)
treea138c1ce7fb63a0a966fc64e86a26d80b3f80f6d /net
parentcb6ca8e1ed922082bacc6e5e5ee040491a443ea2 (diff)
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: Gianluca Anzolin <gianluca@sottospazio.it> Reported-by: Alexander Holler <holler@ahsoftware.de> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/rfcomm/tty.c21
1 files changed, 14 insertions, 7 deletions
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index 84fcf9fff3ea..a535ef148ef6 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -437,7 +437,8 @@ static int rfcomm_release_dev(void __user *arg)
437 tty_kref_put(tty); 437 tty_kref_put(tty);
438 } 438 }
439 439
440 if (!test_and_set_bit(RFCOMM_TTY_RELEASED, &dev->flags)) 440 if (!test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags) &&
441 !test_and_set_bit(RFCOMM_TTY_RELEASED, &dev->flags))
441 tty_port_put(&dev->port); 442 tty_port_put(&dev->port);
442 443
443 tty_port_put(&dev->port); 444 tty_port_put(&dev->port);
@@ -670,10 +671,20 @@ static int rfcomm_tty_install(struct tty_driver *driver, struct tty_struct *tty)
670 671
671 /* install the tty_port */ 672 /* install the tty_port */
672 err = tty_port_install(&dev->port, driver, tty); 673 err = tty_port_install(&dev->port, driver, tty);
673 if (err) 674 if (err) {
674 rfcomm_tty_cleanup(tty); 675 rfcomm_tty_cleanup(tty);
676 return err;
677 }
675 678
676 return err; 679 /* take over the tty_port reference if the port was created with the
680 * flag RFCOMM_RELEASE_ONHUP. This will force the release of the port
681 * when the last process closes the tty. The behaviour is expected by
682 * userspace.
683 */
684 if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags))
685 tty_port_put(&dev->port);
686
687 return 0;
677} 688}
678 689
679static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp) 690static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
@@ -1010,10 +1021,6 @@ static void rfcomm_tty_hangup(struct tty_struct *tty)
1010 BT_DBG("tty %p dev %p", tty, dev); 1021 BT_DBG("tty %p dev %p", tty, dev);
1011 1022
1012 tty_port_hangup(&dev->port); 1023 tty_port_hangup(&dev->port);
1013
1014 if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags) &&
1015 !test_and_set_bit(RFCOMM_TTY_RELEASED, &dev->flags))
1016 tty_port_put(&dev->port);
1017} 1024}
1018 1025
1019static int rfcomm_tty_tiocmget(struct tty_struct *tty) 1026static int rfcomm_tty_tiocmget(struct tty_struct *tty)