* [PATCH bpf-next v5 0/2] bpf: Fix trampoline image UAF on multi detach failure
@ 2026-08-11 2:46 Hui Zhu
2026-08-11 2:46 ` [PATCH bpf-next v5 1/2] bpf: Fix UAF in bpf_trampoline_multi_attach_free on update failure Hui Zhu
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Hui Zhu @ 2026-08-11 2:46 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, John Fastabend,
Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi,
Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa,
Emil Tsalapatis, Ihor Solodrai, KP Singh, Matt Bobrowski,
Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers, bpf,
linux-kernel, linux-trace-kernel
Cc: Hui Zhu
From: Hui Zhu <zhuhui@kylinos.cn>
This series fixes a UAF in bpf_trampoline_multi_attach_free() where
old_image is freed while ftrace still calls into it, and makes
bpf_trampoline_multi_detach() return void as suggested by Jiri Olsa.
Patch 1 fixes the UAF. Patch 2 is an independent cleanup that
changes the return type to void and drops the WARN_ON_ONCE at the
call site.
Changelog:
v5:
According to the comments of bot+bpf-ci, split the single patch into
two: the bug fix and the return-type cleanup.
v4:
According to the comments of bot+bpf-ci, add Fixes: and update comments
of bpf_trampoline_multi_attach_free.
v3:
According to the comments of Jiri Olsa, drop patches 2/3 and the
prog-side machinery.
keep only the simplified image-side fix in
bpf_trampoline_multi_attach_free() and make
bpf_trampoline_multi_detach() return void.
v2:
Folded v1's two detach patches into patch 1.
According to the comments of Jiri Olsa, Pin the prog (pinned_prog) on
cur_image so it stays alive while ftrace may still call into it.
Make bpf_trampoline_multi_detach() return void.
Fix the same UAF in standard (non-multi) trampolines.
According to the comments of sashiko, Fix the prog UAF in
bpf_trampoline_multi_attach() rollback.
Leak the trampoline in bpf_trampoline_put() when cur_image is left
by a rollback.
Hui Zhu (2):
bpf: Fix UAF in bpf_trampoline_multi_attach_free on update failure
bpf: Make bpf_trampoline_multi_detach return void
include/linux/bpf.h | 9 ++++-----
kernel/bpf/trampoline.c | 16 +++++++++++++---
kernel/trace/bpf_trace.c | 2 +-
3 files changed, 18 insertions(+), 9 deletions(-)
--
2.53.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH bpf-next v5 1/2] bpf: Fix UAF in bpf_trampoline_multi_attach_free on update failure
2026-08-11 2:46 [PATCH bpf-next v5 0/2] bpf: Fix trampoline image UAF on multi detach failure Hui Zhu
@ 2026-08-11 2:46 ` Hui Zhu
2026-08-11 2:46 ` [PATCH bpf-next v5 2/2] bpf: Make bpf_trampoline_multi_detach return void Hui Zhu
2026-08-11 9:30 ` [PATCH bpf-next v5 0/2] bpf: Fix trampoline image UAF on multi detach failure Leon Hwang
2 siblings, 0 replies; 4+ messages in thread
From: Hui Zhu @ 2026-08-11 2:46 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, John Fastabend,
Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi,
Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa,
Emil Tsalapatis, Ihor Solodrai, KP Singh, Matt Bobrowski,
Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers, bpf,
linux-kernel, linux-trace-kernel
Cc: Hui Zhu
From: Hui Zhu <zhuhui@kylinos.cn>
When bpf_trampoline_update() fails before modify_fentry_multi()/
unregister_fentry_multi() is called, cur_image is unchanged
(cur_image == old_image) and ftrace still calls into it. Freeing
old_image in that case causes a UAF.
Only free old_image when it differs from cur_image.
Fixes: aef4dfa790b2 ("bpf: Add bpf_trampoline_multi_attach/detach functions")
Signed-off-by: Hui Zhu <zhuhui@kylinos.cn>
---
kernel/bpf/trampoline.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/kernel/bpf/trampoline.c b/kernel/bpf/trampoline.c
index ed7999ad6c66..ea4d3c62f289 100644
--- a/kernel/bpf/trampoline.c
+++ b/kernel/bpf/trampoline.c
@@ -1595,7 +1595,17 @@ static void bpf_trampoline_multi_attach_init(struct bpf_trampoline *tr)
static void bpf_trampoline_multi_attach_free(struct bpf_trampoline *tr)
{
- if (tr->multi_attach.old_image)
+ /*
+ * Only free old_image if it is no longer the active image.
+ * When bpf_trampoline_update() fails before modify_fentry_multi()/
+ * unregister_fentry_multi() is called, cur_image is unchanged
+ * (cur_image == old_image) and ftrace still points to it. Freeing
+ * it would cause a UAF when ftrace calls into the freed memory.
+ * On success, cur_image is either a new image or NULL, so
+ * old_image != cur_image means the image is stale.
+ */
+ if (tr->multi_attach.old_image &&
+ tr->multi_attach.old_image != tr->cur_image)
bpf_tramp_image_put(tr->multi_attach.old_image);
tr->multi_attach.old_image = NULL;
--
2.53.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH bpf-next v5 2/2] bpf: Make bpf_trampoline_multi_detach return void
2026-08-11 2:46 [PATCH bpf-next v5 0/2] bpf: Fix trampoline image UAF on multi detach failure Hui Zhu
2026-08-11 2:46 ` [PATCH bpf-next v5 1/2] bpf: Fix UAF in bpf_trampoline_multi_attach_free on update failure Hui Zhu
@ 2026-08-11 2:46 ` Hui Zhu
2026-08-11 9:30 ` [PATCH bpf-next v5 0/2] bpf: Fix trampoline image UAF on multi detach failure Leon Hwang
2 siblings, 0 replies; 4+ messages in thread
From: Hui Zhu @ 2026-08-11 2:46 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, John Fastabend,
Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi,
Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa,
Emil Tsalapatis, Ihor Solodrai, KP Singh, Matt Bobrowski,
Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers, bpf,
linux-kernel, linux-trace-kernel
Cc: Hui Zhu
From: Hui Zhu <zhuhui@kylinos.cn>
bpf_trampoline_multi_detach() always returns 0 and the sole caller
ignores the return value. Change it to return void and drop the
WARN_ON_ONCE at the call site.
Signed-off-by: Hui Zhu <zhuhui@kylinos.cn>
---
include/linux/bpf.h | 9 ++++-----
kernel/bpf/trampoline.c | 4 ++--
kernel/trace/bpf_trace.c | 2 +-
3 files changed, 7 insertions(+), 8 deletions(-)
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 73bacfc6444d..3255c6f5ea6b 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -1518,8 +1518,8 @@ int arch_prepare_bpf_dispatcher(void *image, void *buf, s64 *funcs, int num_func
int bpf_trampoline_multi_attach(struct bpf_prog *prog, u32 *ids,
struct bpf_tracing_multi_link *link);
-int bpf_trampoline_multi_detach(struct bpf_prog *prog,
- struct bpf_tracing_multi_link *link);
+void bpf_trampoline_multi_detach(struct bpf_prog *prog,
+ struct bpf_tracing_multi_link *link);
void bpf_trampoline_set_flags(struct bpf_trampoline *tr, u32 flags);
/*
@@ -1639,10 +1639,9 @@ static inline int bpf_trampoline_multi_attach(struct bpf_prog *prog, u32 *ids,
{
return -ENOTSUPP;
}
-static inline int bpf_trampoline_multi_detach(struct bpf_prog *prog,
- struct bpf_tracing_multi_link *link)
+static inline void bpf_trampoline_multi_detach(struct bpf_prog *prog,
+ struct bpf_tracing_multi_link *link)
{
- return -ENOTSUPP;
}
static inline void bpf_trampoline_set_flags(struct bpf_trampoline *tr, u32 flags) {}
#endif
diff --git a/kernel/bpf/trampoline.c b/kernel/bpf/trampoline.c
index ea4d3c62f289..e30425789487 100644
--- a/kernel/bpf/trampoline.c
+++ b/kernel/bpf/trampoline.c
@@ -1729,7 +1729,8 @@ int bpf_trampoline_multi_attach(struct bpf_prog *prog, u32 *ids,
return err;
}
-int bpf_trampoline_multi_detach(struct bpf_prog *prog, struct bpf_tracing_multi_link *link)
+void bpf_trampoline_multi_detach(struct bpf_prog *prog,
+ struct bpf_tracing_multi_link *link)
{
struct bpf_tracing_multi_data *data = &link->data;
struct bpf_tracing_multi_node *mnode;
@@ -1759,7 +1760,6 @@ int bpf_trampoline_multi_detach(struct bpf_prog *prog, struct bpf_tracing_multi_
bpf_trampoline_put(mnode->trampoline);
clear_tracing_multi_data(data);
- return 0;
}
#undef for_each_mnode_cnt
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index 891897f8a1b3..29260951aa87 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -3687,7 +3687,7 @@ static void bpf_tracing_multi_link_release(struct bpf_link *link)
struct bpf_tracing_multi_link *tr_link =
container_of(link, struct bpf_tracing_multi_link, link);
- WARN_ON_ONCE(bpf_trampoline_multi_detach(link->prog, tr_link));
+ bpf_trampoline_multi_detach(link->prog, tr_link);
}
static void bpf_tracing_multi_link_dealloc(struct bpf_link *link)
--
2.53.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH bpf-next v5 0/2] bpf: Fix trampoline image UAF on multi detach failure
2026-08-11 2:46 [PATCH bpf-next v5 0/2] bpf: Fix trampoline image UAF on multi detach failure Hui Zhu
2026-08-11 2:46 ` [PATCH bpf-next v5 1/2] bpf: Fix UAF in bpf_trampoline_multi_attach_free on update failure Hui Zhu
2026-08-11 2:46 ` [PATCH bpf-next v5 2/2] bpf: Make bpf_trampoline_multi_detach return void Hui Zhu
@ 2026-08-11 9:30 ` Leon Hwang
2 siblings, 0 replies; 4+ messages in thread
From: Leon Hwang @ 2026-08-11 9:30 UTC (permalink / raw)
To: Hui Zhu, Alexei Starovoitov, Daniel Borkmann, John Fastabend,
Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi,
Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa,
Emil Tsalapatis, Ihor Solodrai, KP Singh, Matt Bobrowski,
Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers, bpf,
linux-kernel, linux-trace-kernel
Cc: Hui Zhu
On 11/8/26 10:46, Hui Zhu wrote:
> From: Hui Zhu <zhuhui@kylinos.cn>
>
> This series fixes a UAF in bpf_trampoline_multi_attach_free() where
> old_image is freed while ftrace still calls into it, and makes
> bpf_trampoline_multi_detach() return void as suggested by Jiri Olsa.
>
> Patch 1 fixes the UAF. Patch 2 is an independent cleanup that
> changes the return type to void and drops the WARN_ON_ONCE at the
> call site.
The UAF issue was reported by Sashiko when reviewing "bpf: Add
tracing_multi link support for bpf progs" [1].
The fix and the cleanup look good to me.
Acked-by: Leon Hwang <leon.hwang@linux.dev>
[1]
https://sashiko.dev/#/message/20260809153308.5331D1F000E9%40smtp.kernel.org
> [...]
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-08-11 9:31 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-11 2:46 [PATCH bpf-next v5 0/2] bpf: Fix trampoline image UAF on multi detach failure Hui Zhu
2026-08-11 2:46 ` [PATCH bpf-next v5 1/2] bpf: Fix UAF in bpf_trampoline_multi_attach_free on update failure Hui Zhu
2026-08-11 2:46 ` [PATCH bpf-next v5 2/2] bpf: Make bpf_trampoline_multi_detach return void Hui Zhu
2026-08-11 9:30 ` [PATCH bpf-next v5 0/2] bpf: Fix trampoline image UAF on multi detach failure Leon Hwang
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox