Bluetooth: hci_ldisc: Fix null pointer derefence in case of early data
commit 84cb3df02aea4b00405521e67c4c67c2d525c364 upstream. HCI_UART_PROTO_SET flag is set before hci_uart_set_proto call. If we receive data from tty layer during this procedure, proto pointer may not be assigned yet, leading to null pointer dereference in rx method hci_uart_tty_receive. This patch fixes this issue by introducing HCI_UART_PROTO_READY flag in order to avoid any proto operation before proto opening and assignment. Signed-off-by: Loic Poulain <loic.poulain@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Cc: Ralph Siemsen <ralph.siemsen@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
364bac4850
commit
cc62ff0cf5
|
@ -227,7 +227,7 @@ static int hci_uart_flush(struct hci_dev *hdev)
|
|||
tty_ldisc_flush(tty);
|
||||
tty_driver_flush_buffer(tty);
|
||||
|
||||
if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
|
||||
if (test_bit(HCI_UART_PROTO_READY, &hu->flags))
|
||||
hu->proto->flush(hu);
|
||||
|
||||
return 0;
|
||||
|
@ -506,7 +506,7 @@ static void hci_uart_tty_close(struct tty_struct *tty)
|
|||
|
||||
cancel_work_sync(&hu->write_work);
|
||||
|
||||
if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) {
|
||||
if (test_and_clear_bit(HCI_UART_PROTO_READY, &hu->flags)) {
|
||||
if (hdev) {
|
||||
if (test_bit(HCI_UART_REGISTERED, &hu->flags))
|
||||
hci_unregister_dev(hdev);
|
||||
|
@ -514,6 +514,7 @@ static void hci_uart_tty_close(struct tty_struct *tty)
|
|||
}
|
||||
hu->proto->close(hu);
|
||||
}
|
||||
clear_bit(HCI_UART_PROTO_SET, &hu->flags);
|
||||
|
||||
kfree(hu);
|
||||
}
|
||||
|
@ -540,7 +541,7 @@ static void hci_uart_tty_wakeup(struct tty_struct *tty)
|
|||
if (tty != hu->tty)
|
||||
return;
|
||||
|
||||
if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
|
||||
if (test_bit(HCI_UART_PROTO_READY, &hu->flags))
|
||||
hci_uart_tx_wakeup(hu);
|
||||
}
|
||||
|
||||
|
@ -564,7 +565,7 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data,
|
|||
if (!hu || tty != hu->tty)
|
||||
return;
|
||||
|
||||
if (!test_bit(HCI_UART_PROTO_SET, &hu->flags))
|
||||
if (!test_bit(HCI_UART_PROTO_READY, &hu->flags))
|
||||
return;
|
||||
|
||||
/* It does not need a lock here as it is already protected by a mutex in
|
||||
|
@ -652,9 +653,11 @@ static int hci_uart_set_proto(struct hci_uart *hu, int id)
|
|||
return err;
|
||||
|
||||
hu->proto = p;
|
||||
set_bit(HCI_UART_PROTO_READY, &hu->flags);
|
||||
|
||||
err = hci_uart_register_dev(hu);
|
||||
if (err) {
|
||||
clear_bit(HCI_UART_PROTO_READY, &hu->flags);
|
||||
p->close(hu);
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -94,6 +94,7 @@ struct hci_uart {
|
|||
/* HCI_UART proto flag bits */
|
||||
#define HCI_UART_PROTO_SET 0
|
||||
#define HCI_UART_REGISTERED 1
|
||||
#define HCI_UART_PROTO_READY 2
|
||||
|
||||
/* TX states */
|
||||
#define HCI_UART_SENDING 1
|
||||
|
|
Loading…
Reference in New Issue
Block a user