linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] Bluetooth: hci_core: fix init with HCI_QUIRK_NON_PERSISTENT_SETUP
@ 2019-10-04  0:09 Mattijs Korpershoek
  2019-10-16 19:27 ` Marcel Holtmann
  0 siblings, 1 reply; 5+ messages in thread
From: Mattijs Korpershoek @ 2019-10-04  0:09 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: Sean Wang, Mattijs Korpershoek, Marcel Holtmann, Johan Hedberg,
	David S. Miller, netdev, linux-kernel

Some HCI devices which have the HCI_QUIRK_NON_PERSISTENT_SETUP [1]
require a call to setup() to be ran after every open().

During the setup() stage, these devices expect the chip to acknowledge
its setup() completion via vendor specific frames.

If userspace opens() such HCI device in HCI_USER_CHANNEL [2] mode,
the vendor specific frames are never tranmitted to the driver, as
they are filtered in hci_rx_work().

Allow HCI devices which have HCI_QUIRK_NON_PERSISTENT_SETUP to process
frames if the HCI device is is HCI_INIT state.

[1] https://lore.kernel.org/patchwork/patch/965071/
[2] https://www.spinics.net/lists/linux-bluetooth/msg37345.html

Fixes: 740011cfe948 ("Bluetooth: Add new quirk for non-persistent setup settings")
Signed-off-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
---
Some more background on the change follows:

The Android bluetooth stack (Bluedroid) also has a HAL implementation
which follows Linux's standard rfkill interface [1].

This implementation relies on the HCI_CHANNEL_USER feature to get
exclusive access to the underlying bluetooth device.

When testing this along with the btkmtksdio driver, the
chip appeared unresponsive when calling the following from userspace:

    struct sockaddr_hci addr;
    int fd;

    fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);

    memset(&addr, 0, sizeof(addr));
    addr.hci_family = AF_BLUETOOTH;
    addr.hci_dev = 0;
    addr.hci_channel = HCI_CHANNEL_USER;

    bind(fd, (struct sockaddr *) &addr, sizeof(addr)); # device hangs

In the case of bluetooth drivers exposing QUIRK_NON_PERSISTENT_SETUP
such as btmtksdio, setup() is called each multiple times.
In particular, when userspace calls bind(), the setup() is called again
and vendor specific commands might be send to re-initialize the chip.

Those commands are filtered out by hci_core in HCI_CHANNEL_USER mode,
preventing setup() from completing successfully.

This has been tested on a 4.19 kernel based on Android Common Kernel.
It has also been compile tested on bluetooth-next.

[1] https://android.googlesource.com/platform/system/bt/+/refs/heads/master/vendor_libs/linux/interface/

 net/bluetooth/hci_core.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 04bc79359a17..5f12e8574d54 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -4440,9 +4440,20 @@ static void hci_rx_work(struct work_struct *work)
 			hci_send_to_sock(hdev, skb);
 		}
 
+		/* If the device has been opened in HCI_USER_CHANNEL,
+		 * the userspace has exclusive access to device.
+		 * When HCI_QUIRK_NON_PERSISTENT_SETUP is set and
+		 * device is HCI_INIT,  we still need to process
+		 * the data packets to the driver in order
+		 * to complete its setup().
+		 */
 		if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
-			kfree_skb(skb);
-			continue;
+			if (!test_bit(HCI_QUIRK_NON_PERSISTENT_SETUP,
+				      &hdev->quirks) ||
+			    !test_bit(HCI_INIT, &hdev->flags)) {
+				kfree_skb(skb);
+				continue;
+			}
 		}
 
 		if (test_bit(HCI_INIT, &hdev->flags)) {
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH] Bluetooth: hci_core: fix init with HCI_QUIRK_NON_PERSISTENT_SETUP
  2019-10-04  0:09 [PATCH] Bluetooth: hci_core: fix init with HCI_QUIRK_NON_PERSISTENT_SETUP Mattijs Korpershoek
@ 2019-10-16 19:27 ` Marcel Holtmann
  2019-10-16 19:53   ` Mattijs Korpershoek
  2019-10-17  3:20   ` [PATCH v2] Bluetooth: hci_core: fix init for HCI_USER_CHANNEL Mattijs Korpershoek
  0 siblings, 2 replies; 5+ messages in thread
