From: sashiko-bot@kernel.org
To: "Hui Zhu" <hui.zhu@linux.dev>
Cc: bpf@vger.kernel.org
Subject: Re: [PATCH bpf-next 2/2] bpf: Fix UAF in bpf_trampoline_multi_detach when ftrace update fails
Date: Thu, 16 Jul 2026 08:55:32 +0000 [thread overview]
Message-ID: <20260716085533.1258C1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <d1fcbede8f311db5cfa7cbe34371de7b63186ce5.1784191209.git.zhuhui@kylinos.cn>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
New issues:
- [High] Rolling back the trampoline image during detach introduces a memory leak of the trampoline image and its executable page.
Pre-existing issues:
- [Critical] Failing to update ftrace during detach causes an exploitable Use-After-Free of BPF program memory.
--
--- Patch [2]: [PATCH bpf-next 2/2] bpf: Fix UAF in bpf_trampoline_multi_detach when ftrace update fails ---
commit 74c497eb28abb2878db6016026226008d3d6f7a6
Author: Hui Zhu <zhuhui@kylinos.cn>
Subject: bpf: Fix UAF in bpf_trampoline_multi_detach when ftrace update fails
This patch updates bpf_trampoline_multi_detach to capture ftrace update
failures and uses a rollback mechanism to prevent freeing the old trampoline
image while ftrace still points to it.
> diff --git a/kernel/bpf/trampoline.c b/kernel/bpf/trampoline.c
> --- a/kernel/bpf/trampoline.c
> +++ b/kernel/bpf/trampoline.c
[ ... ]
> @@ -1734,13 +1734,41 @@ int bpf_trampoline_multi_detach(struct bpf_prog *prog, struct bpf_tracing_multi_
> - for_each_mnode(mnode, link)
> - bpf_trampoline_multi_attach_free(mnode->trampoline);
> + for_each_mnode(mnode, link) {
> + struct bpf_trampoline *tr = mnode->trampoline;
> +
> + /* If the batch ftrace update failed for this mnode's path,
> + * ftrace still points to old_image. Use rollback to restore
> + * cur_image to old_image (putting the new cur_image if any)
> + * so the trampoline keeps the image ftrace is calling.
[ ... ]
> + */
> + if (tr->multi_attach.old_image &&
> + tr->multi_attach.old_image != tr->cur_image &&
> + ((err_unreg && !tr->cur_image) ||
> + (err_mod && tr->cur_image)))
> + bpf_trampoline_multi_attach_rollback(tr);
[Severity: High]
Does this rollback leak the trampoline image memory?
In a successful detach, tr->cur_image is typically set to NULL. By calling
bpf_trampoline_multi_attach_rollback(), we restore tr->cur_image to
tr->multi_attach.old_image instead of freeing it.
When the link is subsequently destroyed, bpf_trampoline_put() is called.
Because the BPF program was already unlinked from the trampoline earlier in
this function via __bpf_trampoline_unlink_prog(), tr->progs_hlist is
completely empty.
This causes bpf_trampoline_put() to directly free the trampoline structure:
kernel/bpf/trampoline.c:bpf_trampoline_put() {
...
if (hlist_empty(&tr->progs_hlist[BPF_TRAMP_FENTRY]) &&
...) {
...
kfree(tr);
}
}
Because bpf_trampoline_put() expects tr->cur_image to be NULL when no
programs remain, it does not free it. Is there another mechanism that
will eventually clean up this restored image, or is it permanently leaked?
[Severity: Critical]
This is a pre-existing issue, but does keeping the old image active still
lead to a use-after-free of the BPF program itself?
Even though the rollback preserves the trampoline image so ftrace can safely
call it without faulting, the BPF program was already unlinked by
__bpf_trampoline_unlink_prog().
Since bpf_trampoline_multi_detach() unconditionally returns 0, the caller
proceeds with tearing down the link, ignoring the ftrace detachment failure:
kernel/trace/bpf_trace.c:bpf_tracing_multi_link_release() {
WARN_ON_ONCE(bpf_trampoline_multi_detach(link->prog, tr_link));
}
This continues to bpf_link_dealloc() which calls bpf_prog_put(link->prog),
freeing the BPF program's memory.
Because the ftrace hook could not be removed, won't ftrace eventually fire
and execute the preserved old_image, which contains hardcoded direct calls
to the now-freed BPF program?
> + else
> + bpf_trampoline_multi_attach_free(tr);
> + }
>
> trampoline_unlock_all();
>
--
Sashiko AI review · https://sashiko.dev/#/patchset/cover.1784191209.git.zhuhui@kylinos.cn?part=2
prev parent reply other threads:[~2026-07-16 8:55 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-16 8:43 [PATCH bpf-next 0/2] bpf: Fix two trampoline image UAFs in bpf_trampoline_multi_detach() Hui Zhu
2026-07-16 8:43 ` [PATCH bpf-next 1/2] bpf: Fix stale old_image UAF on trampoline update failure Hui Zhu
2026-07-16 9:05 ` sashiko-bot
2026-07-16 8:43 ` [PATCH bpf-next 2/2] bpf: Fix UAF in bpf_trampoline_multi_detach when ftrace update fails Hui Zhu
2026-07-16 8:55 ` 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=20260716085533.1258C1F000E9@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=hui.zhu@linux.dev \
--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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox