All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Shen Yongchao" <grayhat@foxmail.com>
Cc: dmitry.torokhov@gmail.com, linux-input@vger.kernel.org
Subject: Re: [PATCH] HID: bpf: serialize device reference release in struct_ops destroy path
Date: Mon, 03 Aug 2026 14:49:58 +0000	[thread overview]
Message-ID: <20260803145000.E44E91F000E9@smtp.kernel.org> (raw)
In-Reply-To: <tencent_6C4272FCE4F12C891C300445A9D8E6C68C0A@qq.com>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:

Pre-existing issues:
- [High] Time-of-check to time-of-use (TOCTOU) race leading to a Use-After-Free of `hdev` during lock acquisition.
- [High] Early return bypasses `list_del_rcu()` and `synchronize_srcu()`, leaving a freed BPF ops object in the device's active program list.
--

--- Patch [1]: [PATCH] HID: bpf: serialize device reference release in struct_ops destroy path ---
commit cfdd4ce27d8a975674b1f3418e6b5078b5d94946
Author: Shen Yongchao <grayhat@foxmail.com>
Subject: HID: bpf: serialize device reference release in struct_ops destroy path

This patch aims to fix a double-put race condition in the HID BPF struct_ops
destroy and unreg paths. It serializes the remove/NULL decision under
hdev->bpf.prog_list_lock to ensure exactly one path releases the device
reference.

> diff --git a/drivers/hid/bpf/hid_bpf_struct_ops.c b/drivers/hid/bpf/hid_bpf_struct_ops.c
> index 702c22fae136a..049df06477610 100644
> --- a/drivers/hid/bpf/hid_bpf_struct_ops.c
> +++ b/drivers/hid/bpf/hid_bpf_struct_ops.c
> @@ -250,6 +250,11 @@ static void hid_bpf_unreg(void *kdata, struct bpf_link *link)
>  
>  	mutex_lock(&hdev->bpf.prog_list_lock);

[Severity: High]
This is a pre-existing issue, but is it possible for hdev to be completely
freed between being read from ops->hdev and used here in mutex_lock()?

If hid_bpf_unreg() reads hdev = ops->hdev and is then preempted, could
__hid_bpf_ops_destroy_device() execute concurrently, clear ops->hdev, and
drop the registration's device reference via hid_put_device(hdev)?

If that was the final reference, the device could be freed, leading to a
use-after-free when the unreg thread resumes and attempts to lock
&hdev->bpf.prog_list_lock.

> +	if (!ops->hdev) {
> +		mutex_unlock(&hdev->bpf.prog_list_lock);
> +		return;
> +	}
> +

[Severity: High]
This is a pre-existing issue, but does this early return safely handle list
cleanup?

In __hid_bpf_ops_destroy_device(), e->hdev = NULL is set, but the node is
intentionally left linked in hdev->bpf.prog_list.

If hid_bpf_unreg() runs, sees !ops->hdev under the lock, and returns early
here, it entirely bypasses list_del_rcu(&ops->list) and
synchronize_srcu(&hdev->bpf.srcu).

Since the BPF framework will subsequently free the ops map memory, wouldn't
this leave a freed object in hdev->bpf.prog_list?

If a driver .remove callback then triggers hid_bpf_hw_request() (for example,
to turn off LEDs), it would traverse the list under SRCU and access the freed
ops object.

>  	list_del_rcu(&ops->list);

[ ... ]

> @@ -310,13 +315,17 @@ static struct bpf_struct_ops bpf_hid_bpf_ops = {
>  void __hid_bpf_ops_destroy_device(struct hid_device *hdev)
>  {
>  	struct hid_bpf_ops *e;
> +	int count = 0;
>  
> -	rcu_read_lock();
> -	list_for_each_entry_rcu(e, &hdev->bpf.prog_list, list) {
> -		hid_put_device(hdev);
> +	mutex_lock(&hdev->bpf.prog_list_lock);
> +	list_for_each_entry(e, &hdev->bpf.prog_list, list) {
>  		e->hdev = NULL;
> +		count++;
>  	}
> -	rcu_read_unlock();
> +	mutex_unlock(&hdev->bpf.prog_list_lock);
> +
> +	while (count--)
> +		hid_put_device(hdev);
>  }

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/tencent_6C4272FCE4F12C891C300445A9D8E6C68C0A@qq.com?part=1

      reply	other threads:[~2026-08-03 14:50 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-03 14:31 [PATCH] HID: bpf: serialize device reference release in struct_ops destroy path Shen Yongchao
2026-08-03 14:49 ` sashiko-bot [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=20260803145000.E44E91F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=dmitry.torokhov@gmail.com \
    --cc=grayhat@foxmail.com \
    --cc=linux-input@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /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.