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