Bluetooth: hci_uart: check for missing tty operations [Linux 3.16.72]

This Linux kernel change "Bluetooth: hci_uart: check for missing tty operations" is included in the Linux 3.16.72 release. This change is authored by Vladis Dronov <vdronov [at]> on Tue Jul 30 11:33:45 2019 +0200. The commit for this change in Linux stable tree is ebb8302 (patch) which is from upstream commit b36a155. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream b36a155.

Bluetooth: hci_uart: check for missing tty operations

commit b36a1552d7319bbfd5cf7f08726c23c5c66d4f73 upstream.

Certain ttys operations (pty_unix98_ops) lack tiocmget() and tiocmset()
functions which are called by the certain HCI UART protocols (hci_ath,
hci_bcm, hci_intel, hci_mrvl, hci_qca) via hci_uart_set_flow_control()
or directly. This leads to an execution at NULL and can be triggered by
an unprivileged user. Fix this by adding a helper function and a check
for the missing tty operations in the protocols code.

This fixes CVE-2019-10207. The Fixes: lines list commits where calls to
tiocm[gs]et() or hci_uart_set_flow_control() were added to the HCI UART

Fixes: b3190df62861 ("Bluetooth: Support for Atheros AR300x serial chip")
Fixes: 118612fb9165 ("Bluetooth: hci_bcm: Add suspend/resume PM functions")
Fixes: ff2895592f0f ("Bluetooth: hci_intel: Add Intel baudrate configuration support")
Fixes: 162f812f23ba ("Bluetooth: hci_uart: Add Marvell support")
Fixes: fa9ad876b8e0 ("Bluetooth: hci_qca: Add support for Qualcomm Bluetooth chip wcn3990")
Signed-off-by: Vladis Dronov <>
Signed-off-by: Marcel Holtmann <>
Reviewed-by: Yu-Chen, Cho <>
Tested-by: Yu-Chen, Cho <>
Signed-off-by: Linus Torvalds <>
[bwh: Backported to 3.16:
 - Only hci_ath is affected
 - There is no serdev support]
Signed-off-by: Ben Hutchings <>

There are 13 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 drivers/bluetooth/hci_ath.c   | 3 +++
 drivers/bluetooth/hci_ldisc.c | 9 +++++++++
 drivers/bluetooth/hci_uart.h  | 1 +
 3 files changed, 13 insertions(+)

diff --git a/drivers/bluetooth/hci_ath.c b/drivers/bluetooth/hci_ath.c
index 0bc8a6a..353ed68 100644
--- a/drivers/bluetooth/hci_ath.c
+++ b/drivers/bluetooth/hci_ath.c
@@ -112,6 +112,9 @@ static int ath_open(struct hci_uart *hu)

    BT_DBG("hu %p", hu);

+   if (!hci_uart_has_flow_control(hu))
+       return -EOPNOTSUPP;
    ath = kzalloc(sizeof(*ath), GFP_KERNEL);
    if (!ath)
        return -ENOMEM;
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index e00f8f5..9ad4370 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -261,6 +261,15 @@ static int hci_uart_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
    return 0;

+/* Check the underlying device or tty has flow control support */
+bool hci_uart_has_flow_control(struct hci_uart *hu)
+   if (hu->tty->driver->ops->tiocmget && hu->tty->driver->ops->tiocmset)
+       return true;
+   return false;
 /* ------ LDISC part ------ */
 /* hci_uart_tty_open
diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h
index 12df101..58e0bb8 100644
--- a/drivers/bluetooth/hci_uart.h
+++ b/drivers/bluetooth/hci_uart.h
@@ -90,6 +90,7 @@ struct hci_uart {
 int hci_uart_unregister_proto(struct hci_uart_proto *p);
 int hci_uart_tx_wakeup(struct hci_uart *hu);
 int hci_uart_init_ready(struct hci_uart *hu);
+bool hci_uart_has_flow_control(struct hci_uart *hu);

 int h4_init(void);

Leave a Reply

Your email address will not be published. Required fields are marked *