aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Hurley <peter@hurleysoftware.com>2014-02-09 20:59:08 -0500
committerMarcel Holtmann <marcel@holtmann.org>2014-02-14 16:39:29 -0500
commit80ea73378af46b0023eb2f400d26c2a60248ffaa (patch)
tree3a1c25981ab3a5a77a1d656c7b2b44dae32d2698
parent1c64834e0624c61735308138e67cc3b527f41621 (diff)
Bluetooth: Fix unreleased rfcomm_dev reference
When RFCOMM_RELEASE_ONHUP is set, the rfcomm tty driver 'takes over' the initial rfcomm_dev reference created by the RFCOMMCREATEDEV ioctl. The assumption is that the rfcomm tty driver will release the rfcomm_dev reference when the tty is freed (in rfcomm_tty_cleanup()). However, if the tty is never opened, the 'take over' never occurs, so when RFCOMMRELEASEDEV ioctl is called, the reference is not released. Track the state of the reference 'take over' so that the release is guaranteed by either the RFCOMMRELEASEDEV ioctl or the rfcomm tty driver. Note that the synchronous hangup in rfcomm_release_dev() ensures that rfcomm_tty_install() cannot race with the RFCOMMRELEASEDEV ioctl. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Tested-By: Alexander Holler <holler@ahsoftware.de> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-rw-r--r--include/net/bluetooth/rfcomm.h1
-rw-r--r--net/bluetooth/rfcomm/tty.c6
2 files changed, 5 insertions, 2 deletions
diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h
index b9759eb17cdd..0d69936831fa 100644
--- a/include/net/bluetooth/rfcomm.h
+++ b/include/net/bluetooth/rfcomm.h
@@ -333,6 +333,7 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel,
333 333
334/* rfcomm_dev.status bit definitions */ 334/* rfcomm_dev.status bit definitions */
335#define RFCOMM_DEV_RELEASED 0 335#define RFCOMM_DEV_RELEASED 0
336#define RFCOMM_TTY_OWNED 1
336 337
337struct rfcomm_dev_req { 338struct rfcomm_dev_req {
338 s16 dev_id; 339 s16 dev_id;
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index d9d4bc89e638..bb570d95adca 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -441,7 +441,7 @@ static int rfcomm_release_dev(void __user *arg)
441 tty_kref_put(tty); 441 tty_kref_put(tty);
442 } 442 }
443 443
444 if (!test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags)) 444 if (!test_bit(RFCOMM_TTY_OWNED, &dev->status))
445 tty_port_put(&dev->port); 445 tty_port_put(&dev->port);
446 446
447 tty_port_put(&dev->port); 447 tty_port_put(&dev->port);
@@ -685,8 +685,10 @@ static int rfcomm_tty_install(struct tty_driver *driver, struct tty_struct *tty)
685 * when the last process closes the tty. The behaviour is expected by 685 * when the last process closes the tty. The behaviour is expected by
686 * userspace. 686 * userspace.
687 */ 687 */
688 if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags)) 688 if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags)) {
689 set_bit(RFCOMM_TTY_OWNED, &dev->status);
689 tty_port_put(&dev->port); 690 tty_port_put(&dev->port);
691 }
690 692
691 return 0; 693 return 0;
692} 694}