[PATCH AUTOSEL for 4.14 061/135] Bluetooth: hci_ldisc: Fix another race when closing the tty.

From: alexander . levin
Date: Thu Dec 07 2017 - 13:02:40 EST


From: Ronald TschalÃr <ronald@xxxxxxxxxxxxx>

[ Upstream commit 0338b1b393ec7910898e8f7b25b3bf31a7282e16 ]

The following race condition still existed:

P1 P2
cancel_work_sync()
hci_uart_tx_wakeup()
hci_uart_write_work()
hci_uart_dequeue()
clear_bit(HCI_UART_PROTO_READY)
hci_unregister_dev(hdev)
hci_free_dev(hdev)
hu->proto->close(hu)
kfree(hu)
access to hdev and hu

Cancelling the work after clearing the HCI_UART_PROTO_READY bit avoids
this as any hci_uart_tx_wakeup() issued after the flag is cleared will
detect that and not schedule further work.

Signed-off-by: Ronald TschalÃr <ronald@xxxxxxxxxxxxx>
Reviewed-by: Lukas Wunner <lukas@xxxxxxxxx>
Signed-off-by: Marcel Holtmann <marcel@xxxxxxxxxxxx>
Signed-off-by: Sasha Levin <alexander.levin@xxxxxxxxxxx>
---
drivers/bluetooth/hci_ldisc.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index a746627e784e..6e2403805784 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -510,13 +510,13 @@ static void hci_uart_tty_close(struct tty_struct *tty)
if (hdev)
hci_uart_close(hdev);

- cancel_work_sync(&hu->write_work);
-
if (test_bit(HCI_UART_PROTO_READY, &hu->flags)) {
write_lock_irqsave(&hu->proto_lock, flags);
clear_bit(HCI_UART_PROTO_READY, &hu->flags);
write_unlock_irqrestore(&hu->proto_lock, flags);

+ cancel_work_sync(&hu->write_work);
+
if (hdev) {
if (test_bit(HCI_UART_REGISTERED, &hu->flags))
hci_unregister_dev(hdev);
--
2.11.0