From: Krystian Kaniewski <krystianmkaniewski@gmail.com>
To: syzbot <syzbot@kernel.org>,
syzkaller-upstream-moderation@googlegroups.com
Cc: syzbot@lists.linux.dev
Subject: Re: [PATCH RFC v2] Bluetooth: hci_sysfs: Fix NULL pointer dereference in device_del()
Date: Thu, 3 Sep 2026 10:10:14 +0200 [thread overview]
Message-ID: <8b187e1f-abb9-4a0e-8748-a97b4ceac680@gmail.com> (raw)
In-Reply-To: <7649937b-a96e-44a1-8785-79b23c26ffe6@mail.kernel.org>
Remove the quoted crash trace or replace it with the retained report
trace. The retained report shows `PID: 14113 Comm: kbnepd bnep0` and
faults in `klist_put()` from `device_del()` during `bnep_session`. The
current quote instead shows `PID: 21636 Comm: syz-executor` and faults
through `device_move()`, so it is not the actual report and contradicts
the corrected subject and ordering described below it. Keep the code
diff, corrected `device_del()` race explanation, `Fixes` tag,
provenance, and report links unchanged.
On 9/2/2026 6:57 PM, syzbot wrote:
> A NULL pointer dereference in klist_put() occurs when a child device (such
> as a BNEP network device in bnep_session) is concurrently being
> unregistered while hci_conn_del_sysfs() reparents child devices:
>
> Oops: general protection fault, probably for non-canonical address
> 0xdffffc000000000b: 0000 [#1] SMP KASAN NOPTI
> KASAN: null-ptr-deref in range [0x0000000000000058-0x000000000000005f]
> CPU: 1 UID: 0 PID: 21636 Comm: syz-executor Not tainted syzkaller #1
> PREEMPT(full)
> Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS
> 1.16.3-debian-1.16.3-2 04/01/2014
> RIP: 0010:klist_put lib/klist.c:212 [inline]
> RIP: 0010:klist_del lib/klist.c:230 [inline]
> RIP: 0010:klist_remove+0x156/0x340 lib/klist.c:249
> ...
> Call Trace:
> <TASK>
> device_move+0x18e/0x720 drivers/base/core.c:4702
> hci_conn_del_sysfs+0xb8/0x1a0 net/bluetooth/hci_sysfs.c:75
> hci_conn_cleanup net/bluetooth/hci_conn.c:170 [inline]
> hci_conn_del+0xc3d/0x1200 net/bluetooth/hci_conn.c:1318
> hci_conn_hash_flush+0x189/0x260 net/bluetooth/hci_conn.c:2747
> hci_dev_close_sync+0x7fc/0x10c0 net/bluetooth/hci_sync.c:5593
> hci_dev_do_close net/bluetooth/hci_core.c:502 [inline]
> hci_unregister_dev+0x232/0x5b0 net/bluetooth/hci_core.c:2681
> vhci_release+0x16d/0x1c0 drivers/bluetooth/hci_vhci.c:700
> ...
> </TASK>
>
> This crash is caused by a race condition between hci_conn_del_sysfs() and
> concurrent child device unregistration (e.g. bnep_session calling
> unregister_netdev()). During device unregistration, device_del() snapshots
> a non-NULL parent pointer. Concurrently, hci_conn_del_sysfs() finds the
> child device using device_find_any_child() and calls device_move() to
> reparent it to NULL, which removes the node from its parent's klist and
> clears knode_parent. Subsequently, device_del() calls
> klist_del(&dev->p->knode_parent) using the stale parent snapshot, causing
> klist_put() to dereference knode_klist(n)->put on an already removed node,
> resulting in a NULL pointer dereference.
>
> This race was introduced by commit 27aabf27fd01 ("Bluetooth: fix
> use-after-free in device_for_each_child()"), which replaced
> device_find_child(..., __match_tty) with device_find_any_child() in
> hci_conn_del_sysfs(). That change was intended to avoid a use-after-free
> where conn->dev outlived its parent hdev->dev when child devices held
> references to conn->dev, because conn->dev only held a reference to
> hdev->dev while registered in sysfs.
>
> Fix the issue properly by taking an explicit reference to the parent device
> with get_device(&hdev->dev) in hci_conn_init_sysfs() and dropping it with
> put_device(parent) in bt_link_release() when the conn device is freed. This
> ensures that hdev->dev remains valid for the entire lifecycle of conn->dev,
> resolving the underlying use-after-free. With the parent reference held
> properly, restore the __match_tty filter in hci_conn_del_sysfs() so that
> device_move() is only invoked on persistent RFCOMM TTY devices as
> originally intended, eliminating the race condition with unregistering
> network devices.
>
> Fixes: 27aabf27fd01 ("Bluetooth: fix use-after-free in device_for_each_child()")
> Assisted-by: Gemini:gemini-3.7-flash syzbot
> Reported-by: syzbot+6df45dd3d03e1a9aca96@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=6df45dd3d03e1a9aca96
> Link: https://syzkaller.appspot.com/ai_job?id=03299926-ecd5-4848-b5f8-a253b09af490
> To: <linux-bluetooth@vger.kernel.org>
> To: "Luiz Augusto von Dentz" <luiz.dentz@gmail.com>
> To: "Marcel Holtmann" <marcel@holtmann.org>
> To: "Dmitry Antipov" <dmantipov@yandex.ru>
> Cc: <linux-kernel@vger.kernel.org>
>
> ---
> v2:
> - Update subject line to reflect the NULL pointer dereference in device_del().
> - Replace trace with the actual crash report trace.
> - Clarify the race condition ordering between device_del() and concurrent hci_conn_del_sysfs().
>
> v1:
> https://lore.kernel.org/all/21c8fde7-0caa-4f2c-ae68-4bd3443ff0b5@mail.kernel.org/T/
> ---
> diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
> index 8957ce7c2..c2065abf7 100644
> --- a/net/bluetooth/hci_sysfs.c
> +++ b/net/bluetooth/hci_sysfs.c
> @@ -13,7 +13,10 @@ static const struct class bt_class = {
> static void bt_link_release(struct device *dev)
> {
> struct hci_conn *conn = to_hci_conn(dev);
> + struct device *parent = dev->parent;
> +
> kfree(conn);
> + put_device(parent);
> }
>
> static const struct device_type bt_link = {
> @@ -21,6 +24,16 @@ static const struct device_type bt_link = {
> .release = bt_link_release,
> };
>
> +/*
> + * The rfcomm tty device will possibly retain even when conn
> + * is down, and sysfs doesn't support move zombie device,
> + * so we should move the device before conn device is destroyed.
> + */
> +static int __match_tty(struct device *dev, const void *data)
> +{
> + return !strncmp(dev_name(dev), "rfcomm", 6);
> +}
> +
> void hci_conn_init_sysfs(struct hci_conn *conn)
> {
> struct hci_dev *hdev = conn->hdev;
> @@ -29,7 +42,7 @@ void hci_conn_init_sysfs(struct hci_conn *conn)
>
> conn->dev.type = &bt_link;
> conn->dev.class = &bt_class;
> - conn->dev.parent = &hdev->dev;
> + conn->dev.parent = get_device(&hdev->dev);
>
> device_initialize(&conn->dev);
> }
> @@ -69,7 +82,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn)
> while (1) {
> struct device *dev;
>
> - dev = device_find_any_child(&conn->dev);
> + dev = device_find_child(&conn->dev, NULL, __match_tty);
> if (!dev)
> break;
> device_move(dev, NULL, DPM_ORDER_DEV_LAST);
>
>
> base-commit: cee9395acd8043be0644b25c34bfa86623f2b935
prev parent reply other threads:[~2026-09-03 8:10 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-02 16:57 [PATCH RFC v2] Bluetooth: hci_sysfs: Fix NULL pointer dereference in device_del() syzbot
2026-09-03 8:10 ` Krystian Kaniewski [this message]
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=8b187e1f-abb9-4a0e-8748-a97b4ceac680@gmail.com \
--to=krystianmkaniewski@gmail.com \
--cc=syzbot@kernel.org \
--cc=syzbot@lists.linux.dev \
--cc=syzkaller-upstream-moderation@googlegroups.com \
/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.