From: Marcel Holtmann @ 2019-10-16 19:27 UTC (permalink / raw)
  To: Mattijs Korpershoek
  Cc: Bluez mailing list, Sean Wang, Johan Hedberg, David S. Miller,
	netdev, linux-kernel

Hi Mattijs,

> Some HCI devices which have the HCI_QUIRK_NON_PERSISTENT_SETUP [1]
> require a call to setup() to be ran after every open().
> 
> During the setup() stage, these devices expect the chip to acknowledge
> its setup() completion via vendor specific frames.
> 
> If userspace opens() such HCI device in HCI_USER_CHANNEL [2] mode,
> the vendor specific frames are never tranmitted to the driver, as
> they are filtered in hci_rx_work().
> 
> Allow HCI devices which have HCI_QUIRK_NON_PERSISTENT_SETUP to process
> frames if the HCI device is is HCI_INIT state.
> 
> [1] https://lore.kernel.org/patchwork/patch/965071/
> [2] https://www.spinics.net/lists/linux-bluetooth/msg37345.html
> 
> Fixes: 740011cfe948 ("Bluetooth: Add new quirk for non-persistent setup settings")
> Signed-off-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
> ---
> Some more background on the change follows:
> 
> The Android bluetooth stack (Bluedroid) also has a HAL implementation
> which follows Linux's standard rfkill interface [1].
> 
> This implementation relies on the HCI_CHANNEL_USER feature to get
> exclusive access to the underlying bluetooth device.
> 
> When testing this along with the btkmtksdio driver, the
> chip appeared unresponsive when calling the following from userspace:
> 
>    struct sockaddr_hci addr;
>    int fd;
> 
>    fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
> 
>    memset(&addr, 0, sizeof(addr));
>    addr.hci_family = AF_BLUETOOTH;
>    addr.hci_dev = 0;
>    addr.hci_channel = HCI_CHANNEL_USER;
> 
>    bind(fd, (struct sockaddr *) &addr, sizeof(addr)); # device hangs
> 
> In the case of bluetooth drivers exposing QUIRK_NON_PERSISTENT_SETUP
> such as btmtksdio, setup() is called each multiple times.
> In particular, when userspace calls bind(), the setup() is called again
> and vendor specific commands might be send to re-initialize the chip.
> 
> Those commands are filtered out by hci_core in HCI_CHANNEL_USER mode,
> preventing setup() from completing successfully.
> 
> This has been tested on a 4.19 kernel based on Android Common Kernel.
> It has also been compile tested on bluetooth-next.
> 
> [1] https://android.googlesource.com/platform/system/bt/+/refs/heads/master/vendor_libs/linux/interface/
> 
> net/bluetooth/hci_core.c | 15 +++++++++++++--
> 1 file changed, 13 insertions(+), 2 deletions(-)
> 
> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> index 04bc79359a17..5f12e8574d54 100644
> --- a/net/bluetooth/hci_core.c
> +++ b/net/bluetooth/hci_core.c
> @@ -4440,9 +4440,20 @@ static void hci_rx_work(struct work_struct *work)
> 			hci_send_to_sock(hdev, skb);
> 		}
> 
> +		/* If the device has been opened in HCI_USER_CHANNEL,
> +		 * the userspace has exclusive access to device.
> +		 * When HCI_QUIRK_NON_PERSISTENT_SETUP is set and
> +		 * device is HCI_INIT,  we still need to process
> +		 * the data packets to the driver in order
> +		 * to complete its setup().
> +		 */
> 		if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
> -			kfree_skb(skb);
> -			continue;
> +			if (!test_bit(HCI_QUIRK_NON_PERSISTENT_SETUP,
> +				      &hdev->quirks) ||
> +			    !test_bit(HCI_INIT, &hdev->flags)) {
> +				kfree_skb(skb);
> +				continue;
> +			}
> 		}

	if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL) &&
	    !test_bit(HCI_INIT, &hdev->flags)) {
		kfree_skb(skb);
		continue;
	}

Wouldn’t it be enough to just add a check for HCI_INIT to this. I mean it makes no difference if ->setup is repeated on each device open or not. We want to process event during HCI_INIT when in user channel mode.

Regards

