mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
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:

                 reply	other threads:[~2026-10-24 15:28 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-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 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®