From: Cen Zhang <zzzccc427@gmail.com>
To: marcel@holtmann.org, luiz.dentz@gmail.com
Cc: linux-bluetooth@vger.kernel.org, linux-kernel@vger.kernel.org,
baijiaju1990@gmail.com, jjzuming@gmail.com, zzzccc427@gmail.com
Subject: [PATCH] Bluetooth: hci_core: Keep RCU protection through LTK filtering
Date: Tue, 6 Oct 2026 15:38:38 +0800 [thread overview]
Message-ID: <pm-bluetooth-objects-candidate-0123-v5-83023fa5b4741c350341@gmail.com> (raw)
The LTK selected by hci_find_ltk() must remain allocated while its
value is checked against the blocked-key list. The finder releases RCU
before passing k->val to hci_is_blocked_key(). The helper's own RCU
section protects the blocked-key list, but the selected LTK may already
have been reclaimed before that section starts.
An LE ATT socket security request can reach smp_ltk_encrypt() without
holding hdev->lock. With a matching stored LTK and an LTK-type
blocked-key entry present, a concurrent MGMT_OP_LOAD_LONG_TERM_KEYS can
remove the selected LTK in the following order:
Socket security Management / RCU reclamation
hci_find_ltk()
rcu_read_lock()
select k
rcu_read_unlock()
load_long_term_keys()
hci_dev_lock(hdev)
hci_smp_ltks_clear(hdev)
list_del_rcu(&k->list)
kfree_rcu(k, rcu)
grace period ends; k is freed
hci_is_blocked_key(..., k->val)
memcmp(b->val, val, ...)
The final comparison reads freed LTK bytes. Entering a new RCU section
in hci_is_blocked_key() cannot protect a pointer obtained before the
completed grace period.
Keep the finder's RCU read-side section active through the blocked-key
comparison and the warning that reads k->bdaddr. Release it before
returning on either matched-key path. This delays reclamation until the
finder has finished using the selected record, following the existing
IRK lookup pattern.
KFENCE report as below:
==================================================================
BUG: KFENCE: use-after-free read in hci_is_blocked_key+0xdf/0x240
Use-after-free read at 0x00000000b9ee38e4 (in kfence-#249):
hci_is_blocked_key+0xdf/0x240
blocked_key_wrapper+0xc5/0x140 [pmbd_ltk_probe]
hci_find_ltk+0x1aa/0x3e0
smp_ltk_encrypt.isra.0+0xad/0x340
smp_conn_security+0x3b8/0x8c0
l2cap_sock_setsockopt+0x1c4b/0x2270
do_sock_setsockopt+0x1fb/0x430
__sys_setsockopt+0x106/0x180
__x64_sys_setsockopt+0xc2/0x160
do_syscall_64+0x115/0x6a0
entry_SYSCALL_64_after_hwframe+0x77/0x7f
kfence-#249: 0x00000000121f2ad9-0x000000005b5bfb3d, size=72, cache=kmalloc-96
allocated by task 495 on cpu 0 at 36.722380s (2.603973s ago):
hci_add_ltk+0x1f5/0x3a0
load_long_term_keys+0x6d0/0x860
hci_sock_sendmsg+0x128b/0x22e0
__sys_sendto+0x425/0x470
__x64_sys_sendto+0xe5/0x1c0
do_syscall_64+0x115/0x6a0
entry_SYSCALL_64_after_hwframe+0x77/0x7f
freed by task 533 on cpu 0 at 36.993097s (2.339769s ago):
__rcu_free_sheaf_prepare+0x261/0x2a0
rcu_free_sheaf+0x1f/0xe0
rcu_core+0x661/0x1d10
handle_softirqs+0x201/0x930
__irq_exit_rcu+0x110/0x1e0
irq_exit_rcu+0xe/0x20
sysvec_apic_timer_interrupt+0x6c/0x80
asm_sysvec_apic_timer_interrupt+0x1a/0x20
srso_alias_return_thunk+0x0/0xfbef5
__asan_memcpy+0x23/0x60
create_monitor_ctrl_event+0x1a2/0x460
mgmt_cmd_complete+0x2da/0x580
load_long_term_keys+0x741/0x860
hci_sock_sendmsg+0x128b/0x22e0
__sys_sendto+0x425/0x470
__x64_sys_sendto+0xe5/0x1c0
do_syscall_64+0x115/0x6a0
entry_SYSCALL_64_after_hwframe+0x77/0x7f
CPU: 1 UID: 0 PID: 495 Comm: python3 Tainted: G O 7.2.0-rc6-pmb-bt-functional-v1+ #1 PREEMPT(lazy)
Tainted: [O]=OOT_MODULE
Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
==================================================================
Fixes: 600a87490ff9 ("Bluetooth: Implementation of MGMT_OP_SET_BLOCKED_KEYS.")
Assisted-by: LLM
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
---
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 05d1ca25f4..90905dabf7 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1153,16 +1153,16 @@ struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr,
continue;
if (smp_ltk_is_sc(k) || ltk_role(k->type) == role) {
- rcu_read_unlock();
-
if (hci_is_blocked_key(hdev, HCI_BLOCKED_KEY_TYPE_LTK,
k->val)) {
bt_dev_warn_ratelimited(hdev,
"LTK blocked for %pMR",
&k->bdaddr);
+ rcu_read_unlock();
return NULL;
}
+ rcu_read_unlock();
return k;
}
}
reply other threads:[~2026-10-06 7:38 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=pm-bluetooth-objects-candidate-0123-v5-83023fa5b4741c350341@gmail.com \
--to=zzzccc427@gmail.com \
--cc=baijiaju1990@gmail.com \
--cc=jjzuming@gmail.com \
--cc=linux-bluetooth@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=luiz.dentz@gmail.com \
--cc=marcel@holtmann.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®