From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-sn1nam01on0105.outbound.protection.outlook.com ([104.47.32.105]:54752 "EHLO NAM01-SN1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S965904AbeCHFC6 (ORCPT ); Thu, 8 Mar 2018 00:02:58 -0500 From: Sasha Levin To: "linux-kernel@vger.kernel.org" , "stable@vger.kernel.org" CC: Dean Jenkins , Marcel Holtmann , Sasha Levin Subject: [PATCH AUTOSEL for 4.9 124/190] Bluetooth: hci_ldisc: Add protocol check to hci_uart_tx_wakeup() Date: Thu, 8 Mar 2018 04:59:46 +0000 Message-ID: <20180308045810.8041-124-alexander.levin@microsoft.com> References: <20180308045810.8041-1-alexander.levin@microsoft.com> In-Reply-To: <20180308045810.8041-1-alexander.levin@microsoft.com> Content-Language: en-US Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Sender: stable-owner@vger.kernel.org List-ID: From: Dean Jenkins [ Upstream commit 2d6f1da168e1d62c47f7d50135ac4cbd8411dcb1 ] Before attempting to schedule a work-item onto hu->write_work in hci_uart_tx_wakeup(), check that the Data Link protocol layer is still bound to the HCI UART driver. Failure to perform this protocol check causes a race condition between the work queue hu->write_work running hci_uart_write_work() and the Data Link protocol layer being unbound (closed) in hci_uart_tty_close(). Note hci_uart_tty_close() does have a "cancel_work_sync(&hu->write_work)" but it is ineffective because it cannot prevent work-items being added to hu->write_work after cancel_work_sync() has run. Therefore, add a check for HCI_UART_PROTO_READY into hci_uart_tx_wakeup() which prevents scheduling of the work queue when HCI_UART_PROTO_READY is in the clear state. However, note a small race condition remains because the hci_uart_tx_wakeup() thread can run in parallel with the hci_uart_tty_close() thread so it is possible that a schedule of hu->write_work can occur when HCI_UART_PROTO_READY is cleared. A complete solution needs locking of the threads which is implemented in a future commit. Signed-off-by: Dean Jenkins Signed-off-by: Marcel Holtmann Signed-off-by: Sasha Levin --- drivers/bluetooth/hci_ldisc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index 7ec73945351c..2230f9368c21 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -125,6 +125,9 @@ static inline struct sk_buff *hci_uart_dequeue(struct h= ci_uart *hu) =20 int hci_uart_tx_wakeup(struct hci_uart *hu) { + if (!test_bit(HCI_UART_PROTO_READY, &hu->flags)) + return 0; + if (test_and_set_bit(HCI_UART_SENDING, &hu->tx_state)) { set_bit(HCI_UART_TX_WAKEUP, &hu->tx_state); return 0; --=20 2.14.1