bpf: Roll back freplace link state when bpf_arch_text_poke() fails

A freplace attach claims the target prog by bumping
tgt_prog->aux->freplace_link_cnt and setting tr->extension_prog.
bpf_arch_text_poke() then makes the extension take effect.  If the
poke fails, the claims are never released: the attach unwinds
through bpf_link_cleanup(), which clears link->prog, so
bpf_trampoline_unlink_prog() never runs.

Drop the link count under ext_mutex on the error path, and set
tr->extension_prog only after the poke succeeded.  The count is
still bumped before the poke: it blocks prog_array updates while
the entry is patched.

Fixes: d6083f040d ("bpf: Prevent tailcall infinite loop caused by freplace")
Fixes: be8704ff07 ("bpf: Introduce dynamic program extensions")
Suggested-by: Leon Hwang <leon.hwang@linux.dev>
Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Leon Hwang <leon.hwang@linux.dev>
Link: https://patch.msgid.link/20260928091121.219333-1-chenyuan_fl@163.com
This commit is contained in:
Yuan Chen 2026-09-28 17:11:21 +08:00 committed by Alexei Starovoitov
parent 2b5440b31c
commit 5ec398d9ec
No known key found for this signature in database

View File

@ -1026,10 +1026,17 @@ static int __bpf_trampoline_link_prog(struct bpf_tramp_node *node,
err = bpf_freplace_link_tgt_prog(tgt_prog);
if (err)
return err;
err = bpf_arch_text_poke(tr->func.addr, BPF_MOD_NOP,
BPF_MOD_JUMP, NULL,
node->link->prog->bpf_func);
if (err) {
/* Undo the claim from bpf_freplace_link_tgt_prog(). */
guard(mutex)(&tgt_prog->aux->ext_mutex);
tgt_prog->aux->freplace_link_cnt--;
return err;
}
tr->extension_prog = node->link->prog;
return bpf_arch_text_poke(tr->func.addr, BPF_MOD_NOP,
BPF_MOD_JUMP, NULL,
node->link->prog->bpf_func);
return 0;
}
err = bpf_trampoline_add_prog(tr, node, cnt);
if (err)