summaryrefslogtreecommitdiff
path: root/tools/testing
diff options
context:
space:
mode:
authorKumar Kartikeya Dwivedi <memxor@gmail.com>2026-09-21 04:38:33 +0200
committerAlexei Starovoitov <ast@kernel.org>2026-09-21 17:12:39 +0000
commita25a61385b04c957277bc421d703e79c8ecf4841 (patch)
treeb75a234581c0faa882d35f0f2ed8286e68dabad9 /tools/testing
parent5da4a9f26fca03ccd8afcc88f5c709c459c00ab8 (diff)
downloadlinux-next-a25a61385b04c957277bc421d703e79c8ecf4841.tar.gz
linux-next-a25a61385b04c957277bc421d703e79c8ecf4841.zip
selftests/bpf: Cover generic output stack initialization
Exercise generic output buffers with and without CAP_PERFMON, using both helpers and __uninit kfuncs. Check that initialized bytes stay readable and lose stale value information, while invalid bytes remain unreadable without permission to read uninitialized stack memory. Cover constant and variable sizes, scalar spills, pointer spills, special stack objects, and privileged variable offsets. Add a kfunc that writes only the first byte of its output. Its runtime tests read preinitialized bytes, checking both the written byte and an untouched tail byte across a liveness checkpoint. Verify that the sysctl name helper and uninitialized fixed and variable-sized kfunc outputs are accepted when their contents are not read back. Update existing __uninit readback expectations and exercise skb_load_bytes with reduced capabilities. Even fully-writing generic outputs now preserve invalid bytes in the verifier, so reading those bytes requires prior initialization by the BPF program. Use map_update_elem inputs for helper_arg_fallback_keeps_scanning. Its original snprintf argument no longer reads the buffer, and a privileged output with an unknown size does not trigger the whole-stack read fallback. A variable-offset key and parent-frame value retain the intended assertion. Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Link: https://patch.msgid.link/20260921023843.411943-10-memxor@gmail.com
Diffstat (limited to 'tools/testing')
-rw-r--r--tools/testing/selftests/bpf/progs/verifier_helper_access_var_len.c189
-rw-r--r--tools/testing/selftests/bpf/progs/verifier_kfunc_uninit.c136
-rw-r--r--tools/testing/selftests/bpf/progs/verifier_kfunc_uninit_multi.c6
-rw-r--r--tools/testing/selftests/bpf/progs/verifier_live_stack.c33
-rw-r--r--tools/testing/selftests/bpf/progs/verifier_raw_stack.c4
-rw-r--r--tools/testing/selftests/bpf/test_kmods/bpf_testmod.c7
-rw-r--r--tools/testing/selftests/bpf/test_kmods/bpf_testmod_kfunc.h1
7 files changed, 356 insertions, 20 deletions
diff --git a/tools/testing/selftests/bpf/progs/verifier_helper_access_var_len.c b/tools/testing/selftests/bpf/progs/verifier_helper_access_var_len.c
index d1452ef6f2f9..e87eb6f221e4 100644
--- a/tools/testing/selftests/bpf/progs/verifier_helper_access_var_len.c
+++ b/tools/testing/selftests/bpf/progs/verifier_helper_access_var_len.c
@@ -822,4 +822,193 @@ __naked void bytes_no_leak_init_memory(void)
: __clobber_all);
}
+SEC("cgroup/sysctl")
+__success
+__caps_unpriv(CAP_BPF | CAP_NET_ADMIN)
+__success_unpriv
+__naked void sysctl_initialized_stack(void)
+{
+ asm volatile (
+ "*(u64 *)(r10 - 16) = 0;"
+ "*(u64 *)(r10 - 8) = 0;"
+ "r2 = r10;"
+ "r2 += -16;"
+ "r3 = 16;"
+ "r4 = 0;"
+ "call %[bpf_sysctl_get_name];"
+ "r0 = *(u8 *)(r10 - 1);"
+ "r0 &= 1;"
+ "exit;"
+ : : __imm(bpf_sysctl_get_name) : __clobber_all);
+}
+
+SEC("cgroup/sysctl")
+__success
+__caps_unpriv(CAP_BPF | CAP_NET_ADMIN)
+__success_unpriv
+__naked void sysctl_uninitialized_stack(void)
+{
+ asm volatile (
+ "r2 = r10;"
+ "r2 += -16;"
+ "r3 = 16;"
+ "r4 = 0;"
+ "call %[bpf_sysctl_get_name];"
+ "r0 = 0;"
+ "exit;"
+ : : __imm(bpf_sysctl_get_name) : __clobber_all);
+}
+
+SEC("cgroup/sysctl")
+__success
+__flag(BPF_F_TEST_STATE_FREQ)
+__caps_unpriv(CAP_BPF | CAP_NET_ADMIN)
+__success_unpriv
+__naked void sysctl_partial_initialized_bytes(void)
+{
+ asm volatile (
+ "*(u32 *)(r10 - 16) = 0;"
+ "*(u8 *)(r10 - 1) = 1;"
+ "goto +0;"
+ "r2 = r10;"
+ "r2 += -16;"
+ "r3 = 16;"
+ "r4 = 0;"
+ "call %[bpf_sysctl_get_name];"
+ "r0 = *(u32 *)(r10 - 16);"
+ "r1 = *(u8 *)(r10 - 1);"
+ "r0 += r1;"
+ "r0 &= 1;"
+ "exit;"
+ : : __imm(bpf_sysctl_get_name) : __clobber_all);
+}
+
+SEC("cgroup/sysctl")
+__success
+__caps_unpriv(CAP_BPF | CAP_NET_ADMIN)
+__failure_unpriv __msg_unpriv("invalid read from stack off -1+0 size 1")
+__naked void sysctl_partial_invalid_bytes(void)
+{
+ asm volatile (
+ "*(u32 *)(r10 - 16) = 0;"
+ "r2 = r10;"
+ "r2 += -16;"
+ "r3 = 16;"
+ "r4 = 0;"
+ "call %[bpf_sysctl_get_name];"
+ "r0 = *(u8 *)(r10 - 1);"
+ "r0 &= 1;"
+ "exit;"
+ : : __imm(bpf_sysctl_get_name) : __clobber_all);
+}
+
+SEC("cgroup/sysctl")
+__success
+__flag(BPF_F_TEST_STATE_FREQ)
+__caps_unpriv(CAP_BPF | CAP_NET_ADMIN)
+__success_unpriv
+__naked void sysctl_partial_variable_size(void)
+{
+ asm volatile (
+ "r3 = *(u32 *)(r1 + 0);"
+ "r3 &= 15;"
+ "r3 += 1;"
+ "*(u8 *)(r10 - 1) = 1;"
+ "goto +0;"
+ "r2 = r10;"
+ "r2 += -16;"
+ "r4 = 0;"
+ "call %[bpf_sysctl_get_name];"
+ "r0 = *(u8 *)(r10 - 1);"
+ "r0 &= 1;"
+ "exit;"
+ : : __imm(bpf_sysctl_get_name) : __clobber_all);
+}
+
+SEC("cgroup/sysctl")
+__success
+__caps_unpriv(CAP_BPF | CAP_NET_ADMIN)
+__failure_unpriv __msg_unpriv("invalid read from stack off -1+0 size 1")
+__naked void sysctl_partial_variable_invalid(void)
+{
+ asm volatile (
+ "r3 = *(u32 *)(r1 + 0);"
+ "r3 &= 15;"
+ "r3 += 1;"
+ "r2 = r10;"
+ "r2 += -16;"
+ "r4 = 0;"
+ "call %[bpf_sysctl_get_name];"
+ "r0 = *(u8 *)(r10 - 1);"
+ "r0 &= 1;"
+ "exit;"
+ : : __imm(bpf_sysctl_get_name) : __clobber_all);
+}
+
+SEC("cgroup/sysctl")
+__success
+__flag(BPF_F_TEST_STATE_FREQ)
+__caps_unpriv(CAP_BPF | CAP_NET_ADMIN)
+__failure_unpriv __msg_unpriv("invalid read from stack R2")
+__naked void sysctl_partial_spilled_pointer(void)
+{
+ asm volatile (
+ "*(u64 *)(r10 - 8) = r1;"
+ "goto +0;"
+ "r2 = r10;"
+ "r2 += -8;"
+ "r3 = 8;"
+ "r4 = 0;"
+ "call %[bpf_sysctl_get_name];"
+ "r0 = 0;"
+ "exit;"
+ : : __imm(bpf_sysctl_get_name) : __clobber_all);
+}
+
+SEC("cgroup/sysctl")
+__success
+__caps_unpriv(CAP_BPF | CAP_NET_ADMIN)
+__failure_unpriv __msg_unpriv("invalid read from stack R2")
+int sysctl_partial_dynptr(struct bpf_sysctl *ctx)
+{
+ struct bpf_dynptr ptr;
+ long long key = 0, *data;
+
+ data = bpf_map_lookup_elem(&map_hash_8b, &key);
+ if (!data)
+ return 0;
+ bpf_dynptr_from_mem(data, sizeof(*data), 0, &ptr);
+ bpf_sysctl_get_name(ctx, (char *)&ptr, sizeof(ptr), 0);
+ return 0;
+}
+
+SEC("cgroup/sysctl")
+__success
+__naked void sysctl_partial_variable_offset(void)
+{
+ asm volatile (
+ "r2 = *(u32 *)(r1 + 0);"
+ "r2 &= 8;"
+ "r2 += r10;"
+ "r2 += -24;"
+ "r3 = 16;"
+ "r4 = 0;"
+ "call %[bpf_sysctl_get_name];"
+ "r0 = *(u8 *)(r10 - 16);"
+ "r0 &= 1;"
+ "exit;"
+ : : __imm(bpf_sysctl_get_name) : __clobber_all);
+}
+
+SEC("tc")
+__success __retval(42)
+int snprintf_partial_output_runtime(struct __sk_buff *ctx)
+{
+ char buf[16];
+
+ buf[15] = 42;
+ bpf_snprintf(buf, sizeof(buf), "ok", NULL, 0);
+ return buf[15];
+}
+
char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/verifier_kfunc_uninit.c b/tools/testing/selftests/bpf/progs/verifier_kfunc_uninit.c
index f7818303e703..ff2fb36a0260 100644
--- a/tools/testing/selftests/bpf/progs/verifier_kfunc_uninit.c
+++ b/tools/testing/selftests/bpf/progs/verifier_kfunc_uninit.c
@@ -12,6 +12,7 @@ void __kfunc_btf_root(void)
asm volatile ("" :
: "r"(&bpf_kfunc_test_uninit_struct),
"r"(&bpf_kfunc_test_uninit_mem),
+ "r"(&bpf_kfunc_test_uninit_partial),
"r"(&bpf_kfunc_test_uninit_alias));
}
@@ -97,4 +98,139 @@ __naked void uninitialized_input_alias(void)
: : __imm(bpf_kfunc_test_uninit_alias) : __clobber_all);
}
+SEC("tc")
+__success __retval(0)
+__caps_unpriv(CAP_BPF | CAP_NET_ADMIN)
+__prepare_priv
+__success_unpriv
+__naked void uninitialized_struct_output_ignored(void)
+{
+ asm volatile (
+ "r1 = r10;"
+ "r1 += -16;"
+ "call %[bpf_kfunc_test_uninit_struct];"
+ "r0 = 0;"
+ "exit;"
+ : : __imm(bpf_kfunc_test_uninit_struct) : __clobber_all);
+}
+
+SEC("tc")
+__success __retval(0)
+__caps_unpriv(CAP_BPF | CAP_NET_ADMIN)
+__prepare_priv
+__success_unpriv
+__naked void variable_size_uninitialized_output_ignored(void)
+{
+ asm volatile (
+ "r2 = *(u32 *)(r1 + 0);"
+ "r2 &= 7;"
+ "r2 += 1;"
+ "r1 = r10;"
+ "r1 += -8;"
+ "call %[bpf_kfunc_test_uninit_mem];"
+ "r0 = 0;"
+ "exit;"
+ : : __imm(bpf_kfunc_test_uninit_mem) : __clobber_all);
+}
+
+SEC("tc")
+__success __retval(49)
+__flag(BPF_F_TEST_STATE_FREQ)
+__caps_unpriv(CAP_BPF | CAP_NET_ADMIN)
+__prepare_priv
+__success_unpriv
+__naked void partial_output_preserves_initialized_bytes(void)
+{
+ asm volatile (
+ "*(u8 *)(r10 - 8) = 0;"
+ "*(u8 *)(r10 - 1) = 7;"
+ "goto +0;"
+ "r1 = r10;"
+ "r1 += -8;"
+ "r2 = 8;"
+ "call %[bpf_kfunc_test_uninit_partial];"
+ "r0 = *(u8 *)(r10 - 8);"
+ "r1 = *(u8 *)(r10 - 1);"
+ "r0 += r1;"
+ "exit;"
+ : : __imm(bpf_kfunc_test_uninit_partial) : __clobber_all);
+}
+
+SEC("tc")
+__success __retval(42)
+__caps_unpriv(CAP_BPF | CAP_NET_ADMIN)
+__prepare_priv
+__failure_unpriv __msg_unpriv("invalid read from stack off -8+0 size 1")
+__naked void uninitialized_sized_output_read(void)
+{
+ asm volatile (
+ "r1 = r10;"
+ "r1 += -8;"
+ "r2 = 8;"
+ "call %[bpf_kfunc_test_uninit_mem];"
+ "r0 = *(u8 *)(r10 - 8);"
+ "exit;"
+ : : __imm(bpf_kfunc_test_uninit_mem) : __clobber_all);
+}
+
+SEC("tc")
+__success __retval(42)
+__caps_unpriv(CAP_BPF | CAP_NET_ADMIN)
+__prepare_priv
+__failure_unpriv __msg_unpriv("invalid read from stack off -8+0 size 1")
+__naked void variable_size_uninitialized_output_read(void)
+{
+ asm volatile (
+ "r2 = *(u32 *)(r1 + 0);"
+ "r2 &= 7;"
+ "r2 += 1;"
+ "r1 = r10;"
+ "r1 += -8;"
+ "call %[bpf_kfunc_test_uninit_mem];"
+ "r0 = *(u8 *)(r10 - 8);"
+ "exit;"
+ : : __imm(bpf_kfunc_test_uninit_mem) : __clobber_all);
+}
+
+SEC("tc")
+__success __retval(1)
+__caps_unpriv(CAP_BPF | CAP_NET_ADMIN)
+__prepare_priv
+__failure_unpriv __msg_unpriv("invalid read from stack off -16+0 size 4")
+__naked void fixed_struct_uninitialized_output_read(void)
+{
+ asm volatile (
+ "r1 = r10;"
+ "r1 += -16;"
+ "call %[bpf_kfunc_test_uninit_struct];"
+ "r0 = *(u32 *)(r10 - 16);"
+ "exit;"
+ : : __imm(bpf_kfunc_test_uninit_struct) : __clobber_all);
+}
+
+SEC("tc")
+__success __retval(49)
+__flag(BPF_F_TEST_STATE_FREQ)
+__caps_unpriv(CAP_BPF | CAP_NET_ADMIN)
+__prepare_priv
+__success_unpriv
+__naked void partial_output_variable_size(void)
+{
+ asm volatile (
+ "r2 = *(u32 *)(r1 + 0);"
+ "r2 &= 7;"
+ "r2 += 1;"
+ "*(u8 *)(r10 - 8) = 0;"
+ "*(u8 *)(r10 - 1) = 7;"
+ "goto +0;"
+ "r1 = r10;"
+ "r1 += -8;"
+ "call %[bpf_kfunc_test_uninit_partial];"
+ "r0 = *(u8 *)(r10 - 8);"
+ "r1 = *(u8 *)(r10 - 1);"
+ "r0 += r1;"
+ "exit;"
+ : : __imm(bpf_kfunc_test_uninit_partial) : __clobber_all);
+}
+
char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/verifier_kfunc_uninit_multi.c b/tools/testing/selftests/bpf/progs/verifier_kfunc_uninit_multi.c
index 18ced0d0a3b2..ab3bb81a11fd 100644
--- a/tools/testing/selftests/bpf/progs/verifier_kfunc_uninit_multi.c
+++ b/tools/testing/selftests/bpf/progs/verifier_kfunc_uninit_multi.c
@@ -49,7 +49,7 @@ SEC("tc")
__success __retval(42)
__caps_unpriv(CAP_BPF | CAP_NET_ADMIN)
__prepare_priv
-__success_unpriv
+__failure_unpriv __msg_unpriv("invalid read from stack off -16+0 size 4")
__naked void variable_size_preserves_other_output(void)
{
asm volatile (
@@ -71,7 +71,7 @@ __arch_x86_64 __arch_arm64
__success __retval(42)
__caps_unpriv(CAP_BPF | CAP_NET_ADMIN)
__prepare_priv
-__success_unpriv
+__failure_unpriv __msg_unpriv("invalid read from stack off -8+0 size 4")
__naked void output_after_by_value_argument(void)
{
asm volatile (
@@ -91,7 +91,7 @@ __arch_x86_64 __arch_arm64 __arch_riscv64
__success __retval(15)
__caps_unpriv(CAP_BPF | CAP_NET_ADMIN)
__prepare_priv
-__success_unpriv
+__failure_unpriv __msg_unpriv("invalid read from stack off -8+0 size 4")
__naked void output_passed_on_stack(void)
{
asm volatile (
diff --git a/tools/testing/selftests/bpf/progs/verifier_live_stack.c b/tools/testing/selftests/bpf/progs/verifier_live_stack.c
index bc3dfdc1a536..7a1a0670f851 100644
--- a/tools/testing/selftests/bpf/progs/verifier_live_stack.c
+++ b/tools/testing/selftests/bpf/progs/verifier_live_stack.c
@@ -21,8 +21,6 @@ struct {
__type(value, __u64);
} array_map_8b SEC(".maps");
-const char snprintf_u64_fmt[] = "%llu";
-
SEC("socket")
__log_level(2)
__msg("0: (79) r1 = *(u64 *)(r10 -8) ; use: fp0-8")
@@ -1947,15 +1945,15 @@ static __used __naked void fwd_parent_key_to_helper(void)
/*
* Regression for keeping later helper args after a whole-stack fallback
- * on an earlier local arg. The first bpf_snprintf() arg is a local
+ * on an earlier local arg. The bpf_map_update_elem() key is a local
* frame-derived pointer with offset-imprecise tracking (`fp1 ?`), which
- * conservatively marks the whole local stack live. The fourth arg still
+ * conservatively marks the whole local stack live. The value arg still
* forwards &parent_fp-8 and must contribute nonlocal_use[0]=0:3.
*/
SEC("socket")
__log_level(2)
__success
-__msg("call bpf_snprintf{{.*}} ; use: fp1-8..-512 fp0-8")
+__msg("call bpf_map_update_elem{{.*}}; use: fp1-8..-512 fp0-8")
__naked void helper_arg_fallback_keeps_scanning(void)
{
asm volatile (
@@ -1963,32 +1961,33 @@ __naked void helper_arg_fallback_keeps_scanning(void)
"*(u64 *)(r10 - 8) = r1;"
"r1 = r10;"
"r1 += -8;"
- "call helper_snprintf_parent_after_local_fallback;"
+ "call helper_update_parent_after_local_fallback;"
"r0 = 0;"
"exit;"
::: __clobber_all);
}
-static __used __naked void helper_snprintf_parent_after_local_fallback(void)
+static __used __naked void helper_update_parent_after_local_fallback(void)
{
asm volatile (
"r6 = r1;" /* save &parent_fp-8 */
"call %[bpf_get_prandom_u32];"
"r0 &= 8;"
- "r1 = r10;"
- "r1 += -16;"
- "r1 += r0;" /* local fp, offset-imprecise */
- "r2 = 8;"
- "r3 = %[snprintf_u64_fmt] ll;"
- "r4 = r6;" /* later arg: parent fp-8 */
- "r5 = 8;"
- "call %[bpf_snprintf];"
+ "*(u64 *)(r10 - 16) = 0;"
+ "*(u64 *)(r10 - 8) = 0;"
+ "r2 = r10;"
+ "r2 += -16;"
+ "r2 += r0;" /* local fp, offset-imprecise */
+ "r1 = %[array_map_8b] ll;"
+ "r3 = r6;" /* later arg: parent fp-8 */
+ "r4 = 0;"
+ "call %[bpf_map_update_elem];"
"r0 = 0;"
"exit;"
:
: __imm(bpf_get_prandom_u32),
- __imm(bpf_snprintf),
- __imm_addr(snprintf_u64_fmt)
+ __imm(bpf_map_update_elem),
+ __imm_addr(array_map_8b)
: __clobber_all);
}
diff --git a/tools/testing/selftests/bpf/progs/verifier_raw_stack.c b/tools/testing/selftests/bpf/progs/verifier_raw_stack.c
index c689665e07b9..9f0f48ecb421 100644
--- a/tools/testing/selftests/bpf/progs/verifier_raw_stack.c
+++ b/tools/testing/selftests/bpf/progs/verifier_raw_stack.c
@@ -84,6 +84,8 @@ __naked void skb_load_bytes_zero_len(void)
SEC("tc")
__description("raw_stack: skb_load_bytes, no init")
__success __retval(0)
+__caps_unpriv(CAP_BPF | CAP_NET_ADMIN)
+__failure_unpriv __msg_unpriv("invalid read from stack off -8+0 size 8")
__naked void skb_load_bytes_no_init(void)
{
asm volatile (" \
@@ -103,6 +105,8 @@ __naked void skb_load_bytes_no_init(void)
SEC("tc")
__description("raw_stack: skb_load_bytes, init")
__success __retval(0)
+__caps_unpriv(CAP_BPF | CAP_NET_ADMIN)
+__success_unpriv
__naked void stack_skb_load_bytes_init(void)
{
asm volatile (" \
diff --git a/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c b/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c
index 211886a8ee87..93847ca6293b 100644
--- a/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c
+++ b/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c
@@ -1330,6 +1330,12 @@ __bpf_kfunc void bpf_kfunc_test_uninit_mem(void *out__uninit, u32 out__sz)
memset(out__uninit, 0x2a, out__sz);
}
+__bpf_kfunc void bpf_kfunc_test_uninit_partial(void *out__uninit, u32 out__sz)
+{
+ if (out__sz)
+ *(u8 *)out__uninit = 42;
+}
+
__bpf_kfunc int bpf_kfunc_test_uninit_alias(int *out__uninit, const int *in)
{
int value = get_unaligned(in);
@@ -1788,6 +1794,7 @@ BTF_ID_FLAGS(func, bpf_kfunc_call_test_pass1)
BTF_ID_FLAGS(func, bpf_kfunc_call_test_pass2)
BTF_ID_FLAGS(func, bpf_kfunc_test_uninit_struct)
BTF_ID_FLAGS(func, bpf_kfunc_test_uninit_mem)
+BTF_ID_FLAGS(func, bpf_kfunc_test_uninit_partial)
BTF_ID_FLAGS(func, bpf_kfunc_test_uninit_alias)
BTF_ID_FLAGS(func, bpf_kfunc_test_uninit_multi)
BTF_ID_FLAGS(func, bpf_kfunc_test_uninit_pair)
diff --git a/tools/testing/selftests/bpf/test_kmods/bpf_testmod_kfunc.h b/tools/testing/selftests/bpf/test_kmods/bpf_testmod_kfunc.h
index 524f2cb9bdf4..67c02a421d13 100644
--- a/tools/testing/selftests/bpf/test_kmods/bpf_testmod_kfunc.h
+++ b/tools/testing/selftests/bpf/test_kmods/bpf_testmod_kfunc.h
@@ -291,6 +291,7 @@ void bpf_kfunc_call_test_pass1(struct prog_test_pass1 *p) __ksym;
void bpf_kfunc_call_test_pass2(struct prog_test_pass2 *p) __ksym;
void bpf_kfunc_test_uninit_struct(struct prog_test_pass1 *out__uninit) __ksym;
void bpf_kfunc_test_uninit_mem(void *out__uninit, __u32 out__sz) __ksym;
+void bpf_kfunc_test_uninit_partial(void *out__uninit, __u32 out__sz) __ksym;
int bpf_kfunc_test_uninit_alias(int *out__uninit, const int *in) __ksym;
void bpf_kfunc_test_uninit_multi(int *a__uninit, void *b__uninit, __u32 b__sz) __ksym;
void bpf_kfunc_test_uninit_pair(struct prog_test_pair_arg p, int *out__uninit) __ksym;