Marcel


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Bluetooth: hci_core: fix init with HCI_QUIRK_NON_PERSISTENT_SETUP
  2019-10-16 19:27 ` Marcel Holtmann
@ 2019-10-16 19:53   ` Mattijs Korpershoek
  2019-10-17  3:20   ` [PATCH v2] Bluetooth: hci_core: fix init for HCI_USER_CHANNEL Mattijs Korpershoek
  1 sibling, 0 replies; 5+ messages in thread
From: Mattijs Korpershoek @ 2019-10-16 19:53 UTC (permalink / raw)
  To: Marcel Holtmann
  Cc: Bluez mailing list, Sean Wang, Johan Hedberg, David S. Miller,
	netdev, linux-kernel


Hi Marcel,

Marcel Holtmann <marcel@holtmann.org> writes:

> Hi Mattijs,
>
>> Some HCI devices which have the HCI_QUIRK_NON_PERSISTENT_SETUP 
>> [1]
>> require a call to setup() to be ran after every open().
>> 
>> During the setup() stage, these devices expect the chip to 
>> acknowledge
>> its setup() completion via vendor specific frames.
>> 
>> If userspace opens() such HCI device in HCI_USER_CHANNEL [2] 
>> mode,
>> the vendor specific frames are never tranmitted to the driver, 
>> as
>> they are filtered in hci_rx_work().
>> 
>> Allow HCI devices which have HCI_QUIRK_NON_PERSISTENT_SETUP to 
>> process
>> frames if the HCI device is is HCI_INIT state.
>> 
>> [1] https://lore.kernel.org/patchwork/patch/965071/
>> [2] https://www.spinics.net/lists/linux-bluetooth/msg37345.html
>> 
>> Fixes: 740011cfe948 ("Bluetooth: Add new quirk for 
>> non-persistent setup settings")
>> Signed-off-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
>> ---
>> Some more background on the change follows:
>> 
>> The Android bluetooth stack (Bluedroid) also has a HAL 
>> implementation
>> which follows Linux's standard rfkill interface [1].
>> 
>> This implementation relies on the HCI_CHANNEL_USER feature to 
>> get
>> exclusive access to the underlying bluetooth device.
>> 
>> When testing this along with the btkmtksdio driver, the
>> chip appeared unresponsive when calling the following from 
>> userspace:
>> 
>>    struct sockaddr_hci addr;
>>    int fd;
>> 
>>    fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
>> 
>>    memset(&addr, 0, sizeof(addr));
>>    addr.hci_family = AF_BLUETOOTH;
>>    addr.hci_dev = 0;
>>    addr.hci_channel = HCI_CHANNEL_USER;
>> 
>>    bind(fd, (struct sockaddr *) &addr, sizeof(addr)); # device 
>>    hangs
>> 
>> In the case of bluetooth drivers exposing 
>> QUIRK_NON_PERSISTENT_SETUP
>> such as btmtksdio, setup() is called each multiple times.
>> In particular, when userspace calls bind(), the setup() is 
>> called again
>> and vendor specific commands might be send to re-initialize the 
>> chip.
>> 
>> Those commands are filtered out by hci_core in HCI_CHANNEL_USER 
>> mode,
>> preventing setup() from completing successfully.
>> 
>> This has been tested on a 4.19 kernel based on Android Common 
>> Kernel.
>> It has also been compile tested on bluetooth-next.
>> 
>> [1] 
>> https://android.googlesource.com/platform/system/bt/+/refs/heads/master/vendor_libs/linux/interface/
>> 
>> net/bluetooth/hci_core.c | 15 +++++++++++++--
>> 1 file changed, 13 insertions(+), 2 deletions(-)
>> 
>> diff --git a/net/bluetooth/hci_core.c 
>> b/net/bluetooth/hci_core.c
>> index 04bc79359a17..5f12e8574d54 100644
>> --- a/net/bluetooth/hci_core.c
>> +++ b/net/bluetooth/hci_core.c
>> @@ -4440,9 +4440,20 @@ static void hci_rx_work(struct 
>> work_struct *work)
>> 			hci_send_to_sock(hdev, skb);
>> 		}
>> 
>> +		/* If the device has been opened in HCI_USER_CHANNEL,
>> +		 * the userspace has exclusive access to device.
>> +		 * When HCI_QUIRK_NON_PERSISTENT_SETUP is set and
>> +		 * device is HCI_INIT,  we still need to process
>> +		 * the data packets to the driver in order
>> +		 * to complete its setup().
>> +		 */
>> 		if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
>> -			kfree_skb(skb);
>> -			continue;
>> +			if (!test_bit(HCI_QUIRK_NON_PERSISTENT_SETUP,
>> +				      &hdev->quirks) ||
>> +			    !test_bit(HCI_INIT, &hdev->flags)) {
>> +				kfree_skb(skb);
>> +				continue;
>> +			}
>> 		}
>
> 	if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL) &&
> 	    !test_bit(HCI_INIT, &hdev->flags)) {
> 		kfree_skb(skb);
> 		continue;
> 	}
>
> Wouldn’t it be enough to just add a check for HCI_INIT to this. 
> I mean it makes no difference if ->setup is repeated on each 
> device open or not. We want to process event during HCI_INIT 
> when in user channel mode.
Thank you for your review. You are right. We always want to 
process
events during HCI_INIT in user channel mode.

I'll send a v2

Regards,
Mattijs

>
> Regards
>
> Marcel


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v2] Bluetooth: hci_core: fix init for HCI_USER_CHANNEL
  2019-10-16 19:27 ` Marcel Holtmann
  2019-10-16 19:53   ` Mattijs Korpershoek
@ 2019-10-17  3:20   ` Mattijs Korpershoek
  2019-10-17  5:11     ` Marcel Holtmann
  1 sibling, 1 reply; 5+ messages in thread
From: Mattijs Korpershoek @ 2019-10-17  3:20 UTC (permalink / raw)
  To: linux-bluetooth
  Cc: Mattijs Korpershoek, Marcel Holtmann, Johan Hedberg,
	David S. Miller, netdev, linux-kernel

During the setup() stage, HCI device drivers expect the chip to
acknowledge its setup() completion via vendor specific frames.

If userspace opens() such HCI device in HCI_USER_CHANNEL [1] mode,
the vendor specific frames are never tranmitted to the driver, as
they are filtered in hci_rx_work().

Allow HCI devices which operate in HCI_USER_CHANNEL mode to receive
frames if the HCI device is is HCI_INIT state.

[1] https://www.spinics.net/lists/linux-bluetooth/msg37345.html

Fixes: 23500189d7e0 ("Bluetooth: Introduce new HCI socket channel for user operation")
Signed-off-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
---
Changelog:
v2:
* change test logic to transfer packets when in INIT phase
  for user channel mode as recommended by Marcel
* renamed patch from
  "Bluetooth: hci_core: fix init with HCI_QUIRK_NON_PERSISTENT_SETUP"

v1:
 * https://lkml.org/lkml/2019/10/3/2250

Some more background on the change follows:

The Android bluetooth stack (Bluedroid) also has a HAL implementation
which follows Linux's standard rfkill interface [1].

This implementation relies on the HCI_CHANNEL_USER feature to get
exclusive access to the underlying bluetooth device.

When testing this along with the btkmtksdio driver, the
chip appeared unresponsive when calling the following from userspace:

    struct sockaddr_hci addr;
    int fd;

    fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);

    memset(&addr, 0, sizeof(addr));
    addr.hci_family = AF_BLUETOOTH;
    addr.hci_dev = 0;
    addr.hci_channel = HCI_CHANNEL_USER;

    bind(fd, (struct sockaddr *) &addr, sizeof(addr)); # device hangs

In the case of bluetooth drivers exposing QUIRK_NON_PERSISTENT_SETUP
such as btmtksdio, setup() is called each multiple times.
In particular, when userspace calls bind(), the setup() is called again
and vendor specific commands might be send to re-initialize the chip.

Those commands are filtered out by hci_core in HCI_CHANNEL_USER mode,
preventing setup() from completing successfully.

This has been tested on a 4.19 kernel based on Android Common Kernel.
It has also been compile tested on bluetooth-next.

[1] https://android.googlesource.com/platform/system/bt/+/refs/heads/master/vendor_libs/linux/interface/

 net/bluetooth/hci_core.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index b2559d4bed81..0cc9ce917222 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -4440,7 +4440,14 @@ static void hci_rx_work(struct work_struct *work)
 			hci_send_to_sock(hdev, skb);
 		}
 
-		if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
+		/* If the device has been opened in HCI_USER_CHANNEL,
+		 * the userspace has exclusive access to device.
+		 * When device is HCI_INIT, we still need to process
+		 * the data packets to the driver in order
+		 * to complete its setup().
+		 */
+		if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL) &&
+		    !test_bit(HCI_INIT, &hdev->flags)) {
 			kfree_skb(skb);
 			continue;
 		}
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v2] Bluetooth: hci_core: fix init for HCI_USER_CHANNEL
  2019-10-17  3:20   ` [PATCH v2] Bluetooth: hci_core: fix init for HCI_USER_CHANNEL Mattijs Korpershoek
