* [PATCH v2 2/5] Bluetooth: 6lowpan: fix BDADDR_LE vs ADDR_LE_DEV address type confusion
2025-11-03 18:29 [PATCH v2 1/5] Bluetooth: 6lowpan: reset link-local header on ipv6 recv path Pauli Virtanen
@ 2025-11-03 18:29 ` Pauli Virtanen
2025-11-03 18:29 ` [PATCH v2 3/5] Bluetooth: L2CAP: export l2cap_chan_hold for modules Pauli Virtanen
` (4 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Pauli Virtanen @ 2025-11-03 18:29 UTC (permalink / raw)
To: linux-bluetooth
Cc: Pauli Virtanen, marcel, johan.hedberg, luiz.dentz, linux-kernel,
Paul Menzel
Bluetooth 6lowpan.c confuses BDADDR_LE and ADDR_LE_DEV address types,
e.g. debugfs "connect" command takes the former, and "disconnect" and
"connect" to already connected device take the latter. This is due to
using same value both for l2cap_chan_connect and hci_conn_hash_lookup_le
which take different dst_type values.
Fix address type passed to hci_conn_hash_lookup_le().
Retain the debugfs API difference between "connect" and "disconnect"
commands since it's been like this since 2015 and nobody apparently
complained.
Fixes: f5ad4ffceba0 ("Bluetooth: 6lowpan: Use hci_conn_hash_lookup_le() when possible")
Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
Signed-off-by: Pauli Virtanen <pav@iki.fi>
---
Notes:
v2:
- no changes
net/bluetooth/6lowpan.c | 28 ++++++++++++++++++++++++----
1 file changed, 24 insertions(+), 4 deletions(-)
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
index f1d29fa4b411..0d8c2e2e9a6c 100644
--- a/net/bluetooth/6lowpan.c
+++ b/net/bluetooth/6lowpan.c
@@ -957,10 +957,11 @@ static struct l2cap_chan *bt_6lowpan_listen(void)
}
static int get_l2cap_conn(char *buf, bdaddr_t *addr, u8 *addr_type,
- struct l2cap_conn **conn)
+ struct l2cap_conn **conn, bool disconnect)
{
struct hci_conn *hcon;
struct hci_dev *hdev;
+ int le_addr_type;
int n;
n = sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx %hhu",
@@ -971,13 +972,32 @@ static int get_l2cap_conn(char *buf, bdaddr_t *addr, u8 *addr_type,
if (n < 7)
return -EINVAL;
+ if (disconnect) {
+ /* The "disconnect" debugfs command has used different address
+ * type constants than "connect" since 2015. Let's retain that
+ * for now even though it's obviously buggy...
+ */
+ *addr_type += 1;
+ }
+
+ switch (*addr_type) {
+ case BDADDR_LE_PUBLIC:
+ le_addr_type = ADDR_LE_DEV_PUBLIC;
+ break;
+ case BDADDR_LE_RANDOM:
+ le_addr_type = ADDR_LE_DEV_RANDOM;
+ break;
+ default:
+ return -EINVAL;
+ }
+
/* The LE_PUBLIC address type is ignored because of BDADDR_ANY */
hdev = hci_get_route(addr, BDADDR_ANY, BDADDR_LE_PUBLIC);
if (!hdev)
return -ENOENT;
hci_dev_lock(hdev);
- hcon = hci_conn_hash_lookup_le(hdev, addr, *addr_type);
+ hcon = hci_conn_hash_lookup_le(hdev, addr, le_addr_type);
hci_dev_unlock(hdev);
hci_dev_put(hdev);
@@ -1104,7 +1124,7 @@ static ssize_t lowpan_control_write(struct file *fp,
buf[buf_size] = '\0';
if (memcmp(buf, "connect ", 8) == 0) {
- ret = get_l2cap_conn(&buf[8], &addr, &addr_type, &conn);
+ ret = get_l2cap_conn(&buf[8], &addr, &addr_type, &conn, false);
if (ret == -EINVAL)
return ret;
@@ -1141,7 +1161,7 @@ static ssize_t lowpan_control_write(struct file *fp,
}
if (memcmp(buf, "disconnect ", 11) == 0) {
- ret = get_l2cap_conn(&buf[11], &addr, &addr_type, &conn);
+ ret = get_l2cap_conn(&buf[11], &addr, &addr_type, &conn, true);
if (ret < 0)
return ret;
--
2.51.1
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v2 3/5] Bluetooth: L2CAP: export l2cap_chan_hold for modules
2025-11-03 18:29 [PATCH v2 1/5] Bluetooth: 6lowpan: reset link-local header on ipv6 recv path Pauli Virtanen
2025-11-03 18:29 ` [PATCH v2 2/5] Bluetooth: 6lowpan: fix BDADDR_LE vs ADDR_LE_DEV address type confusion Pauli Virtanen
@ 2025-11-03 18:29 ` Pauli Virtanen
2025-11-04 10:44 ` Paul Menzel
2025-11-03 18:29 ` [PATCH v2 4/5] Bluetooth: 6lowpan: Don't hold spin lock over sleeping functions Pauli Virtanen
` (3 subsequent siblings)
5 siblings, 1 reply; 8+ messages in thread
From: Pauli Virtanen @ 2025-11-03 18:29 UTC (permalink / raw)
To: linux-bluetooth
Cc: Pauli Virtanen, marcel, johan.hedberg, luiz.dentz, linux-kernel
l2cap_chan_put() is exported, so export also l2cap_chan_hold() for
modules.
l2cap_chan_hold() has use case in net/bluetooth/6lowpan.c
Signed-off-by: Pauli Virtanen <pav@iki.fi>
---
Notes:
v2:
- New patch for v2
- Used for build fix with CONFIG_BT_6LOWPAN=m
net/bluetooth/l2cap_core.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index d08320380ad6..35c57657bcf4 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -497,6 +497,7 @@ void l2cap_chan_hold(struct l2cap_chan *c)
kref_get(&c->kref);
}
+EXPORT_SYMBOL_GPL(l2cap_chan_hold);
struct l2cap_chan *l2cap_chan_hold_unless_zero(struct l2cap_chan *c)
{
--
2.51.1
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH v2 3/5] Bluetooth: L2CAP: export l2cap_chan_hold for modules
2025-11-03 18:29 ` [PATCH v2 3/5] Bluetooth: L2CAP: export l2cap_chan_hold for modules Pauli Virtanen
@ 2025-11-04 10:44 ` Paul Menzel
0 siblings, 0 replies; 8+ messages in thread
From: Paul Menzel @ 2025-11-04 10:44 UTC (permalink / raw)
To: Pauli Virtanen
Cc: linux-bluetooth, marcel, johan.hedberg, luiz.dentz, linux-kernel
Dear Pauli,
Thank you for the patch.
Am 03.11.25 um 19:29 schrieb Pauli Virtanen:
> l2cap_chan_put() is exported, so export also l2cap_chan_hold() for
> modules.
>
> l2cap_chan_hold() has use case in net/bluetooth/6lowpan.c
>
> Signed-off-by: Pauli Virtanen <pav@iki.fi>
> ---
>
> Notes:
> v2:
> - New patch for v2
> - Used for build fix with CONFIG_BT_6LOWPAN=m
>
> net/bluetooth/l2cap_core.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> index d08320380ad6..35c57657bcf4 100644
> --- a/net/bluetooth/l2cap_core.c
> +++ b/net/bluetooth/l2cap_core.c
> @@ -497,6 +497,7 @@ void l2cap_chan_hold(struct l2cap_chan *c)
>
> kref_get(&c->kref);
> }
> +EXPORT_SYMBOL_GPL(l2cap_chan_hold);
>
> struct l2cap_chan *l2cap_chan_hold_unless_zero(struct l2cap_chan *c)
> {
Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
Kind regards,
Paul
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v2 4/5] Bluetooth: 6lowpan: Don't hold spin lock over sleeping functions
2025-11-03 18:29 [PATCH v2 1/5] Bluetooth: 6lowpan: reset link-local header on ipv6 recv path Pauli Virtanen
2025-11-03 18:29 ` [PATCH v2 2/5] Bluetooth: 6lowpan: fix BDADDR_LE vs ADDR_LE_DEV address type confusion Pauli Virtanen
2025-11-03 18:29 ` [PATCH v2 3/5] Bluetooth: L2CAP: export l2cap_chan_hold for modules Pauli Virtanen
@ 2025-11-03 18:29 ` Pauli Virtanen
2025-11-03 18:29 ` [PATCH v2 5/5] Bluetooth: 6lowpan: add missing l2cap_chan_lock() Pauli Virtanen
` (2 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Pauli Virtanen @ 2025-11-03 18:29 UTC (permalink / raw)
To: linux-bluetooth
Cc: Pauli Virtanen, marcel, johan.hedberg, luiz.dentz, linux-kernel
disconnect_all_peers() calls sleeping function (l2cap_chan_close) under
spinlock. Holding the lock doesn't actually do any good -- we work on a
local copy of the list, and the lock doesn't protect against peer->chan
having already been freed.
Fix by taking refcounts of peer->chan instead. Clean up the code and
old comments a bit.
Take devices_lock instead of RCU, because the kfree_rcu();
l2cap_chan_put(); construct in chan_close_cb() does not guarantee
peer->chan is necessarily valid in RCU.
Also take l2cap_chan_lock() which is required for l2cap_chan_close().
Log: (bluez 6lowpan-tester Client Connect - Disable)
------
BUG: sleeping function called from invalid context at kernel/locking/mutex.c:575
...
<TASK>
...
l2cap_send_disconn_req (net/bluetooth/l2cap_core.c:938 net/bluetooth/l2cap_core.c:1495)
...
? __pfx_l2cap_chan_close (net/bluetooth/l2cap_core.c:809)
do_enable_set (net/bluetooth/6lowpan.c:1048 net/bluetooth/6lowpan.c:1068)
------
Fixes: 90305829635d ("Bluetooth: 6lowpan: Converting rwlocks to use RCU")
Signed-off-by: Pauli Virtanen <pav@iki.fi>
---
Notes:
v2:
- Take devices_lock instead of RCU and use l2cap_chan_hold(). The
unless_zero() variant is not correct here, as peer->chan l2cap_chan
does not wait for RCU when its refcount hits 0.
net/bluetooth/6lowpan.c | 74 +++++++++++++++++++++++++----------------
1 file changed, 46 insertions(+), 28 deletions(-)
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
index 0d8c2e2e9a6c..588d7e94e606 100644
--- a/net/bluetooth/6lowpan.c
+++ b/net/bluetooth/6lowpan.c
@@ -53,6 +53,11 @@ static bool enable_6lowpan;
static struct l2cap_chan *listen_chan;
static DEFINE_MUTEX(set_lock);
+enum {
+ LOWPAN_PEER_CLOSING,
+ LOWPAN_PEER_MAXBITS
+};
+
struct lowpan_peer {
struct list_head list;
struct rcu_head rcu;
@@ -61,6 +66,8 @@ struct lowpan_peer {
/* peer addresses in various formats */
unsigned char lladdr[ETH_ALEN];
struct in6_addr peer_addr;
+
+ DECLARE_BITMAP(flags, LOWPAN_PEER_MAXBITS);
};
struct lowpan_btle_dev {
@@ -1014,41 +1021,52 @@ static int get_l2cap_conn(char *buf, bdaddr_t *addr, u8 *addr_type,
static void disconnect_all_peers(void)
{
struct lowpan_btle_dev *entry;
- struct lowpan_peer *peer, *tmp_peer, *new_peer;
- struct list_head peers;
+ struct lowpan_peer *peer;
+ int nchans;
- INIT_LIST_HEAD(&peers);
-
- /* We make a separate list of peers as the close_cb() will
- * modify the device peers list so it is better not to mess
- * with the same list at the same time.
+ /* l2cap_chan_close() cannot be called from RCU, and lock ordering
+ * chan->lock > devices_lock prevents taking write side lock, so copy
+ * then close.
*/
rcu_read_lock();
-
- list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) {
- list_for_each_entry_rcu(peer, &entry->peers, list) {
- new_peer = kmalloc(sizeof(*new_peer), GFP_ATOMIC);
- if (!new_peer)
- break;
-
- new_peer->chan = peer->chan;
- INIT_LIST_HEAD(&new_peer->list);
-
- list_add(&new_peer->list, &peers);
- }
- }
-
+ list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list)
+ list_for_each_entry_rcu(peer, &entry->peers, list)
+ clear_bit(LOWPAN_PEER_CLOSING, peer->flags);
rcu_read_unlock();
- spin_lock(&devices_lock);
- list_for_each_entry_safe(peer, tmp_peer, &peers, list) {
- l2cap_chan_close(peer->chan, ENOENT);
+ do {
+ struct l2cap_chan *chans[32];
+ int i;
- list_del_rcu(&peer->list);
- kfree_rcu(peer, rcu);
- }
- spin_unlock(&devices_lock);
+ nchans = 0;
+
+ spin_lock(&devices_lock);
+
+ list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) {
+ list_for_each_entry_rcu(peer, &entry->peers, list) {
+ if (test_and_set_bit(LOWPAN_PEER_CLOSING,
+ peer->flags))
+ continue;
+
+ l2cap_chan_hold(peer->chan);
+ chans[nchans++] = peer->chan;
+
+ if (nchans >= ARRAY_SIZE(chans))
+ goto done;
+ }
+ }
+
+done:
+ spin_unlock(&devices_lock);
+
+ for (i = 0; i < nchans; ++i) {
+ l2cap_chan_lock(chans[i]);
+ l2cap_chan_close(chans[i], ENOENT);
+ l2cap_chan_unlock(chans[i]);
+ l2cap_chan_put(chans[i]);
+ }
+ } while (nchans);
}
struct set_enable {
--
2.51.1
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v2 5/5] Bluetooth: 6lowpan: add missing l2cap_chan_lock()
2025-11-03 18:29 [PATCH v2 1/5] Bluetooth: 6lowpan: reset link-local header on ipv6 recv path Pauli Virtanen
` (2 preceding siblings ...)
2025-11-03 18:29 ` [PATCH v2 4/5] Bluetooth: 6lowpan: Don't hold spin lock over sleeping functions Pauli Virtanen
@ 2025-11-03 18:29 ` Pauli Virtanen
2025-11-03 19:07 ` [v2,1/5] Bluetooth: 6lowpan: reset link-local header on ipv6 recv path bluez.test.bot
2025-11-07 19:10 ` [PATCH v2 1/5] " patchwork-bot+bluetooth
5 siblings, 0 replies; 8+ messages in thread
From: Pauli Virtanen @ 2025-11-03 18:29 UTC (permalink / raw)
To: linux-bluetooth
Cc: Pauli Virtanen, marcel, johan.hedberg, luiz.dentz, linux-kernel
l2cap_chan_close() needs to be called in l2cap_chan_lock(), otherwise
l2cap_le_sig_cmd() etc. may run concurrently.
Add missing locks around l2cap_chan_close().
Fixes: 6b8d4a6a0314 ("Bluetooth: 6LoWPAN: Use connected oriented channel instead of fixed one")
Signed-off-by: Pauli Virtanen <pav@iki.fi>
---
Notes:
v2:
- no changes
l2cap_chan_send() has same issue, but harder to fix so leave for later
net/bluetooth/6lowpan.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
index 588d7e94e606..2c21ae8abadc 100644
--- a/net/bluetooth/6lowpan.c
+++ b/net/bluetooth/6lowpan.c
@@ -927,7 +927,9 @@ static int bt_6lowpan_disconnect(struct l2cap_conn *conn, u8 dst_type)
BT_DBG("peer %p chan %p", peer, peer->chan);
+ l2cap_chan_lock(peer->chan);
l2cap_chan_close(peer->chan, ENOENT);
+ l2cap_chan_unlock(peer->chan);
return 0;
}
@@ -1089,7 +1091,9 @@ static void do_enable_set(struct work_struct *work)
mutex_lock(&set_lock);
if (listen_chan) {
+ l2cap_chan_lock(listen_chan);
l2cap_chan_close(listen_chan, 0);
+ l2cap_chan_unlock(listen_chan);
l2cap_chan_put(listen_chan);
}
@@ -1148,7 +1152,9 @@ static ssize_t lowpan_control_write(struct file *fp,
mutex_lock(&set_lock);
if (listen_chan) {
+ l2cap_chan_lock(listen_chan);
l2cap_chan_close(listen_chan, 0);
+ l2cap_chan_unlock(listen_chan);
l2cap_chan_put(listen_chan);
listen_chan = NULL;
}
@@ -1310,7 +1316,9 @@ static void __exit bt_6lowpan_exit(void)
debugfs_remove(lowpan_control_debugfs);
if (listen_chan) {
+ l2cap_chan_lock(listen_chan);
l2cap_chan_close(listen_chan, 0);
+ l2cap_chan_unlock(listen_chan);
l2cap_chan_put(listen_chan);
}
--
2.51.1
^ permalink raw reply related [flat|nested] 8+ messages in thread* RE: [v2,1/5] Bluetooth: 6lowpan: reset link-local header on ipv6 recv path
2025-11-03 18:29 [PATCH v2 1/5] Bluetooth: 6lowpan: reset link-local header on ipv6 recv path Pauli Virtanen
` (3 preceding siblings ...)
2025-11-03 18:29 ` [PATCH v2 5/5] Bluetooth: 6lowpan: add missing l2cap_chan_lock() Pauli Virtanen
@ 2025-11-03 19:07 ` bluez.test.bot
2025-11-07 19:10 ` [PATCH v2 1/5] " patchwork-bot+bluetooth
5 siblings, 0 replies; 8+ messages in thread
From: bluez.test.bot @ 2025-11-03 19:07 UTC (permalink / raw)
To: linux-bluetooth, pav
[-- Attachment #1: Type: text/plain, Size: 2296 bytes --]
This is automated email and please do not reply to this email!
Dear submitter,
Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=1019069
---Test result---
Test Summary:
CheckPatch PENDING 0.38 seconds
GitLint PENDING 0.33 seconds
SubjectPrefix PASS 0.41 seconds
BuildKernel PASS 25.36 seconds
CheckAllWarning PASS 28.27 seconds
CheckSparse PASS 31.47 seconds
BuildKernel32 PASS 25.24 seconds
TestRunnerSetup PASS 504.90 seconds
TestRunner_l2cap-tester PASS 23.69 seconds
TestRunner_iso-tester PASS 69.75 seconds
TestRunner_bnep-tester PASS 6.06 seconds
TestRunner_mgmt-tester FAIL 113.38 seconds
TestRunner_rfcomm-tester PASS 9.23 seconds
TestRunner_sco-tester PASS 14.26 seconds
TestRunner_ioctl-tester PASS 9.89 seconds
TestRunner_mesh-tester FAIL 11.56 seconds
TestRunner_smp-tester PASS 8.39 seconds
TestRunner_userchan-tester PASS 6.45 seconds
IncrementalBuild PENDING 0.91 seconds
Details
##############################
Test: CheckPatch - PENDING
Desc: Run checkpatch.pl script
Output:
##############################
Test: GitLint - PENDING
Desc: Run gitlint
Output:
##############################
Test: TestRunner_mgmt-tester - FAIL
Desc: Run mgmt-tester with test-runner
Output:
Total: 490, Passed: 485 (99.0%), Failed: 1, Not Run: 4
Failed Test Cases
Read Exp Feature - Success Failed 0.104 seconds
##############################
Test: TestRunner_mesh-tester - FAIL
Desc: Run mesh-tester with test-runner
Output:
Total: 10, Passed: 8 (80.0%), Failed: 2, Not Run: 0
Failed Test Cases
Mesh - Send cancel - 1 Timed out 1.990 seconds
Mesh - Send cancel - 2 Timed out 1.997 seconds
##############################
Test: IncrementalBuild - PENDING
Desc: Incremental build with the patches in the series
Output:
---
Regards,
Linux Bluetooth
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH v2 1/5] Bluetooth: 6lowpan: reset link-local header on ipv6 recv path
2025-11-03 18:29 [PATCH v2 1/5] Bluetooth: 6lowpan: reset link-local header on ipv6 recv path Pauli Virtanen
` (4 preceding siblings ...)
2025-11-03 19:07 ` [v2,1/5] Bluetooth: 6lowpan: reset link-local header on ipv6 recv path bluez.test.bot
@ 2025-11-07 19:10 ` patchwork-bot+bluetooth
5 siblings, 0 replies; 8+ messages in thread
From: patchwork-bot+bluetooth @ 2025-11-07 19:10 UTC (permalink / raw)
To: Pauli Virtanen
Cc: linux-bluetooth, marcel, johan.hedberg, luiz.dentz, linux-kernel,
pmenzel
Hello:
This series was applied to bluetooth/bluetooth-next.git (master)
by Luiz Augusto von Dentz <luiz.von.dentz@intel.com>:
On Mon, 3 Nov 2025 20:29:46 +0200 you wrote:
> Bluetooth 6lowpan.c netdev has header_ops, so it must set link-local
> header for RX skb, otherwise things crash, eg. with AF_PACKET SOCK_RAW
>
> Add missing skb_reset_mac_header() for uncompressed ipv6 RX path.
>
> For the compressed one, it is done in lowpan_header_decompress().
>
> [...]
Here is the summary with links:
- [v2,1/5] Bluetooth: 6lowpan: reset link-local header on ipv6 recv path
https://git.kernel.org/bluetooth/bluetooth-next/c/7de8dc9b760c
- [v2,2/5] Bluetooth: 6lowpan: fix BDADDR_LE vs ADDR_LE_DEV address type confusion
https://git.kernel.org/bluetooth/bluetooth-next/c/c7409a88d204
- [v2,3/5] Bluetooth: L2CAP: export l2cap_chan_hold for modules
https://git.kernel.org/bluetooth/bluetooth-next/c/35d11c1cf51d
- [v2,4/5] Bluetooth: 6lowpan: Don't hold spin lock over sleeping functions
https://git.kernel.org/bluetooth/bluetooth-next/c/e1cd2d7db0bf
- [v2,5/5] Bluetooth: 6lowpan: add missing l2cap_chan_lock()
https://git.kernel.org/bluetooth/bluetooth-next/c/fde5b271c88f
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 8+ messages in thread