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