@ 2019-10-17  5:11     ` Marcel Holtmann
  0 siblings, 0 replies; 5+ messages in thread
From: Marcel Holtmann @ 2019-10-17  5:11 UTC (permalink / raw)
  To: Mattijs Korpershoek
  Cc: Bluez mailing list, Johan Hedberg, David S. Miller, netdev, linux-kernel

Hi Mattijs,

> During the setup() stage, HCI device drivers expect the chip to
> acknowledge its setup() completion via vendor specific frames.
> 
> If userspace opens() such HCI device in HCI_USER_CHANNEL [1] mode,
> the vendor specific frames are never tranmitted to the driver, as
> they are filtered in hci_rx_work().
> 
> Allow HCI devices which operate in HCI_USER_CHANNEL mode to receive
> frames if the HCI device is is HCI_INIT state.
> 
> [1] https://www.spinics.net/lists/linux-bluetooth/msg37345.html
> 
> Fixes: 23500189d7e0 ("Bluetooth: Introduce new HCI socket channel for user operation")
> Signed-off-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
> ---
> Changelog:
> v2:
> * change test logic to transfer packets when in INIT phase
>  for user channel mode as recommended by Marcel
> * renamed patch from
>  "Bluetooth: hci_core: fix init with HCI_QUIRK_NON_PERSISTENT_SETUP"
> 
> v1:
> * https://lkml.org/lkml/2019/10/3/2250
> 
> Some more background on the change follows:
> 
> The Android bluetooth stack (Bluedroid) also has a HAL implementation
> which follows Linux's standard rfkill interface [1].
> 
> This implementation relies on the HCI_CHANNEL_USER feature to get
> exclusive access to the underlying bluetooth device.
> 
> When testing this along with the btkmtksdio driver, the
> chip appeared unresponsive when calling the following from userspace:
> 
>    struct sockaddr_hci addr;
>    int fd;
> 
>    fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
> 
>    memset(&addr, 0, sizeof(addr));
>    addr.hci_family = AF_BLUETOOTH;
>    addr.hci_dev = 0;
>    addr.hci_channel = HCI_CHANNEL_USER;
> 
>    bind(fd, (struct sockaddr *) &addr, sizeof(addr)); # device hangs
> 
> In the case of bluetooth drivers exposing QUIRK_NON_PERSISTENT_SETUP
> such as btmtksdio, setup() is called each multiple times.
> In particular, when userspace calls bind(), the setup() is called again
> and vendor specific commands might be send to re-initialize the chip.
> 
> Those commands are filtered out by hci_core in HCI_CHANNEL_USER mode,
> preventing setup() from completing successfully.
> 
> This has been tested on a 4.19 kernel based on Android Common Kernel.
> It has also been compile tested on bluetooth-next.
> 
> [1] https://android.googlesource.com/platform/system/bt/+/refs/heads/master/vendor_libs/linux/interface/
> 
> net/bluetooth/hci_core.c | 9 ++++++++-
> 1 file changed, 8 insertions(+), 1 deletion(-)

patch has been applied to bluetooth-next tree.

Regards

Marcel


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2019-10-17  5:12 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-10-04  0:09 [PATCH] Bluetooth: hci_core: fix init with HCI_QUIRK_NON_PERSISTENT_SETUP Mattijs Korpershoek
2019-10-16 19:27 ` Marcel Holtmann
2019-10-16 19:53   ` Mattijs Korpershoek
2019-10-17  3:20   ` [PATCH v2] Bluetooth: hci_core: fix init for HCI_USER_CHANNEL Mattijs Korpershoek
2019-10-17  5:11     ` Marcel Holtmann

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).