selftests/bpf: Add tests for callx

Add verifier_callx tests:
- calls via r0, callee saved regs, pointer passed as argument, returned
  from subprog, spilled/filled, different callees on different paths.
  These are executed to test JIT.
- invalid operands: scalar, other pointers, modified and variable
  PTR_TO_FUNC, global functions, reserved fields, JMP32.
- callx under lock.
- bounded and unbounded recursion via callx.
- stack depth of call chains through callx, including address taken
  several frames above callx.
- tail calls in the callee and the caller of callx.
- stack liveness: caller slots read by callee stay alive.
- no const propagation across callx.
- precision backtracking through callx.
- address of a function that is never called, with and without callx.
- function pointers in C.

callx needs JIT. Add RUN_JITED() to skip the tests when it's off.

Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://patch.msgid.link/20260924031042.1690890-16-alexei.starovoitov@gmail.com
This commit is contained in:
Alexei Starovoitov 2026-09-24 03:10:40 +00:00
parent 9f99fc05fc
commit e9b22d5079
No known key found for this signature in database
2 changed files with 1049 additions and 0 deletions

View File

@ -28,6 +28,7 @@
#include "verifier_btf_ctx_access.skel.h" #include "verifier_btf_ctx_access.skel.h"
#include "verifier_btf_unreliable_prog.skel.h" #include "verifier_btf_unreliable_prog.skel.h"
#include "verifier_call_large_imm.skel.h" #include "verifier_call_large_imm.skel.h"
#include "verifier_callx.skel.h"
#include "verifier_cfg.skel.h" #include "verifier_cfg.skel.h"
#include "verifier_cgroup_inv_retcode.skel.h" #include "verifier_cgroup_inv_retcode.skel.h"
#include "verifier_cgroup_skb.skel.h" #include "verifier_cgroup_skb.skel.h"
@ -173,6 +174,14 @@ static void run_tests_aux(const char *skel_name,
#define RUN(skel) run_tests_aux(#skel, skel##__elf_bytes, NULL) #define RUN(skel) run_tests_aux(#skel, skel##__elf_bytes, NULL)
/* for tests of what the interpreter doesn't support */
#define RUN_JITED(skel) do { \
if (is_jit_enabled()) \
RUN(skel); \
else \
test__skip(); \
} while (0)
void test_arena_kfunc(void) { RUN_TESTS(arena_kfunc); } void test_arena_kfunc(void) { RUN_TESTS(arena_kfunc); }
void test_arena_kfunc_jit(void) { RUN_TESTS(arena_kfunc_jit); } void test_arena_kfunc_jit(void) { RUN_TESTS(arena_kfunc_jit); }
@ -199,6 +208,7 @@ void test_verifier_bswap(void) { RUN(verifier_bswap); }
void test_verifier_btf_ctx_access(void) { RUN(verifier_btf_ctx_access); } void test_verifier_btf_ctx_access(void) { RUN(verifier_btf_ctx_access); }
void test_verifier_btf_unreliable_prog(void) { RUN(verifier_btf_unreliable_prog); } void test_verifier_btf_unreliable_prog(void) { RUN(verifier_btf_unreliable_prog); }
void test_verifier_call_large_imm(void) { RUN(verifier_call_large_imm); } void test_verifier_call_large_imm(void) { RUN(verifier_call_large_imm); }
void test_verifier_callx(void) { RUN_JITED(verifier_callx); }
void test_verifier_cfg(void) { RUN(verifier_cfg); } void test_verifier_cfg(void) { RUN(verifier_cfg); }
void test_verifier_cgroup_inv_retcode(void) { RUN(verifier_cgroup_inv_retcode); } void test_verifier_cgroup_inv_retcode(void) { RUN(verifier_cgroup_inv_retcode); }
void test_verifier_cgroup_skb(void) { RUN(verifier_cgroup_skb); } void test_verifier_cgroup_skb(void) { RUN(verifier_cgroup_skb); }

File diff suppressed because it is too large Load Diff