1 // SPDX-License-Identifier: GPL-2.0 2 3 #include <vmlinux.h> 4 #include <bpf/bpf_helpers.h> 5 #include "bpf_misc.h" 6 #include "bpf_experimental.h" 7 8 /* From include/linux/filter.h */ 9 #define MAX_BPF_STACK 512 10 11 #if defined(__TARGET_ARCH_x86) 12 13 struct elem { 14 struct bpf_timer t; 15 char pad[256]; 16 }; 17 18 struct { 19 __uint(type, BPF_MAP_TYPE_ARRAY); 20 __uint(max_entries, 1); 21 __type(key, int); 22 __type(value, struct elem); 23 } array SEC(".maps"); 24 25 SEC("kprobe") 26 __description("Private stack, single prog") 27 __success 28 __arch_x86_64 29 __jited(" movabsq $0x{{.*}}, %r9") 30 __jited(" addq %gs:0x{{.*}}, %r9") 31 __jited(" movl $0x2a, %edi") 32 __jited(" movq %rdi, -0x100(%r9)") 33 __naked void private_stack_single_prog(void) 34 { 35 asm volatile (" \ 36 r1 = 42; \ 37 *(u64 *)(r10 - 256) = r1; \ 38 r0 = 0; \ 39 exit; \ 40 " ::: __clobber_all); 41 } 42 43 SEC("raw_tp") 44 __description("No private stack") 45 __success 46 __arch_x86_64 47 __jited(" subq $0x8, %rsp") 48 __naked void no_private_stack_nested(void) 49 { 50 asm volatile (" \ 51 r1 = 42; \ 52 *(u64 *)(r10 - 8) = r1; \ 53 r0 = 0; \ 54 exit; \ 55 " ::: __clobber_all); 56 } 57 58 __used 59 __naked static void cumulative_stack_depth_subprog(void) 60 { 61 asm volatile (" \ 62 r1 = 41; \ 63 *(u64 *)(r10 - 32) = r1; \ 64 call %[bpf_get_smp_processor_id]; \ 65 exit; \ 66 " : 67 : __imm(bpf_get_smp_processor_id) 68 : __clobber_all); 69 } 70 71 SEC("kprobe") 72 __description("Private stack, subtree > MAX_BPF_STACK") 73 __success 74 __arch_x86_64 75 /* private stack fp for the main prog */ 76 __jited(" movabsq $0x{{.*}}, %r9") 77 __jited(" addq %gs:0x{{.*}}, %r9") 78 __jited(" movl $0x2a, %edi") 79 __jited(" movq %rdi, -0x200(%r9)") 80 __jited(" pushq %r9") 81 __jited(" callq 0x{{.*}}") 82 __jited(" popq %r9") 83 __jited(" xorl %eax, %eax") 84 __naked void private_stack_nested_1(void) 85 { 86 asm volatile (" \ 87 r1 = 42; \ 88 *(u64 *)(r10 - %[max_bpf_stack]) = r1; \ 89 call cumulative_stack_depth_subprog; \ 90 r0 = 0; \ 91 exit; \ 92 " : 93 : __imm_const(max_bpf_stack, MAX_BPF_STACK) 94 : __clobber_all); 95 } 96 97 __naked __noinline __used 98 static unsigned long loop_callback(void) 99 { 100 asm volatile (" \ 101 call %[bpf_get_prandom_u32]; \ 102 r1 = 42; \ 103 *(u64 *)(r10 - 512) = r1; \ 104 call cumulative_stack_depth_subprog; \ 105 r0 = 0; \ 106 exit; \ 107 " : 108 : __imm(bpf_get_prandom_u32) 109 : __clobber_common); 110 } 111 112 SEC("raw_tp") 113 __description("Private stack, callback") 114 __success 115 __arch_x86_64 116 /* for func loop_callback */ 117 __jited("func #1") 118 __jited(" endbr64") 119 __jited(" nopl (%rax,%rax)") 120 __jited(" nopl (%rax)") 121 __jited(" pushq %rbp") 122 __jited(" movq %rsp, %rbp") 123 __jited(" endbr64") 124 __jited(" movabsq $0x{{.*}}, %r9") 125 __jited(" addq %gs:0x{{.*}}, %r9") 126 __jited(" pushq %r9") 127 __jited(" callq") 128 __jited(" popq %r9") 129 __jited(" movl $0x2a, %edi") 130 __jited(" movq %rdi, -0x200(%r9)") 131 __jited(" pushq %r9") 132 __jited(" callq") 133 __jited(" popq %r9") 134 __naked void private_stack_callback(void) 135 { 136 asm volatile (" \ 137 r1 = 1; \ 138 r2 = %[loop_callback]; \ 139 r3 = 0; \ 140 r4 = 0; \ 141 call %[bpf_loop]; \ 142 r0 = 0; \ 143 exit; \ 144 " : 145 : __imm_ptr(loop_callback), 146 __imm(bpf_loop) 147 : __clobber_common); 148 } 149 150 SEC("fentry/bpf_fentry_test9") 151 __description("Private stack, exception in main prog") 152 __success __retval(0) 153 __arch_x86_64 154 __jited(" pushq %r9") 155 __jited(" callq") 156 __jited(" popq %r9") 157 int private_stack_exception_main_prog(void) 158 { 159 asm volatile (" \ 160 r1 = 42; \ 161 *(u64 *)(r10 - 512) = r1; \ 162 " ::: __clobber_common); 163 164 bpf_throw(0); 165 return 0; 166 } 167 168 __used static int subprog_exception(void) 169 { 170 bpf_throw(0); 171 return 0; 172 } 173 174 SEC("fentry/bpf_fentry_test9") 175 __description("Private stack, exception in subprog") 176 __success __retval(0) 177 __arch_x86_64 178 __jited(" movq %rdi, -0x200(%r9)") 179 __jited(" pushq %r9") 180 __jited(" callq") 181 __jited(" popq %r9") 182 int private_stack_exception_sub_prog(void) 183 { 184 asm volatile (" \ 185 r1 = 42; \ 186 *(u64 *)(r10 - 512) = r1; \ 187 call subprog_exception; \ 188 " ::: __clobber_common); 189 190 return 0; 191 } 192 193 int glob; 194 __noinline static void subprog2(int *val) 195 { 196 glob += val[0] * 2; 197 } 198 199 __noinline static void subprog1(int *val) 200 { 201 int tmp[64] = {}; 202 203 tmp[0] = *val; 204 subprog2(tmp); 205 } 206 207 __noinline static int timer_cb1(void *map, int *key, struct bpf_timer *timer) 208 { 209 subprog1(key); 210 return 0; 211 } 212 213 __noinline static int timer_cb2(void *map, int *key, struct bpf_timer *timer) 214 { 215 return 0; 216 } 217 218 SEC("fentry/bpf_fentry_test9") 219 __description("Private stack, async callback, not nested") 220 __success __retval(0) 221 __arch_x86_64 222 __jited(" movabsq $0x{{.*}}, %r9") 223 int private_stack_async_callback_1(void) 224 { 225 struct bpf_timer *arr_timer; 226 int array_key = 0; 227 228 arr_timer = bpf_map_lookup_elem(&array, &array_key); 229 if (!arr_timer) 230 return 0; 231 232 bpf_timer_init(arr_timer, &array, 1); 233 bpf_timer_set_callback(arr_timer, timer_cb2); 234 bpf_timer_start(arr_timer, 0, 0); 235 subprog1(&array_key); 236 return 0; 237 } 238 239 SEC("fentry/bpf_fentry_test9") 240 __description("Private stack, async callback, potential nesting") 241 __success __retval(0) 242 __arch_x86_64 243 __jited(" subq $0x100, %rsp") 244 int private_stack_async_callback_2(void) 245 { 246 struct bpf_timer *arr_timer; 247 int array_key = 0; 248 249 arr_timer = bpf_map_lookup_elem(&array, &array_key); 250 if (!arr_timer) 251 return 0; 252 253 bpf_timer_init(arr_timer, &array, 1); 254 bpf_timer_set_callback(arr_timer, timer_cb1); 255 bpf_timer_start(arr_timer, 0, 0); 256 subprog1(&array_key); 257 return 0; 258 } 259 260 #else 261 262 SEC("kprobe") 263 __description("private stack is not supported, use a dummy test") 264 __success 265 int dummy_test(void) 266 { 267 return 0; 268 } 269 270 #endif 271 272 char _license[] SEC("license") = "GPL"; 273