From bb23f07cb63975968bbabe314486e2b087234fc5 Mon Sep 17 00:00:00 2001 From: Dan Gora Date: Tue, 9 May 2023 12:51:19 -0700 Subject: [PATCH 01/16] Bluetooth: btrtl: Add missing MODULE_FIRMWARE declarations Add missing MODULE_FIRMWARE declarations for firmware referenced in btrtl.c. Signed-off-by: Dan Gora Signed-off-by: Luiz Augusto von Dentz Signed-off-by: Jakub Kicinski --- drivers/bluetooth/btrtl.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/bluetooth/btrtl.c b/drivers/bluetooth/btrtl.c index 2915c82d719d..d978e7cea873 100644 --- a/drivers/bluetooth/btrtl.c +++ b/drivers/bluetooth/btrtl.c @@ -1367,14 +1367,30 @@ MODULE_FIRMWARE("rtl_bt/rtl8723cs_vf_fw.bin"); MODULE_FIRMWARE("rtl_bt/rtl8723cs_vf_config.bin"); MODULE_FIRMWARE("rtl_bt/rtl8723cs_xx_fw.bin"); MODULE_FIRMWARE("rtl_bt/rtl8723cs_xx_config.bin"); +MODULE_FIRMWARE("rtl_bt/rtl8723d_fw.bin"); +MODULE_FIRMWARE("rtl_bt/rtl8723d_config.bin"); MODULE_FIRMWARE("rtl_bt/rtl8723ds_fw.bin"); MODULE_FIRMWARE("rtl_bt/rtl8723ds_config.bin"); MODULE_FIRMWARE("rtl_bt/rtl8761a_fw.bin"); MODULE_FIRMWARE("rtl_bt/rtl8761a_config.bin"); +MODULE_FIRMWARE("rtl_bt/rtl8761b_fw.bin"); +MODULE_FIRMWARE("rtl_bt/rtl8761b_config.bin"); +MODULE_FIRMWARE("rtl_bt/rtl8761bu_fw.bin"); +MODULE_FIRMWARE("rtl_bt/rtl8761bu_config.bin"); MODULE_FIRMWARE("rtl_bt/rtl8821a_fw.bin"); MODULE_FIRMWARE("rtl_bt/rtl8821a_config.bin"); +MODULE_FIRMWARE("rtl_bt/rtl8821c_fw.bin"); +MODULE_FIRMWARE("rtl_bt/rtl8821c_config.bin"); +MODULE_FIRMWARE("rtl_bt/rtl8821cs_fw.bin"); +MODULE_FIRMWARE("rtl_bt/rtl8821cs_config.bin"); MODULE_FIRMWARE("rtl_bt/rtl8822b_fw.bin"); MODULE_FIRMWARE("rtl_bt/rtl8822b_config.bin"); +MODULE_FIRMWARE("rtl_bt/rtl8822cs_fw.bin"); +MODULE_FIRMWARE("rtl_bt/rtl8822cs_config.bin"); +MODULE_FIRMWARE("rtl_bt/rtl8822cu_fw.bin"); +MODULE_FIRMWARE("rtl_bt/rtl8822cu_config.bin"); +MODULE_FIRMWARE("rtl_bt/rtl8851bu_fw.bin"); +MODULE_FIRMWARE("rtl_bt/rtl8851bu_config.bin"); MODULE_FIRMWARE("rtl_bt/rtl8852au_fw.bin"); MODULE_FIRMWARE("rtl_bt/rtl8852au_config.bin"); MODULE_FIRMWARE("rtl_bt/rtl8852bs_fw.bin"); @@ -1383,5 +1399,3 @@ MODULE_FIRMWARE("rtl_bt/rtl8852bu_fw.bin"); MODULE_FIRMWARE("rtl_bt/rtl8852bu_config.bin"); MODULE_FIRMWARE("rtl_bt/rtl8852cu_fw.bin"); MODULE_FIRMWARE("rtl_bt/rtl8852cu_config.bin"); -MODULE_FIRMWARE("rtl_bt/rtl8851bu_fw.bin"); -MODULE_FIRMWARE("rtl_bt/rtl8851bu_config.bin"); From 022b6101c28a33fa8073b284423b88dc46b03d87 Mon Sep 17 00:00:00 2001 From: Dan Gora Date: Tue, 9 May 2023 12:45:24 -0700 Subject: [PATCH 02/16] Bluetooth: btusb: Add device 6655:8771 to device tables This device is an Inspire branded BT 5.1 USB dongle with a Realtek RTL8761BU chip using the "Best Buy China" vendor ID. The device table is as follows: T: Bus=01 Lev=01 Prnt=02 Port=09 Cnt=01 Dev#= 7 Spd=12 MxCh= 0 D: Ver= 1.10 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=6655 ProdID=8771 Rev=02.00 S: Manufacturer=Realtek S: Product=Bluetooth Radio S: SerialNumber=00E04C239987 C: #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=500mA I: If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms I: If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms Signed-off-by: Dan Gora Signed-off-by: Luiz Augusto von Dentz Signed-off-by: Jakub Kicinski --- drivers/bluetooth/btusb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 2a8e2bb038f5..0b0a02cf0d4a 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -655,6 +655,8 @@ static const struct usb_device_id blacklist_table[] = { BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0bda, 0x8771), .driver_info = BTUSB_REALTEK | BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x6655, 0x8771), .driver_info = BTUSB_REALTEK | + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x7392, 0xc611), .driver_info = BTUSB_REALTEK | BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x2b89, 0x8761), .driver_info = BTUSB_REALTEK | From 8153b738bc547878a017889d2b1cf8dd2de0e0c6 Mon Sep 17 00:00:00 2001 From: Min-Hua Chen Date: Fri, 19 May 2023 18:43:23 +0800 Subject: [PATCH 03/16] Bluetooth: btqca: use le32_to_cpu for ver.soc_id Use le32_to_cpu for ver.soc_id to fix the following sparse warning. drivers/bluetooth/btqca.c:640:24: sparse: warning: restricted __le32 degrades to integer Signed-off-by: Min-Hua Chen Signed-off-by: Luiz Augusto von Dentz Signed-off-by: Jakub Kicinski --- drivers/bluetooth/btqca.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c index fd0941fe8608..e7e58a956d15 100644 --- a/drivers/bluetooth/btqca.c +++ b/drivers/bluetooth/btqca.c @@ -637,7 +637,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, snprintf(config.fwname, sizeof(config.fwname), "qca/%s", firmware_name); else if (qca_is_wcn399x(soc_type)) { - if (ver.soc_id == QCA_WCN3991_SOC_ID) { + if (le32_to_cpu(ver.soc_id) == QCA_WCN3991_SOC_ID) { snprintf(config.fwname, sizeof(config.fwname), "qca/crnv%02xu.bin", rom_ver); } else { From f752a0b334bb95fe9b42ecb511e0864e2768046f Mon Sep 17 00:00:00 2001 From: Zhengping Jiang Date: Wed, 24 May 2023 17:04:15 -0700 Subject: [PATCH 04/16] Bluetooth: L2CAP: Fix use-after-free Fix potential use-after-free in l2cap_le_command_rej. Signed-off-by: Zhengping Jiang Signed-off-by: Luiz Augusto von Dentz Signed-off-by: Jakub Kicinski --- net/bluetooth/l2cap_core.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index c5e8798e297c..17ca13e8c044 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -6374,9 +6374,14 @@ static inline int l2cap_le_command_rej(struct l2cap_conn *conn, if (!chan) goto done; + chan = l2cap_chan_hold_unless_zero(chan); + if (!chan) + goto done; + l2cap_chan_lock(chan); l2cap_chan_del(chan, ECONNREFUSED); l2cap_chan_unlock(chan); + l2cap_chan_put(chan); done: mutex_unlock(&conn->chan_lock); From 0cb7365850bacb8c2a9975cae672d65714d8daa1 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 31 May 2023 11:04:23 +0200 Subject: [PATCH 05/16] Bluetooth: fix invalid-bdaddr quirk for non-persistent setup Devices that lack persistent storage for the device address can indicate this by setting the HCI_QUIRK_INVALID_BDADDR which causes the controller to be marked as unconfigured until user space has set a valid address. Once configured, the device address must be set on every setup for controllers with HCI_QUIRK_NON_PERSISTENT_SETUP to avoid marking the controller as unconfigured and requiring the address to be set again. Fixes: 740011cfe948 ("Bluetooth: Add new quirk for non-persistent setup settings") Signed-off-by: Johan Hovold Signed-off-by: Luiz Augusto von Dentz Signed-off-by: Jakub Kicinski --- net/bluetooth/hci_sync.c | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c index 804cde43b4e0..b5b1b610df33 100644 --- a/net/bluetooth/hci_sync.c +++ b/net/bluetooth/hci_sync.c @@ -4626,23 +4626,17 @@ static int hci_dev_setup_sync(struct hci_dev *hdev) invalid_bdaddr = test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); if (!ret) { - if (test_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks)) { - if (!bacmp(&hdev->public_addr, BDADDR_ANY)) - hci_dev_get_bd_addr_from_property(hdev); + if (test_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks) && + !bacmp(&hdev->public_addr, BDADDR_ANY)) + hci_dev_get_bd_addr_from_property(hdev); - if (bacmp(&hdev->public_addr, BDADDR_ANY) && - hdev->set_bdaddr) { - ret = hdev->set_bdaddr(hdev, - &hdev->public_addr); - - /* If setting of the BD_ADDR from the device - * property succeeds, then treat the address - * as valid even if the invalid BD_ADDR - * quirk indicates otherwise. - */ - if (!ret) - invalid_bdaddr = false; - } + if ((invalid_bdaddr || + test_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks)) && + bacmp(&hdev->public_addr, BDADDR_ANY) && + hdev->set_bdaddr) { + ret = hdev->set_bdaddr(hdev, &hdev->public_addr); + if (!ret) + invalid_bdaddr = false; } } From 6945795bc81ab7be22750ecfb365056688f2fada Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 31 May 2023 11:04:24 +0200 Subject: [PATCH 06/16] Bluetooth: fix use-bdaddr-property quirk Devices that lack persistent storage for the device address can indicate this by setting the HCI_QUIRK_INVALID_BDADDR which causes the controller to be marked as unconfigured until user space has set a valid address. The related HCI_QUIRK_USE_BDADDR_PROPERTY was later added to similarly indicate that the device lacks a valid address but that one may be specified in the devicetree. As is clear from commit 7a0e5b15ca45 ("Bluetooth: Add quirk for reading BD_ADDR from fwnode property") that added and documented this quirk and commits like de79a9df1692 ("Bluetooth: btqcomsmd: use HCI_QUIRK_USE_BDADDR_PROPERTY"), the device address of controllers with this flag should be treated as invalid until user space has had a chance to configure the controller in case the devicetree property is missing. As it does not make sense to allow controllers with invalid addresses, restore the original semantics, which also makes sure that the implementation is consistent (e.g. get_missing_options() indicates that the address must be set) and matches the documentation (including comments in the code, such as, "In case any of them is set, the controller has to start up as unconfigured."). Fixes: e668eb1e1578 ("Bluetooth: hci_core: Don't stop BT if the BD address missing in dts") Signed-off-by: Johan Hovold Signed-off-by: Luiz Augusto von Dentz Signed-off-by: Jakub Kicinski --- net/bluetooth/hci_sync.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c index b5b1b610df33..8561616abbe5 100644 --- a/net/bluetooth/hci_sync.c +++ b/net/bluetooth/hci_sync.c @@ -4623,16 +4623,14 @@ static int hci_dev_setup_sync(struct hci_dev *hdev) * BD_ADDR invalid before creating the HCI device or in * its setup callback. */ - invalid_bdaddr = test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); - + invalid_bdaddr = test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) || + test_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks); if (!ret) { if (test_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks) && !bacmp(&hdev->public_addr, BDADDR_ANY)) hci_dev_get_bd_addr_from_property(hdev); - if ((invalid_bdaddr || - test_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks)) && - bacmp(&hdev->public_addr, BDADDR_ANY) && + if (invalid_bdaddr && bacmp(&hdev->public_addr, BDADDR_ANY) && hdev->set_bdaddr) { ret = hdev->set_bdaddr(hdev, &hdev->public_addr); if (!ret) From 1728137b33c00d5a2b5110ed7aafb42e7c32e4a1 Mon Sep 17 00:00:00 2001 From: Sungwoo Kim Date: Wed, 31 May 2023 01:39:56 -0400 Subject: [PATCH 07/16] Bluetooth: L2CAP: Fix use-after-free in l2cap_sock_ready_cb l2cap_sock_release(sk) frees sk. However, sk's children are still alive and point to the already free'd sk's address. To fix this, l2cap_sock_release(sk) also cleans sk's children. ================================================================== BUG: KASAN: use-after-free in l2cap_sock_ready_cb+0xb7/0x100 net/bluetooth/l2cap_sock.c:1650 Read of size 8 at addr ffff888104617aa8 by task kworker/u3:0/276 CPU: 0 PID: 276 Comm: kworker/u3:0 Not tainted 6.2.0-00001-gef397bd4d5fb-dirty #59 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014 Workqueue: hci2 hci_rx_work Call Trace: __dump_stack lib/dump_stack.c:88 [inline] dump_stack_lvl+0x72/0x95 lib/dump_stack.c:106 print_address_description mm/kasan/report.c:306 [inline] print_report+0x175/0x478 mm/kasan/report.c:417 kasan_report+0xb1/0x130 mm/kasan/report.c:517 l2cap_sock_ready_cb+0xb7/0x100 net/bluetooth/l2cap_sock.c:1650 l2cap_chan_ready+0x10e/0x1e0 net/bluetooth/l2cap_core.c:1386 l2cap_config_req+0x753/0x9f0 net/bluetooth/l2cap_core.c:4480 l2cap_bredr_sig_cmd net/bluetooth/l2cap_core.c:5739 [inline] l2cap_sig_channel net/bluetooth/l2cap_core.c:6509 [inline] l2cap_recv_frame+0xe2e/0x43c0 net/bluetooth/l2cap_core.c:7788 l2cap_recv_acldata+0x6ed/0x7e0 net/bluetooth/l2cap_core.c:8506 hci_acldata_packet net/bluetooth/hci_core.c:3813 [inline] hci_rx_work+0x66e/0xbc0 net/bluetooth/hci_core.c:4048 process_one_work+0x4ea/0x8e0 kernel/workqueue.c:2289 worker_thread+0x364/0x8e0 kernel/workqueue.c:2436 kthread+0x1b9/0x200 kernel/kthread.c:376 ret_from_fork+0x2c/0x50 arch/x86/entry/entry_64.S:308 Allocated by task 288: kasan_save_stack+0x22/0x50 mm/kasan/common.c:45 kasan_set_track+0x25/0x30 mm/kasan/common.c:52 ____kasan_kmalloc mm/kasan/common.c:374 [inline] __kasan_kmalloc+0x82/0x90 mm/kasan/common.c:383 kasan_kmalloc include/linux/kasan.h:211 [inline] __do_kmalloc_node mm/slab_common.c:968 [inline] __kmalloc+0x5a/0x140 mm/slab_common.c:981 kmalloc include/linux/slab.h:584 [inline] sk_prot_alloc+0x113/0x1f0 net/core/sock.c:2040 sk_alloc+0x36/0x3c0 net/core/sock.c:2093 l2cap_sock_alloc.constprop.0+0x39/0x1c0 net/bluetooth/l2cap_sock.c:1852 l2cap_sock_create+0x10d/0x220 net/bluetooth/l2cap_sock.c:1898 bt_sock_create+0x183/0x290 net/bluetooth/af_bluetooth.c:132 __sock_create+0x226/0x380 net/socket.c:1518 sock_create net/socket.c:1569 [inline] __sys_socket_create net/socket.c:1606 [inline] __sys_socket_create net/socket.c:1591 [inline] __sys_socket+0x112/0x200 net/socket.c:1639 __do_sys_socket net/socket.c:1652 [inline] __se_sys_socket net/socket.c:1650 [inline] __x64_sys_socket+0x40/0x50 net/socket.c:1650 do_syscall_x64 arch/x86/entry/common.c:50 [inline] do_syscall_64+0x3f/0x90 arch/x86/entry/common.c:80 entry_SYSCALL_64_after_hwframe+0x72/0xdc Freed by task 288: kasan_save_stack+0x22/0x50 mm/kasan/common.c:45 kasan_set_track+0x25/0x30 mm/kasan/common.c:52 kasan_save_free_info+0x2e/0x50 mm/kasan/generic.c:523 ____kasan_slab_free mm/kasan/common.c:236 [inline] ____kasan_slab_free mm/kasan/common.c:200 [inline] __kasan_slab_free+0x10a/0x190 mm/kasan/common.c:244 kasan_slab_free include/linux/kasan.h:177 [inline] slab_free_hook mm/slub.c:1781 [inline] slab_free_freelist_hook mm/slub.c:1807 [inline] slab_free mm/slub.c:3787 [inline] __kmem_cache_free+0x88/0x1f0 mm/slub.c:3800 sk_prot_free net/core/sock.c:2076 [inline] __sk_destruct+0x347/0x430 net/core/sock.c:2168 sk_destruct+0x9c/0xb0 net/core/sock.c:2183 __sk_free+0x82/0x220 net/core/sock.c:2194 sk_free+0x7c/0xa0 net/core/sock.c:2205 sock_put include/net/sock.h:1991 [inline] l2cap_sock_kill+0x256/0x2b0 net/bluetooth/l2cap_sock.c:1257 l2cap_sock_release+0x1a7/0x220 net/bluetooth/l2cap_sock.c:1428 __sock_release+0x80/0x150 net/socket.c:650 sock_close+0x19/0x30 net/socket.c:1368 __fput+0x17a/0x5c0 fs/file_table.c:320 task_work_run+0x132/0x1c0 kernel/task_work.c:179 resume_user_mode_work include/linux/resume_user_mode.h:49 [inline] exit_to_user_mode_loop kernel/entry/common.c:171 [inline] exit_to_user_mode_prepare+0x113/0x120 kernel/entry/common.c:203 __syscall_exit_to_user_mode_work kernel/entry/common.c:285 [inline] syscall_exit_to_user_mode+0x21/0x50 kernel/entry/common.c:296 do_syscall_64+0x4c/0x90 arch/x86/entry/common.c:86 entry_SYSCALL_64_after_hwframe+0x72/0xdc The buggy address belongs to the object at ffff888104617800 which belongs to the cache kmalloc-1k of size 1024 The buggy address is located 680 bytes inside of 1024-byte region [ffff888104617800, ffff888104617c00) The buggy address belongs to the physical page: page:00000000dbca6a80 refcount:1 mapcount:0 mapping:0000000000000000 index:0xffff888104614000 pfn:0x104614 head:00000000dbca6a80 order:2 compound_mapcount:0 subpages_mapcount:0 compound_pincount:0 flags: 0x200000000010200(slab|head|node=0|zone=2) raw: 0200000000010200 ffff888100041dc0 ffffea0004212c10 ffffea0004234b10 raw: ffff888104614000 0000000000080002 00000001ffffffff 0000000000000000 page dumped because: kasan: bad access detected Memory state around the buggy address: ffff888104617980: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ffff888104617a00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb >ffff888104617a80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ^ ffff888104617b00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ffff888104617b80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ================================================================== Ack: This bug is found by FuzzBT with a modified Syzkaller. Other contributors are Ruoyu Wu and Hui Peng. Signed-off-by: Sungwoo Kim Signed-off-by: Luiz Augusto von Dentz Signed-off-by: Jakub Kicinski --- net/bluetooth/l2cap_sock.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index eebe256104bc..947ca580bb9a 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -46,6 +46,7 @@ static const struct proto_ops l2cap_sock_ops; static void l2cap_sock_init(struct sock *sk, struct sock *parent); static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio, int kern); +static void l2cap_sock_cleanup_listen(struct sock *parent); bool l2cap_is_socket(struct socket *sock) { @@ -1415,6 +1416,7 @@ static int l2cap_sock_release(struct socket *sock) if (!sk) return 0; + l2cap_sock_cleanup_listen(sk); bt_sock_unlink(&l2cap_sk_list, sk); err = l2cap_sock_shutdown(sock, SHUT_RDWR); From 56b7f325db139c9255b1eb1d1e741576d5f8fa34 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 2 Jun 2023 10:19:12 +0200 Subject: [PATCH 08/16] Bluetooth: hci_bcm: do not mark valid bd_addr as invalid A recent commit restored the original (and still documented) semantics for the HCI_QUIRK_USE_BDADDR_PROPERTY quirk so that the device address is considered invalid unless an address is provided by firmware. This specifically means that this flag must only be set for devices with invalid addresses, but the Broadcom driver has so far been setting this flag unconditionally. Fortunately the driver already checks for invalid addresses during setup and sets the HCI_QUIRK_INVALID_BDADDR flag. Use this flag to indicate when the address can be overridden by firmware (long term, this should probably just always be allowed). Fixes: 6945795bc81a ("Bluetooth: fix use-bdaddr-property quirk") Reported-by: Marek Szyprowski Link: https://lore.kernel.org/lkml/ecef83c8-497f-4011-607b-a63c24764867@samsung.com Signed-off-by: Johan Hovold Tested-by: Marek Szyprowski Signed-off-by: Luiz Augusto von Dentz Signed-off-by: Jakub Kicinski --- drivers/bluetooth/hci_bcm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index 83bf5d4330c4..874d23089b39 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -643,7 +643,8 @@ static int bcm_setup(struct hci_uart *hu) * Allow the bootloader to set a valid address through the * device tree. */ - set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hu->hdev->quirks); + if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hu->hdev->quirks)) + set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hu->hdev->quirks); if (!bcm_request_irq(bcm)) err = bcm_setup_sleep(hu); From 6b9545dc9f8ff01d8bc1229103960d9cd265343f Mon Sep 17 00:00:00 2001 From: Pauli Virtanen Date: Thu, 1 Jun 2023 09:34:43 +0300 Subject: [PATCH 09/16] Bluetooth: ISO: use hci_sync for setting CIG parameters When reconfiguring CIG after disconnection of the last CIS, LE Remove CIG shall be sent before LE Set CIG Parameters. Otherwise, it fails because CIG is in the inactive state and not configurable (Core v5.3 Vol 6 Part B Sec. 4.5.14.3). This ordering is currently wrong under suitable timing conditions, because LE Remove CIG is sent via the hci_sync queue and may be delayed, but Set CIG Parameters is via hci_send_cmd. Make the ordering well-defined by sending also Set CIG Parameters via hci_sync. Fixes: 26afbd826ee3 ("Bluetooth: Add initial implementation of CIS connections") Signed-off-by: Pauli Virtanen Signed-off-by: Luiz Augusto von Dentz Signed-off-by: Jakub Kicinski --- net/bluetooth/hci_conn.c | 47 +++++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 1ef952bda97d..2275e0d9f841 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -775,6 +775,11 @@ static void le_conn_timeout(struct work_struct *work) hci_abort_conn(conn, HCI_ERROR_REMOTE_USER_TERM); } +struct iso_cig_params { + struct hci_cp_le_set_cig_params cp; + struct hci_cis_params cis[0x1f]; +}; + struct iso_list_data { union { u8 cig; @@ -786,10 +791,7 @@ struct iso_list_data { u16 sync_handle; }; int count; - struct { - struct hci_cp_le_set_cig_params cp; - struct hci_cis_params cis[0x11]; - } pdu; + struct iso_cig_params pdu; }; static void bis_list(struct hci_conn *conn, void *data) @@ -1764,10 +1766,33 @@ static int hci_le_create_big(struct hci_conn *conn, struct bt_iso_qos *qos) return hci_send_cmd(hdev, HCI_OP_LE_CREATE_BIG, sizeof(cp), &cp); } +static void set_cig_params_complete(struct hci_dev *hdev, void *data, int err) +{ + struct iso_cig_params *pdu = data; + + bt_dev_dbg(hdev, ""); + + if (err) + bt_dev_err(hdev, "Unable to set CIG parameters: %d", err); + + kfree(pdu); +} + +static int set_cig_params_sync(struct hci_dev *hdev, void *data) +{ + struct iso_cig_params *pdu = data; + u32 plen; + + plen = sizeof(pdu->cp) + pdu->cp.num_cis * sizeof(pdu->cis[0]); + return __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_CIG_PARAMS, plen, pdu, + HCI_CMD_TIMEOUT); +} + static bool hci_le_set_cig_params(struct hci_conn *conn, struct bt_iso_qos *qos) { struct hci_dev *hdev = conn->hdev; struct iso_list_data data; + struct iso_cig_params *pdu; memset(&data, 0, sizeof(data)); @@ -1837,12 +1862,18 @@ static bool hci_le_set_cig_params(struct hci_conn *conn, struct bt_iso_qos *qos) if (qos->ucast.cis == BT_ISO_QOS_CIS_UNSET || !data.pdu.cp.num_cis) return false; - if (hci_send_cmd(hdev, HCI_OP_LE_SET_CIG_PARAMS, - sizeof(data.pdu.cp) + - (data.pdu.cp.num_cis * sizeof(*data.pdu.cis)), - &data.pdu) < 0) + pdu = kzalloc(sizeof(*pdu), GFP_KERNEL); + if (!pdu) return false; + memcpy(pdu, &data.pdu, sizeof(*pdu)); + + if (hci_cmd_sync_queue(hdev, set_cig_params_sync, pdu, + set_cig_params_complete) < 0) { + kfree(pdu); + return false; + } + return true; } From db9cbcadc16e8b9f0b3ef5870f3a38ebafcbe8e0 Mon Sep 17 00:00:00 2001 From: Pauli Virtanen Date: Sat, 3 Jun 2023 00:28:12 +0300 Subject: [PATCH 10/16] Bluetooth: hci_event: fix Set CIG Parameters error status handling If the event has error status, return right error code and don't show incorrect "response malformed" messages. Signed-off-by: Pauli Virtanen Signed-off-by: Luiz Augusto von Dentz Signed-off-by: Jakub Kicinski --- net/bluetooth/hci_event.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 09ba6d8987ee..1d493eefaabe 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -3812,7 +3812,8 @@ static u8 hci_cc_le_set_cig_params(struct hci_dev *hdev, void *data, bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_CIG_PARAMS); - if (!cp || rp->num_handles != cp->num_cis || rp->cig_id != cp->cig_id) { + if (!rp->status && (!cp || rp->num_handles != cp->num_cis || + rp->cig_id != cp->cig_id)) { bt_dev_err(hdev, "unexpected Set CIG Parameters response data"); status = HCI_ERROR_UNSPECIFIED; } From 73f55453ea5236a586a7f1b3d5e2ee051d655351 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Wed, 7 Jun 2023 12:33:47 -0700 Subject: [PATCH 11/16] Bluetooth: MGMT: Fix marking SCAN_RSP as not connectable When receiving a scan response there is no way to know if the remote device is connectable or not, so when it cannot be merged don't make any assumption and instead just mark it with a new flag defined as MGMT_DEV_FOUND_SCAN_RSP so userspace can tell it is a standalone SCAN_RSP. Link: https://lore.kernel.org/linux-bluetooth/CABBYNZ+CYMsDSPTxBn09Js3BcdC-x7vZFfyLJ3ppZGGwJKmUTw@mail.gmail.com/ Fixes: c70a7e4cc8d2 ("Bluetooth: Add support for Not Connectable flag for Device Found events") Signed-off-by: Luiz Augusto von Dentz Signed-off-by: Jakub Kicinski --- include/net/bluetooth/mgmt.h | 1 + net/bluetooth/hci_event.c | 15 +++++---------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index a5801649f619..5e68b3dd4422 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h @@ -979,6 +979,7 @@ struct mgmt_ev_auth_failed { #define MGMT_DEV_FOUND_NOT_CONNECTABLE BIT(2) #define MGMT_DEV_FOUND_INITIATED_CONN BIT(3) #define MGMT_DEV_FOUND_NAME_REQUEST_FAILED BIT(4) +#define MGMT_DEV_FOUND_SCAN_RSP BIT(5) #define MGMT_EV_DEVICE_FOUND 0x0012 struct mgmt_ev_device_found { diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 1d493eefaabe..2383153d5345 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -6317,23 +6317,18 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr, return; } - /* When receiving non-connectable or scannable undirected - * advertising reports, this means that the remote device is - * not connectable and then clearly indicate this in the - * device found event. - * - * When receiving a scan response, then there is no way to + /* When receiving a scan response, then there is no way to * know if the remote device is connectable or not. However * since scan responses are merged with a previously seen * advertising report, the flags field from that report * will be used. * - * In the really unlikely case that a controller get confused - * and just sends a scan response event, then it is marked as - * not connectable as well. + * In the unlikely case that a controller just sends a scan + * response event that doesn't match the pending report, then + * it is marked as a standalone SCAN_RSP. */ if (type == LE_ADV_SCAN_RSP) - flags = MGMT_DEV_FOUND_NOT_CONNECTABLE; + flags = MGMT_DEV_FOUND_SCAN_RSP; /* If there's nothing pending either store the data from this * event or send an immediate device found event if the data From 14f0dceca60b2fc4f2388505b25f9e6f71785e05 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Thu, 8 Jun 2023 11:12:18 -0700 Subject: [PATCH 12/16] Bluetooth: ISO: Rework sync_interval to be sync_factor This rework sync_interval to be sync_factor as having sync_interval in the order of seconds is sometimes not disarable. Wit sync_factor the application can tell how many SDU intervals it wants to send an announcement with PA, the EA interval is set to 2 times that so a factor of 24 of BIG SDU interval of 10ms would look like the following: < HCI Command: LE Set Extended Advertising Parameters (0x08|0x0036) plen 25 Handle: 0x01 Properties: 0x0000 Min advertising interval: 480.000 msec (0x0300) Max advertising interval: 480.000 msec (0x0300) Channel map: 37, 38, 39 (0x07) Own address type: Random (0x01) Peer address type: Public (0x00) Peer address: 00:00:00:00:00:00 (OUI 00-00-00) Filter policy: Allow Scan Request from Any, Allow Connect Request from Any (0x00) TX power: Host has no preference (0x7f) Primary PHY: LE 1M (0x01) Secondary max skip: 0x00 Secondary PHY: LE 2M (0x02) SID: 0x00 Scan request notifications: Disabled (0x00) < HCI Command: LE Set Periodic Advertising Parameters (0x08|0x003e) plen 7 Handle: 1 Min interval: 240.00 msec (0x00c0) Max interval: 240.00 msec (0x00c0) Properties: 0x0000 Signed-off-by: Luiz Augusto von Dentz Signed-off-by: Jakub Kicinski --- include/net/bluetooth/bluetooth.h | 2 +- net/bluetooth/hci_conn.c | 4 ++-- net/bluetooth/iso.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index 1b4230cd42a3..af729859385e 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -185,7 +185,7 @@ struct bt_iso_ucast_qos { struct bt_iso_bcast_qos { __u8 big; __u8 bis; - __u8 sync_interval; + __u8 sync_factor; __u8 packing; __u8 framing; struct bt_iso_io_qos in; diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 2275e0d9f841..24407a974b9c 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -2075,10 +2075,10 @@ static int create_big_sync(struct hci_dev *hdev, void *data) flags |= MGMT_ADV_FLAG_SEC_2M; /* Align intervals */ - interval = qos->bcast.out.interval / 1250; + interval = (qos->bcast.out.interval / 1250) * qos->bcast.sync_factor; if (qos->bcast.bis) - sync_interval = qos->bcast.sync_interval * 1600; + sync_interval = interval * 4; err = hci_start_per_adv_sync(hdev, qos->bcast.bis, conn->le_per_adv_data_len, conn->le_per_adv_data, flags, interval, diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c index 34d55a85d8f6..0e6cc57b3911 100644 --- a/net/bluetooth/iso.c +++ b/net/bluetooth/iso.c @@ -704,7 +704,7 @@ static struct bt_iso_qos default_qos = { .bcast = { .big = BT_ISO_QOS_BIG_UNSET, .bis = BT_ISO_QOS_BIS_UNSET, - .sync_interval = 0x00, + .sync_factor = 0x01, .packing = 0x00, .framing = 0x00, .in = DEFAULT_IO_QOS, @@ -1213,7 +1213,7 @@ static bool check_ucast_qos(struct bt_iso_qos *qos) static bool check_bcast_qos(struct bt_iso_qos *qos) { - if (qos->bcast.sync_interval > 0x07) + if (qos->bcast.sync_factor == 0x00) return false; if (qos->bcast.packing > 0x01) From d40d6f52d5bbbd7aa7092ba9fa793ad7dc253a35 Mon Sep 17 00:00:00 2001 From: Ivan Orlov Date: Tue, 20 Jun 2023 16:40:52 +0200 Subject: [PATCH 13/16] Bluetooth: hci_sysfs: make bt_class a static const structure Now that the driver core allows for struct class to be in read-only memory, move the bt_class structure to be declared at build time placing it into read-only memory, instead of having to be dynamically allocated at load time. Cc: Marcel Holtmann Cc: Johan Hedberg Cc: Luiz Augusto von Dentz Cc: linux-bluetooth@vger.kernel.org Suggested-by: Greg Kroah-Hartman Signed-off-by: Ivan Orlov Signed-off-by: Greg Kroah-Hartman Signed-off-by: Luiz Augusto von Dentz Signed-off-by: Jakub Kicinski --- net/bluetooth/hci_sysfs.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index 2934d7f4d564..15b33579007c 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c @@ -6,7 +6,9 @@ #include #include -static struct class *bt_class; +static const struct class bt_class = { + .name = "bluetooth", +}; static void bt_link_release(struct device *dev) { @@ -36,7 +38,7 @@ void hci_conn_init_sysfs(struct hci_conn *conn) BT_DBG("conn %p", conn); conn->dev.type = &bt_link; - conn->dev.class = bt_class; + conn->dev.class = &bt_class; conn->dev.parent = &hdev->dev; device_initialize(&conn->dev); @@ -104,7 +106,7 @@ void hci_init_sysfs(struct hci_dev *hdev) struct device *dev = &hdev->dev; dev->type = &bt_host; - dev->class = bt_class; + dev->class = &bt_class; __module_get(THIS_MODULE); device_initialize(dev); @@ -112,12 +114,10 @@ void hci_init_sysfs(struct hci_dev *hdev) int __init bt_sysfs_init(void) { - bt_class = class_create("bluetooth"); - - return PTR_ERR_OR_ZERO(bt_class); + return class_register(&bt_class); } void bt_sysfs_cleanup(void) { - class_destroy(bt_class); + class_unregister(&bt_class); } From fa01eba11f0e57c767a5eab5291c7a01407a00be Mon Sep 17 00:00:00 2001 From: Matthew Anderson Date: Sat, 24 Jun 2023 12:08:10 -0500 Subject: [PATCH 14/16] Bluetooth: btusb: Add MT7922 bluetooth ID for the Asus Ally Adding the device ID from the Asus Ally gets the bluetooth working on the device. Signed-off-by: Matthew Anderson Signed-off-by: Luiz Augusto von Dentz Signed-off-by: Jakub Kicinski --- drivers/bluetooth/btusb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 0b0a02cf0d4a..5ec4ad0a5c86 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -613,6 +613,9 @@ static const struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x0489, 0xe0d9), .driver_info = BTUSB_MEDIATEK | BTUSB_WIDEBAND_SPEECH | BTUSB_VALID_LE_STATES }, + { USB_DEVICE(0x0489, 0xe0f5), .driver_info = BTUSB_MEDIATEK | + BTUSB_WIDEBAND_SPEECH | + BTUSB_VALID_LE_STATES }, { USB_DEVICE(0x13d3, 0x3568), .driver_info = BTUSB_MEDIATEK | BTUSB_WIDEBAND_SPEECH | BTUSB_VALID_LE_STATES }, From 5b6d345d1b65d67624349e5de22227492c637576 Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Sun, 25 Jun 2023 16:45:13 +0800 Subject: [PATCH 15/16] Bluetooth: hci_conn: Use kmemdup() to replace kzalloc + memcpy Use kmemdup rather than duplicating its implementation. ./net/bluetooth/hci_conn.c:1880:7-14: WARNING opportunity for kmemdup. Reported-by: Abaci Robot Closes: https://bugzilla.openanolis.cn/show_bug.cgi?id=5597 Signed-off-by: Jiapeng Chong Signed-off-by: Luiz Augusto von Dentz Signed-off-by: Jakub Kicinski --- net/bluetooth/hci_conn.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 24407a974b9c..056f9516e46d 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -1862,12 +1862,10 @@ static bool hci_le_set_cig_params(struct hci_conn *conn, struct bt_iso_qos *qos) if (qos->ucast.cis == BT_ISO_QOS_CIS_UNSET || !data.pdu.cp.num_cis) return false; - pdu = kzalloc(sizeof(*pdu), GFP_KERNEL); + pdu = kmemdup(&data.pdu, sizeof(*pdu), GFP_KERNEL); if (!pdu) return false; - memcpy(pdu, &data.pdu, sizeof(*pdu)); - if (hci_cmd_sync_queue(hdev, set_cig_params_sync, pdu, set_cig_params_complete) < 0) { kfree(pdu); From 2be22f1941d5f661aa8043261d1bae5b6696c749 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Tue, 20 Jun 2023 15:41:11 -0700 Subject: [PATCH 16/16] Bluetooth: hci_event: Fix parsing of CIS Established Event The ISO Interval on CIS Established Event uses 1.25 ms slots: BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 4, Part E page 2304: Time = N * 1.25 ms In addition to that this always update the QoS settings based on CIS Established Event. Signed-off-by: Luiz Augusto von Dentz Signed-off-by: Jakub Kicinski --- net/bluetooth/hci_event.c | 45 ++++++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 2383153d5345..95816a938cea 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -6786,6 +6786,7 @@ static void hci_le_cis_estabilished_evt(struct hci_dev *hdev, void *data, { struct hci_evt_le_cis_established *ev = data; struct hci_conn *conn; + struct bt_iso_qos *qos; u16 handle = __le16_to_cpu(ev->handle); bt_dev_dbg(hdev, "status 0x%2.2x", ev->status); @@ -6807,21 +6808,39 @@ static void hci_le_cis_estabilished_evt(struct hci_dev *hdev, void *data, goto unlock; } - if (conn->role == HCI_ROLE_SLAVE) { - __le32 interval; + qos = &conn->iso_qos; - memset(&interval, 0, sizeof(interval)); + /* Convert ISO Interval (1.25 ms slots) to SDU Interval (us) */ + qos->ucast.in.interval = le16_to_cpu(ev->interval) * 1250; + qos->ucast.out.interval = qos->ucast.in.interval; - memcpy(&interval, ev->c_latency, sizeof(ev->c_latency)); - conn->iso_qos.ucast.in.interval = le32_to_cpu(interval); - memcpy(&interval, ev->p_latency, sizeof(ev->p_latency)); - conn->iso_qos.ucast.out.interval = le32_to_cpu(interval); - conn->iso_qos.ucast.in.latency = le16_to_cpu(ev->interval); - conn->iso_qos.ucast.out.latency = le16_to_cpu(ev->interval); - conn->iso_qos.ucast.in.sdu = le16_to_cpu(ev->c_mtu); - conn->iso_qos.ucast.out.sdu = le16_to_cpu(ev->p_mtu); - conn->iso_qos.ucast.in.phy = ev->c_phy; - conn->iso_qos.ucast.out.phy = ev->p_phy; + switch (conn->role) { + case HCI_ROLE_SLAVE: + /* Convert Transport Latency (us) to Latency (msec) */ + qos->ucast.in.latency = + DIV_ROUND_CLOSEST(get_unaligned_le24(ev->c_latency), + 1000); + qos->ucast.out.latency = + DIV_ROUND_CLOSEST(get_unaligned_le24(ev->p_latency), + 1000); + qos->ucast.in.sdu = le16_to_cpu(ev->c_mtu); + qos->ucast.out.sdu = le16_to_cpu(ev->p_mtu); + qos->ucast.in.phy = ev->c_phy; + qos->ucast.out.phy = ev->p_phy; + break; + case HCI_ROLE_MASTER: + /* Convert Transport Latency (us) to Latency (msec) */ + qos->ucast.out.latency = + DIV_ROUND_CLOSEST(get_unaligned_le24(ev->c_latency), + 1000); + qos->ucast.in.latency = + DIV_ROUND_CLOSEST(get_unaligned_le24(ev->p_latency), + 1000); + qos->ucast.out.sdu = le16_to_cpu(ev->c_mtu); + qos->ucast.in.sdu = le16_to_cpu(ev->p_mtu); + qos->ucast.out.phy = ev->c_phy; + qos->ucast.in.phy = ev->p_phy; + break; } if (!ev->status) {