diff options
author | Loic Poulain <loic.poulain@intel.com> | 2016-04-04 04:48:13 -0400 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2016-04-08 12:58:56 -0400 |
commit | 84cb3df02aea4b00405521e67c4c67c2d525c364 (patch) | |
tree | 4802172d6283adade1e8299ed851b4b2af8c14d2 | |
parent | 1dbfc59a931495b2e7bdc4e85886162a0b03235b (diff) |
Bluetooth: hci_ldisc: Fix null pointer derefence in case of early data
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>
-rw-r--r-- | drivers/bluetooth/hci_ldisc.c | 11 | ||||
-rw-r--r-- | drivers/bluetooth/hci_uart.h | 1 |
2 files changed, 8 insertions, 4 deletions
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index c00168a5bb80..49b3e1e2d236 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c | |||
@@ -227,7 +227,7 @@ static int hci_uart_flush(struct hci_dev *hdev) | |||
227 | tty_ldisc_flush(tty); | 227 | tty_ldisc_flush(tty); |
228 | tty_driver_flush_buffer(tty); | 228 | tty_driver_flush_buffer(tty); |
229 | 229 | ||
230 | if (test_bit(HCI_UART_PROTO_SET, &hu->flags)) | 230 | if (test_bit(HCI_UART_PROTO_READY, &hu->flags)) |
231 | hu->proto->flush(hu); | 231 | hu->proto->flush(hu); |
232 | 232 | ||
233 | return 0; | 233 | return 0; |
@@ -492,7 +492,7 @@ static void hci_uart_tty_close(struct tty_struct *tty) | |||
492 | 492 | ||
493 | cancel_work_sync(&hu->write_work); | 493 | cancel_work_sync(&hu->write_work); |
494 | 494 | ||
495 | if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) { | 495 | if (test_and_clear_bit(HCI_UART_PROTO_READY, &hu->flags)) { |
496 | if (hdev) { | 496 | if (hdev) { |
497 | if (test_bit(HCI_UART_REGISTERED, &hu->flags)) | 497 | if (test_bit(HCI_UART_REGISTERED, &hu->flags)) |
498 | hci_unregister_dev(hdev); | 498 | hci_unregister_dev(hdev); |
@@ -500,6 +500,7 @@ static void hci_uart_tty_close(struct tty_struct *tty) | |||
500 | } | 500 | } |
501 | hu->proto->close(hu); | 501 | hu->proto->close(hu); |
502 | } | 502 | } |
503 | clear_bit(HCI_UART_PROTO_SET, &hu->flags); | ||
503 | 504 | ||
504 | kfree(hu); | 505 | kfree(hu); |
505 | } | 506 | } |
@@ -526,7 +527,7 @@ static void hci_uart_tty_wakeup(struct tty_struct *tty) | |||
526 | if (tty != hu->tty) | 527 | if (tty != hu->tty) |
527 | return; | 528 | return; |
528 | 529 | ||
529 | if (test_bit(HCI_UART_PROTO_SET, &hu->flags)) | 530 | if (test_bit(HCI_UART_PROTO_READY, &hu->flags)) |
530 | hci_uart_tx_wakeup(hu); | 531 | hci_uart_tx_wakeup(hu); |
531 | } | 532 | } |
532 | 533 | ||
@@ -550,7 +551,7 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, | |||
550 | if (!hu || tty != hu->tty) | 551 | if (!hu || tty != hu->tty) |
551 | return; | 552 | return; |
552 | 553 | ||
553 | if (!test_bit(HCI_UART_PROTO_SET, &hu->flags)) | 554 | if (!test_bit(HCI_UART_PROTO_READY, &hu->flags)) |
554 | return; | 555 | return; |
555 | 556 | ||
556 | /* It does not need a lock here as it is already protected by a mutex in | 557 | /* It does not need a lock here as it is already protected by a mutex in |
@@ -638,9 +639,11 @@ static int hci_uart_set_proto(struct hci_uart *hu, int id) | |||
638 | return err; | 639 | return err; |
639 | 640 | ||
640 | hu->proto = p; | 641 | hu->proto = p; |
642 | set_bit(HCI_UART_PROTO_READY, &hu->flags); | ||
641 | 643 | ||
642 | err = hci_uart_register_dev(hu); | 644 | err = hci_uart_register_dev(hu); |
643 | if (err) { | 645 | if (err) { |
646 | clear_bit(HCI_UART_PROTO_READY, &hu->flags); | ||
644 | p->close(hu); | 647 | p->close(hu); |
645 | return err; | 648 | return err; |
646 | } | 649 | } |
diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h index 4814ff08f427..839bad1d8152 100644 --- a/drivers/bluetooth/hci_uart.h +++ b/drivers/bluetooth/hci_uart.h | |||
@@ -95,6 +95,7 @@ struct hci_uart { | |||
95 | /* HCI_UART proto flag bits */ | 95 | /* HCI_UART proto flag bits */ |
96 | #define HCI_UART_PROTO_SET 0 | 96 | #define HCI_UART_PROTO_SET 0 |
97 | #define HCI_UART_REGISTERED 1 | 97 | #define HCI_UART_REGISTERED 1 |
98 | #define HCI_UART_PROTO_READY 2 | ||
98 | 99 | ||
99 | /* TX states */ | 100 | /* TX states */ |
100 | #define HCI_UART_SENDING 1 | 101 | #define HCI_UART_SENDING 1 |