2017-01-29 20:59:32

by Dean Jenkins

[permalink] [raw]
Subject: [[RFC] PATCH V1 0/3] Minor code improvements for HCI UART LDISC

Please note that these 3 patches have not been formally tested. This is
partly due to not having Bluetooth hardware that will excercise the call to
hci_uart_init_work().

I have released the patches as [RFC] as the changes may need discussion.
I think the changes are trivial and safe.

The motivation for making these minor changes now is that
hci_uart_tty_close() can be reworked in future to simplify it. This means:

1) hu->hdev needs to be correctly set to NULL when the HCI device fails to
be registered.

2) HCI_UART_REGISTERED needs to be clear when the HCI UART fails to be
registered.

3) HCI_UART_PROTO_READY needs to be clear just before the Data Link
Protocol layer is closed.

As these changes are untested there is a risk of potential side-effects but
the changes only make a difference when the HCI device fails to be
registered which should be rare.

The patches were ported to the master branch of bluetooth-next.git

Dean Jenkins (3):
Bluetooth: Add missing return in hci_uart_init_work()
Bluetooth: Ensure hu->hdev set to NULL before freeing hdev
Bluetooth: Add missing clear HCI_UART_PROTO_READY

drivers/bluetooth/hci_ldisc.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)

--
2.7.4


2017-01-29 20:59:35

by Dean Jenkins

[permalink] [raw]
Subject: [[RFC] PATCH V1 3/3] Bluetooth: Add missing clear HCI_UART_PROTO_READY

Ensure that HCI_UART_PROTO_READY is cleared before close(hu) is
called which closes the Data Link protocol layer.

Therefore, add the missing bit clear of HCI_UART_PROTO_READY to
hci_uart_init_work() so that the flag is cleared when
hci_register_dev fails.

Without the fix, the functions of the Data Link protocol layer could
potentially be accessed after that layer has been closed. This
could lead to a crash as memory would have been freed in that layer.

Signed-off-by: Dean Jenkins <[email protected]>
---
drivers/bluetooth/hci_ldisc.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index a351cc7..1887ad4 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -187,6 +187,7 @@ static void hci_uart_init_work(struct work_struct *work)
hdev = hu->hdev;
hu->hdev = NULL;
hci_free_dev(hdev);
+ clear_bit(HCI_UART_PROTO_READY, &hu->flags);
hu->proto->close(hu);
return;
}
--
2.7.4

2017-01-29 20:59:34

by Dean Jenkins

[permalink] [raw]
Subject: [[RFC] PATCH V1 2/3] Bluetooth: Ensure hu->hdev set to NULL before freeing hdev

When hci_register_dev() fails, hu->hdev should be set to NULL before
freeing hdev. This avoids potential use of hu->hdev after it has been
freed.

This commit sets hu->hdev to NULL before calling hci_free_dev() in error
scenarios in hci_uart_init_work() and hci_uart_register_dev().

Signed-off-by: Dean Jenkins <[email protected]>
---
drivers/bluetooth/hci_ldisc.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 3a65414..a351cc7 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -176,6 +176,7 @@ static void hci_uart_init_work(struct work_struct *work)
{
struct hci_uart *hu = container_of(work, struct hci_uart, init_ready);
int err;
+ struct hci_dev *hdev;

if (!test_and_clear_bit(HCI_UART_INIT_PENDING, &hu->hdev_flags))
return;
@@ -183,8 +184,9 @@ static void hci_uart_init_work(struct work_struct *work)
err = hci_register_dev(hu->hdev);
if (err < 0) {
BT_ERR("Can't register HCI device");
- hci_free_dev(hu->hdev);
+ hdev = hu->hdev;
hu->hdev = NULL;
+ hci_free_dev(hdev);
hu->proto->close(hu);
return;
}
@@ -617,6 +619,7 @@ static int hci_uart_register_dev(struct hci_uart *hu)

if (hci_register_dev(hdev) < 0) {
BT_ERR("Can't register HCI device");
+ hu->hdev = NULL;
hci_free_dev(hdev);
return -ENODEV;
}
--
2.7.4

2017-01-29 20:59:33

by Dean Jenkins

[permalink] [raw]
Subject: [[RFC] PATCH V1 1/3] Bluetooth: Add missing return in hci_uart_init_work()

If hci_register_dev() returns an error in hci_uart_init_work()
then the HCI_UART_REGISTERED bit gets erroneously set due to
a missing return statement. Therefore, add the missing return
statement.

The consequence of the missing return is that the HCI UART is not
registered but HCI_UART_REGISTERED is set which allows the code
to think that hu->hdev is safe to access but hu->hdev has been
freed so could lead to a crash.

Signed-off-by: Dean Jenkins <[email protected]>
---
drivers/bluetooth/hci_ldisc.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 9497c46..3a65414 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -186,6 +186,7 @@ static void hci_uart_init_work(struct work_struct *work)
hci_free_dev(hu->hdev);
hu->hdev = NULL;
hu->proto->close(hu);
+ return;
}

set_bit(HCI_UART_REGISTERED, &hu->flags);
--
2.7.4