1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2026 Meta Platforms, Inc. and affiliates. */ 3 4 #include <vmlinux.h> 5 #include <bpf/bpf_helpers.h> 6 #include "../test_kmods/bpf_testmod_kfunc.h" 7 #include "bpf_misc.h" 8 9 #if (defined(__TARGET_ARCH_x86) || defined(__TARGET_ARCH_arm64) || \ 10 (defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64)) && \ 11 defined(__BPF_FEATURE_STACK_ARGUMENT) 12 13 /* Force kfunc extern BTF generation for inline asm call below. 14 * Uses its own SEC so it's not included as a .text subprog. 15 * The '?' prefix sets autoload=false so libbpf won't load it. 16 */ 17 SEC("?tc") 18 int __btf_kfunc_gen(struct __sk_buff *ctx) 19 { 20 char buf[8] = {}; 21 22 return bpf_kfunc_call_stack_arg_mem(0, 0, 0, 0, 0, buf, sizeof(buf)); 23 } 24 25 /* 26 * Test precision backtracking across bpf-to-bpf call for kfunc stack arg. 27 * subprog_call_mem_kfunc receives a size as incoming stack arg (arg6) 28 * and forwards it as mem__sz (arg7) to bpf_kfunc_call_stack_arg_mem. 29 */ 30 __naked __noinline __used 31 static long subprog_call_mem_kfunc(long a, long b, long c, long d, long e, long size) 32 { 33 asm volatile ( 34 "r1 = *(u64 *)(r11 + 8);" /* r1 = incoming arg6 (size) */ 35 "r2 = 0x0807060504030201 ll;" /* r2 = buf contents */ 36 "*(u64 *)(r10 - 8) = r2;" /* store buf to stack */ 37 "r2 = r10;" 38 "r2 += -8;" /* r2 = &buf */ 39 "*(u64 *)(r11 - 8) = r2;" /* outgoing arg6 = buf */ 40 "*(u64 *)(r11 - 16) = r1;" /* outgoing arg7 = size */ 41 "r1 = 1;" 42 "r2 = 2;" 43 "r3 = 3;" 44 "r4 = 4;" 45 "r5 = 5;" 46 "call %[bpf_kfunc_call_stack_arg_mem];" 47 "exit;" 48 : 49 : __imm(bpf_kfunc_call_stack_arg_mem) 50 : __clobber_all 51 ); 52 } 53 54 SEC("tc") 55 __description("stack_arg: precision backtracking across bpf2bpf call for kfunc") 56 __success 57 __log_level(2) 58 __flag(BPF_F_TEST_STATE_FREQ) 59 __btf_func_path("btf__stack_arg_precision.bpf.o") 60 __msg("mark_precise: frame1: last_idx 26 first_idx 13 subseq_idx -1") 61 __msg("mark_precise: frame1: regs= stack= before 25: (b7) r5 = 5") 62 __msg("mark_precise: frame1: regs= stack= before 24: (b7) r4 = 4") 63 __msg("mark_precise: frame1: regs= stack= before 23: (b7) r3 = 3") 64 __msg("mark_precise: frame1: regs= stack= before 22: (b7) r2 = 2") 65 __msg("mark_precise: frame1: regs= stack= before 21: (b7) r1 = 1") 66 __msg("mark_precise: frame1: regs= stack= before 20: (7b) *(u64 *)(r11 -16) = r1") 67 __msg("mark_precise: frame1: regs=r1 stack= before 19: (7b) *(u64 *)(r11 -8) = r2") 68 __msg("mark_precise: frame1: regs=r1 stack= before 18: (07) r2 += -8") 69 __msg("mark_precise: frame1: regs=r1 stack= before 17: (bf) r2 = r10") 70 __msg("mark_precise: frame1: regs=r1 stack= before 16: (7b) *(u64 *)(r10 -8) = r2") 71 __msg("mark_precise: frame1: regs=r1 stack= before 14: (18) r2 = 0x807060504030201") 72 __msg("mark_precise: frame1: regs=r1 stack= before 13: (79) r1 = *(u64 *)(r11 +8)") 73 __msg("mark_precise: frame1: parent state regs= stack=: frame1: R10=fp0") 74 __msg("mark_precise: frame0: parent state regs= stack=: R10=fp0") 75 __msg("mark_precise: frame1: last_idx 11 first_idx 11 subseq_idx 13") 76 __msg("mark_precise: frame1: regs= stack= before 11: (85) call pc+1") 77 __msg("mark_precise: frame0: parent state regs= stack=: R10=fp0") 78 __msg("mark_precise: frame0: last_idx 9 first_idx 7 subseq_idx 11") 79 __msg("mark_precise: frame0: regs= stack= before 9: (05) goto pc+1") 80 __msg("mark_precise: frame0: regs= stack= before 8: (7a) *(u64 *)(r11 -8) = 4") 81 __msg("mark_precise: frame1: last_idx 26 first_idx 13 subseq_idx -1 ") 82 __msg("mark_precise: frame1: regs= stack= before 25: (b7) r5 = 5") 83 __msg("mark_precise: frame1: regs= stack= before 24: (b7) r4 = 4") 84 __msg("mark_precise: frame1: regs= stack= before 23: (b7) r3 = 3") 85 __msg("mark_precise: frame1: regs= stack= before 22: (b7) r2 = 2") 86 __msg("mark_precise: frame1: regs= stack= before 21: (b7) r1 = 1") 87 __msg("mark_precise: frame1: regs= stack= before 20: (7b) *(u64 *)(r11 -16) = r1") 88 __msg("mark_precise: frame1: regs=r1 stack= before 19: (7b) *(u64 *)(r11 -8) = r2") 89 __msg("mark_precise: frame1: regs=r1 stack= before 18: (07) r2 += -8") 90 __msg("mark_precise: frame1: regs=r1 stack= before 17: (bf) r2 = r10") 91 __msg("mark_precise: frame1: regs=r1 stack= before 16: (7b) *(u64 *)(r10 -8) = r2") 92 __msg("mark_precise: frame1: regs=r1 stack= before 14: (18) r2 = 0x807060504030201") 93 __msg("mark_precise: frame1: regs=r1 stack= before 13: (79) r1 = *(u64 *)(r11 +8)") 94 __msg("mark_precise: frame1: parent state regs= stack=: frame1: R10=fp0") 95 __msg("mark_precise: frame0: parent state regs= stack=: R10=fp0") 96 __msg("mark_precise: frame1: last_idx 11 first_idx 11 subseq_idx 13 ") 97 __msg("mark_precise: frame1: regs= stack= before 11: (85) call pc+1") 98 __msg("mark_precise: frame0: parent state regs= stack=: R10=fp0") 99 __msg("mark_precise: frame0: last_idx 10 first_idx 10 subseq_idx 11 ") 100 __msg("mark_precise: frame0: regs= stack= before 10: (7a) *(u64 *)(r11 -8) = 6") 101 __naked void stack_arg_precision_bpf2bpf(void) 102 { 103 asm volatile ( 104 "call %[bpf_get_prandom_u32];" 105 "r6 = r0;" 106 "r1 = 1;" 107 "r2 = 2;" 108 "r3 = 3;" 109 "r4 = 4;" 110 "r5 = 5;" 111 "if r6 < 2 goto l0_%=;" 112 "*(u64 *)(r11 - 8) = 4;" 113 "goto l1_%=;" 114 "l0_%=:" 115 "*(u64 *)(r11 - 8) = 6;" 116 "l1_%=:" 117 "call subprog_call_mem_kfunc;" 118 "exit;" 119 :: __imm(bpf_get_prandom_u32) 120 : __clobber_all 121 ); 122 } 123 124 #else 125 126 SEC("socket") 127 __description("stack_arg_precision: not supported, dummy test") 128 __skip("stack_arg_precision: not supported") 129 __success 130 int dummy_test(void) 131 { 132 return 0; 133 } 134 135 #endif 136 137 char _license[] SEC("license") = "GPL"; 138