diff options
Diffstat (limited to 'recipes-kernel/linux/linux-3.12.70/linux-3.12-release-rfcomm-port-fix.patch')
-rw-r--r-- | recipes-kernel/linux/linux-3.12.70/linux-3.12-release-rfcomm-port-fix.patch | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/recipes-kernel/linux/linux-3.12.70/linux-3.12-release-rfcomm-port-fix.patch b/recipes-kernel/linux/linux-3.12.70/linux-3.12-release-rfcomm-port-fix.patch new file mode 100644 index 0000000..70c41d2 --- /dev/null +++ b/recipes-kernel/linux/linux-3.12.70/linux-3.12-release-rfcomm-port-fix.patch @@ -0,0 +1,78 @@ +commit 5b899241874dcc1a2b932a668731c80a3a869575 +Author: Gianluca Anzolin <gianluca@sottospazio.it> +Date: Mon Jan 6 21:23:50 2014 +0100 + + 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> + +diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c +index 84fcf9f..a535ef1 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) + 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,10 +671,20 @@ 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; ++ } + +- 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) +@@ -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) |