commit f858c2b2ca04fc7ead291821a793638ae120c11d upstream
The verifier allows programs to call global functions as long as their argument types match, using BTF to check the function arguments. One of the allowed argument types to such global functions is PTR_TO_CTX; however the check for this fails on BPF_PROG_TYPE_EXT functions because the verifier uses the wrong type to fetch the vmlinux BTF ID for the program context type. This failure is seen when an XDP program is loaded using libxdp (which loads it as BPF_PROG_TYPE_EXT and attaches it to a global XDP type program).
Fix the issue by passing in the target program type instead of the BPF_PROG_TYPE_EXT type to bpf_prog_get_ctx() when checking function argument compatibility.
The first Fixes tag refers to the latest commit that touched the code in question, while the second one points to the code that first introduced the global function call verification.
v2: - Use resolve_prog_type()
Fixes: 3363bd0cfbb8 ("bpf: Extend kfunc with PTR_TO_CTX, PTR_TO_MEM argument support") Fixes: 51c39bb1d5d1 ("bpf: Introduce function-by-function verification") Reported-by: Simon Sundberg simon.sundberg@kau.se Signed-off-by: Toke Høiland-Jørgensen toke@redhat.com Link: https://lore.kernel.org/r/20220606075253.28422-1-toke@redhat.com Signed-off-by: Alexei Starovoitov ast@kernel.org [ backport: open-code missing resolve_prog_type() helper, resolve context diff ] Signed-off-by: Toke Høiland-Jørgensen toke@redhat.com --- kernel/bpf/btf.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c index 40df35088cdb..3cfba41a0829 100644 --- a/kernel/bpf/btf.c +++ b/kernel/bpf/btf.c @@ -5441,6 +5441,8 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env, struct bpf_reg_state *regs, bool ptr_to_mem_ok) { + enum bpf_prog_type prog_type = env->prog->type == BPF_PROG_TYPE_EXT ? + env->prog->aux->dst_prog->type : env->prog->type; struct bpf_verifier_log *log = &env->log; const char *func_name, *ref_tname; const struct btf_type *t, *ref_t; @@ -5533,8 +5535,7 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env, reg_ref_tname); return -EINVAL; } - } else if (btf_get_prog_ctx_type(log, btf, t, - env->prog->type, i)) { + } else if (btf_get_prog_ctx_type(log, btf, t, prog_type, i)) { /* If function expects ctx type in BTF check that caller * is passing PTR_TO_CTX. */
commit 2cf7b7ffdae519b284f1406012b52e2282fa36bf upstream
Add a selftest that calls a global function with a context object parameter from an freplace function to check that the program context type is correctly converted to the freplace target when fetching the context type from the kernel BTF.
v2: - Trim includes - Get rid of global function - Use __noinline
Signed-off-by: Toke Høiland-Jørgensen toke@redhat.com Link: https://lore.kernel.org/r/20220606075253.28422-2-toke@redhat.com Signed-off-by: Alexei Starovoitov ast@kernel.org [ backport: fix conflict because tests were not serialised ] Signed-off-by: Toke Høiland-Jørgensen toke@redhat.com --- .../selftests/bpf/prog_tests/fexit_bpf2bpf.c | 14 ++++++++++++++ .../selftests/bpf/progs/freplace_global_func.c | 18 ++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 tools/testing/selftests/bpf/progs/freplace_global_func.c
diff --git a/tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c b/tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c index 73b4c76e6b86..52f1426ae06e 100644 --- a/tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c +++ b/tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c @@ -371,6 +371,18 @@ static void test_func_map_prog_compatibility(void) "./test_attach_probe.o"); }
+static void test_func_replace_global_func(void) +{ + const char *prog_name[] = { + "freplace/test_pkt_access", + }; + + test_fexit_bpf2bpf_common("./freplace_global_func.o", + "./test_pkt_access.o", + ARRAY_SIZE(prog_name), + prog_name, false, NULL); +} + void test_fexit_bpf2bpf(void) { if (test__start_subtest("target_no_callees")) @@ -391,4 +403,6 @@ void test_fexit_bpf2bpf(void) test_func_replace_multi(); if (test__start_subtest("fmod_ret_freplace")) test_fmod_ret_freplace(); + if (test__start_subtest("func_replace_global_func")) + test_func_replace_global_func(); } diff --git a/tools/testing/selftests/bpf/progs/freplace_global_func.c b/tools/testing/selftests/bpf/progs/freplace_global_func.c new file mode 100644 index 000000000000..96cb61a6ce87 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/freplace_global_func.c @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-2.0 +#include <linux/bpf.h> +#include <bpf/bpf_helpers.h> + +__noinline +int test_ctx_global_func(struct __sk_buff *skb) +{ + volatile int retval = 1; + return retval; +} + +SEC("freplace/test_pkt_access") +int new_test_pkt_access(struct __sk_buff *skb) +{ + return test_ctx_global_func(skb); +} + +char _license[] SEC("license") = "GPL";
On Tue, Jun 21, 2022 at 10:13:44PM +0200, Toke Høiland-Jørgensen wrote:
commit f858c2b2ca04fc7ead291821a793638ae120c11d upstream
The verifier allows programs to call global functions as long as their argument types match, using BTF to check the function arguments. One of the allowed argument types to such global functions is PTR_TO_CTX; however the check for this fails on BPF_PROG_TYPE_EXT functions because the verifier uses the wrong type to fetch the vmlinux BTF ID for the program context type. This failure is seen when an XDP program is loaded using libxdp (which loads it as BPF_PROG_TYPE_EXT and attaches it to a global XDP type program).
Fix the issue by passing in the target program type instead of the BPF_PROG_TYPE_EXT type to bpf_prog_get_ctx() when checking function argument compatibility.
The first Fixes tag refers to the latest commit that touched the code in question, while the second one points to the code that first introduced the global function call verification.
v2:
- Use resolve_prog_type()
Fixes: 3363bd0cfbb8 ("bpf: Extend kfunc with PTR_TO_CTX, PTR_TO_MEM argument support") Fixes: 51c39bb1d5d1 ("bpf: Introduce function-by-function verification") Reported-by: Simon Sundberg simon.sundberg@kau.se Signed-off-by: Toke Høiland-Jørgensen toke@redhat.com Link: https://lore.kernel.org/r/20220606075253.28422-1-toke@redhat.com Signed-off-by: Alexei Starovoitov ast@kernel.org [ backport: open-code missing resolve_prog_type() helper, resolve context diff ] Signed-off-by: Toke Høiland-Jørgensen toke@redhat.com
All now queued up, thanks.
greg k-h
linux-stable-mirror@lists.linaro.org