summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorHui Zhu <zhuhui@kylinos.cn>2026-08-11 10:46:19 +0800
committerKumar Kartikeya Dwivedi <memxor@gmail.com>2026-08-13 02:52:22 +0200
commit0253073fb7d79a2dd2eae9581ea16db2aef395a6 (patch)
treeb2a6f92e7318dab9f65028d99a042ac9687d1466 /kernel
parentdf2175350ec272f0250d30bc7ee762b4d23030cf (diff)
bpf: Fix UAF in bpf_trampoline_multi_attach_free on update failure
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> Acked-by: Leon Hwang <leon.hwang@linux.dev> Acked-by: Jiri Olsa <jolsa@kernel.org> Link: https://lore.kernel.org/bpf/aaa3829e11e2e26bcd3bda9ee6df7a0101a718ac.1786412280.git.zhuhui@kylinos.cn Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/bpf/trampoline.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/kernel/bpf/trampoline.c b/kernel/bpf/trampoline.c
index e07af35ed040..008448bb4a1f 100644
--- a/kernel/bpf/trampoline.c
+++ b/kernel/bpf/trampoline.c
@@ -1632,7 +1632,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;