All of lore.kernel.org
 help / color / mirror / Atom feed
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] Bluetooth: hci_sysfs: fix null pointer dereference in device_move()
Date: Wed, 2 Sep 2026 18:04:20 +0200	[thread overview]
Message-ID: <768120d6-29c8-487c-adc2-48eaefec9b4a@gmail.com> (raw)
In-Reply-To: <21c8fde7-0caa-4f2c-ae68-4bd3443ff0b5@mail.kernel.org>

Correct the subject and commit message to match the retained crash 
evidence. The report faults in klist_put() from device_del() during 
bnep_session, not in device_move(), and it does not contain the quoted 
PID 7415 "Comm: task" trace. Remove that unsupported trace or replace it 
with the actual bnep_session and device_del stack. Describe the observed 
ordering: device_del() snapshots a non-NULL parent, concurrent 
hci_conn_del_sysfs() moves the child and clears knode_parent, then 
device_del() calls klist_del() using its stale parent decision. Preserve 
the code diff, which correctly restores the RFCOMM-only move and retains 
hdev->dev until the connection device release, along with the existing 
Fixes, Reported-by, Closes, provenance, and recipient tags.

On 9/1/2026 12:16 AM, syzbot wrote:
> A NULL pointer dereference in klist_put() occurs when hci_conn_del_sysfs()
> attempts to reparent child devices to NULL while a child device (such as a
> BNEP network device) is concurrently being unregistered:
>
> 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: 7415 Comm: task Not tainted PREEMPT(full)
> 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()). When a connection is cleaned up, hci_conn_del_sysfs()
> uses device_find_any_child() to look up child devices and calls
> device_move() to reparent them to NULL. If the child device is concurrently
> deleted, device_del() removes the node from its parent's klist via
> klist_del(&dev->p->knode_parent), which decrements the reference count and
> clears the node's n_klist pointer to NULL. When device_move() subsequently
> calls klist_remove(&dev->p->knode_parent), klist_put() attempts to
> dereference knode_klist(n)->put, 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 Gemini:gemini-3.1-pro-preview syzbot
> Reported-by: syzbot+6df45dd3d03e1a9aca96@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=6df45dd3d03e1a9aca96
> Link: https://syzkaller.appspot.com/ai_job?id=2d312ca9-20bf-457f-8a4f-728831a400af
> 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>
>
> ---
> 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

      reply	other threads:[~2026-09-02 16:04 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-31 22:16 [PATCH RFC] Bluetooth: hci_sysfs: fix null pointer dereference in device_move() syzbot
2026-09-02 16:04 ` 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=768120d6-29c8-487c-adc2-48eaefec9b4a@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.