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: vhci: Serialize packet reception with device creation
Date: Sat, 24 Oct 2026 23:28:23 +0800 [thread overview]
Message-ID: <pm-bluetooth-objects-candidate-0253-v6-ffe55995e8c517fb1d86@gmail.com> (raw)
The hci_dev passed to hci_recv_frame() must stay alive until the receive
operation finishes. __vhci_create_device() stores data->hdev before
hci_register_dev() and frees the device if registration fails.
vhci_get_user() checks and uses that pointer without taking the
open_mutex held by the creator or a device reference.
An incoming packet write can overlap the delayed default-create work
scheduled by vhci_open(). If registration fails before acquiring the
registration reference, the following order is possible:
Default-create work Packet write
vhci_create_device()
mutex_lock(open_mutex)
data->hdev = hdev
vhci_get_user()
load data->hdev
hci_register_dev() fails
hci_free_dev(hdev)
bt_host_release(): kfree(hdev)
data->hdev = NULL
mutex_unlock(open_mutex)
hci_recv_frame(hdev, skb)
read hdev->flags
The packet retains the pointer before the final put and reads flags
after the allocation is freed. The HCI_UP/HCI_INIT test therefore
accesses freed memory before it can reject the packet.
Hold open_mutex from the packet-side pointer check until
hci_recv_frame() returns. Creation and its error cleanup already hold
this mutex, so the writer waits until they finish and cannot retain a
failed device allocation. Release the mutex on the missing-device error
path too.
KASAN report as below:
BUG: KASAN: use-after-free in hci_recv_frame+0x4e/0x7e0
Read of size 8 at addr ffff888107034138 by task python3/500
Call Trace:
<TASK>
dump_stack_lvl+0x93/0xd0
print_report+0xce/0x630
? hci_recv_frame+0x4e/0x7e0
? srso_alias_return_thunk+0x5/0xfbef5
? __virt_addr_valid+0x20d/0x410
? hci_recv_frame+0x4e/0x7e0
kasan_report+0xe0/0x110
? hci_recv_frame+0x4e/0x7e0
kasan_check_range+0x105/0x1b0
hci_recv_frame+0x4e/0x7e0
vhci_write+0x35a/0x4c0
vfs_write+0x637/0x1010
? __pfx_vhci_write+0x10/0x10
? __might_fault+0xdd/0x190
? __pfx_vfs_write+0x10/0x10
? __pfx_hrtimer_wakeup+0x10/0x10
? srso_alias_return_thunk+0x5/0xfbef5
? srso_alias_return_thunk+0x5/0xfbef5
? common_nsleep_timens+0xa8/0x160
ksys_write+0x111/0x200
? __pfx_ksys_write+0x10/0x10
? srso_alias_return_thunk+0x5/0xfbef5
? restore_fpregs_from_fpstate+0x55/0x100
do_syscall_64+0x115/0x6a0
entry_SYSCALL_64_after_hwframe+0x77/0x7f
The buggy address belongs to the physical page:
page: refcount:0 mapcount:0 mapping:0000000000000000
index:0xffff888107036a40 pfn:0x107034
flags: 0x200000000000000(node=0|zone=2)
raw: 0200000000000000 ffffea00041c0308 ffff8881887bf180
0000000000000000
raw: ffff888107036a40 0000000000000000 00000000ffffffff
0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff888107034000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
ffff888107034080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
>ffff888107034100: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
^
ffff888107034180: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
ffff888107034200: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
==================================================================
Fixes: 23424c0d3169 ("Bluetooth: Add support creating virtual AMP controllers")
Assisted-by: LLM
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
---
diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c
index 8f7db0102b25f..de7d4d67e46e9 100644
--- a/drivers/bluetooth/hci_vhci.c
+++ b/drivers/bluetooth/hci_vhci.c
@@ -524,7 +524,9 @@ static inline ssize_t vhci_get_user(struct vhci_data *data,
case HCI_ACLDATA_PKT:
case HCI_SCODATA_PKT:
case HCI_ISODATA_PKT:
+ mutex_lock(&data->open_mutex);
if (!data->hdev) {
+ mutex_unlock(&data->open_mutex);
kfree_skb(skb);
return -ENODEV;
}
@@ -532,6 +534,7 @@ static inline ssize_t vhci_get_user(struct vhci_data *data,
hci_skb_pkt_type(skb) = pkt_type;
ret = hci_recv_frame(data->hdev, skb);
+ mutex_unlock(&data->open_mutex);
break;
case HCI_VENDOR_PKT:
next reply other threads:[~2026-10-24 15:28 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-24 15:28 Cen Zhang [this message]
2026-10-24 18:16 ` Bluetooth: vhci: Serialize packet reception with device creation bluez.test.bot
2026-11-10 13:33 ` [PATCH] " Chad Aldreda
2026-11-10 16:10 ` patchwork-bot+bluetooth
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-0253-v6-ffe55995e8c517fb1d86@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.