From: Martin KaFai Lau <martin.lau@linux.dev>
To: xulang <xulang@uniontech.com>
Cc: ast@kernel.org, bpf@vger.kernel.org, daniel@iogearbox.net,
dddddd@hust.edu.cn, dzm91@hust.edu.cn,
hust-os-kernel-patches@googlegroups.com, kaiyanm@hust.edu.cn,
sdf@fomichev.me
Subject: Re: [PATCH] bpf: fix: Race condition in bpf_trampoline_unlink_cgroup_shim
Date: Thu, 12 Feb 2026 11:51:14 -0800 [thread overview]
Message-ID: <64e56f03-bc93-46c1-8d5e-fa9720821620@linux.dev> (raw)
In-Reply-To: <68AC3CE38AB1BD07+20260206071357.4075301-1-xulang@uniontech.com>
On 2/5/26 11:13 PM, xulang wrote:
> Based on Martin KaFai Lau's suggestions, I have created a simple patch.
Thanks for the patch.
>
> The root cause of this bug is that when `bpf_link_put` reduces the
> refcount of `shim_link->link.link` to zero, the resource is considered
> released but may still be referenced via `tr->progs_hlist` in
> `cgroup_shim_find`. The actual cleanup of `tr->progs_hlist` in
> `bpf_shim_tramp_link_release` is deferred. During this window, another
> process can cause a use-after-free via `bpf_trampoline_link_cgroup_shim`.
>
> To fix this:
> 1. Add an atomic non-zero check in `bpf_trampoline_link_cgroup_shim`.
> Only increment the refcount if it is not already zero.
This makes sense.
> 2. Guard the freeing of `shim_link` with `tr->mutex` to prevent release
> while the mutex is held.
I am not sure about this one (details below).
>
> Testing:
> I used a non-rigorous method to verify the fix by adding a delay in
> `bpf_link_put` to make the bug easier to trigger:
>
> void bpf_link_put(struct bpf_link *link)
> {
> if (!atomic64_dec_and_test(&link->refcnt))
> return;
> + msleep(100);
> INIT_WORK(&link->work, bpf_link_put_deferred);
> schedule_work(&link->work);
> }
>
> Before the patch, running a PoC easily reproduced the crash (often within
> dozens of iterations) with a call trace similar to KaiyanM's report.
> After the patch, the bug no longer occurs even after millions of
> iterations.
>
> Signed-off-by: xulang <xulang@uniontech.com>
> ---
> kernel/bpf/trampoline.c | 14 ++++++++++----
> 1 file changed, 10 insertions(+), 4 deletions(-)
>
> diff --git a/kernel/bpf/trampoline.c b/kernel/bpf/trampoline.c
> index 976d89011b15..c16a53cca5e0 100644
> --- a/kernel/bpf/trampoline.c
> +++ b/kernel/bpf/trampoline.c
> @@ -702,15 +702,23 @@ static void bpf_shim_tramp_link_release(struct bpf_link *link)
> return;
>
> WARN_ON_ONCE(bpf_trampoline_unlink_prog(&shim_link->link, shim_link->trampoline, NULL));
bpf_trampoline_unlink_prog() will hold (/wait) for tr->mutex before
unlinking from tr. The link's refcnt is already 0 here.
> - bpf_trampoline_put(shim_link->trampoline);
> }
>
> static void bpf_shim_tramp_link_dealloc(struct bpf_link *link)
> {
> struct bpf_shim_tramp_link *shim_link =
> container_of(link, struct bpf_shim_tramp_link, link.link);
> + struct bpf_trampoline *tr = shim_link->trampoline;
>
> + if (!tr) {
> + kfree(shim_link);
> + return;
> + }
> +
> + mutex_lock(&tr->mutex);
The link_release is done before the link_dealloc. Why it needs to hold
(/wait) for the tr->mutex again?
> kfree(shim_link);
> + mutex_unlock(&tr->mutex);
> + bpf_trampoline_put(tr);
> }
>
> static const struct bpf_link_ops bpf_shim_tramp_link_lops = {
> @@ -800,10 +808,8 @@ int bpf_trampoline_link_cgroup_shim(struct bpf_prog *prog,
> mutex_lock(&tr->mutex);
>
> shim_link = cgroup_shim_find(tr, bpf_func);
> - if (shim_link) {
> + if (shim_link && atomic64_inc_not_zero(&shim_link->link.link.refcnt)) {
Use bpf_link_inc_not_zero().
pw-bot: cr
> /* Reusing existing shim attached by the other program. */
> - bpf_link_inc(&shim_link->link.link);
> -
> mutex_unlock(&tr->mutex);
> bpf_trampoline_put(tr); /* bpf_trampoline_get above */
> return 0;
next prev parent reply other threads:[~2026-02-12 19:51 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-11-25 11:14 bpf: Race condition in bpf_trampoline_unlink_cgroup_shim during concurrent cgroup LSM link release 梅开彦
2025-12-01 20:21 ` Martin KaFai Lau
2025-12-02 4:48 ` 梅开彦
2026-02-06 7:13 ` [PATCH] bpf: fix: Race condition in bpf_trampoline_unlink_cgroup_shim xulang
2026-02-06 7:50 ` bot+bpf-ci
2026-02-12 19:51 ` Martin KaFai Lau [this message]
2026-02-24 9:42 ` xulang
2026-02-25 6:54 ` [PATCH v2] " xulang
2026-02-25 7:38 ` bot+bpf-ci
2026-02-27 20:33 ` Martin KaFai Lau
2026-02-28 2:24 ` [PATCH bpf v3] " xulang
2026-02-28 3:04 ` bot+bpf-ci
2026-03-03 2:39 ` Martin KaFai Lau
2026-03-03 8:36 ` [PATCH bpf v4] " xulang
2026-03-03 9:28 ` bot+bpf-ci
2026-03-03 9:52 ` [PATCH bpf v5] bpf: fix: Race condition in bpf_trampoline_link_cgroup_shim xulang
2026-03-03 23:30 ` patchwork-bot+netdevbpf
2026-03-03 23:30 ` [PATCH bpf v4] bpf: fix: Race condition in bpf_trampoline_unlink_cgroup_shim patchwork-bot+netdevbpf
2026-03-03 23:46 ` Martin KaFai Lau
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=64e56f03-bc93-46c1-8d5e-fa9720821620@linux.dev \
--to=martin.lau@linux.dev \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=dddddd@hust.edu.cn \
--cc=dzm91@hust.edu.cn \
--cc=hust-os-kernel-patches@googlegroups.com \
--cc=kaiyanm@hust.edu.cn \
--cc=sdf@fomichev.me \
--cc=xulang@uniontech.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox