1 // SPDX-License-Identifier: GPL-2.0 2 #include <linux/bpf.h> 3 #include <bpf/bpf_helpers.h> 4 #include "bpf_misc.h" 5 6 int call_happened = 0; 7 8 /* 9 * 32765 is the exact minimum number of padding instructions needed to 10 * trigger the verifier failure, because: 11 * 1. Counting the wrapper instructions around the padding block (one 12 * "r0=0" and two "exit" instructions), the actual jump distance 13 * evaluates to N + 3. 14 * 2. To overflow the s16 max bound (32767), we need N + 3 > 32767. 15 * Thus, N = 32765 is the exact minimum padding size required. 16 */ padding_subprog(void)17static __attribute__((noinline)) void padding_subprog(void) 18 { 19 asm volatile ( 20 "r0 = 0;" 21 ".rept 32765;" 22 "r0 += 0;" 23 ".endr;" 24 ::: __clobber_all); 25 } 26 target_subprog(void)27static __attribute__((noinline)) int target_subprog(void) 28 { 29 /* Use volatile variable here to prevent optimization. */ 30 volatile int magic_ret = 3; 31 return magic_ret; 32 } 33 34 SEC("syscall") 35 __success __retval(3) call_large_imm_test(void * ctx)36int call_large_imm_test(void *ctx) 37 { 38 /* 39 * Landing pad to handle call error on kernel without the fix, 40 * preventing kernel panic. 41 */ 42 asm volatile ( 43 "r0 = 0;" 44 ".rept 32768;" 45 "r0 += 0;" 46 ".endr;" 47 ::: __clobber_all); 48 49 /* 50 * The call_happened variable is 1 only when the call insn wrongly 51 * go back to the landing pad above. 52 */ 53 if (call_happened == 1) { 54 /* Use volatile variable here to prevent optimization. */ 55 volatile int flag = -1; 56 return flag; 57 } 58 59 call_happened = 1; 60 61 padding_subprog(); 62 63 return target_subprog(); 64 } 65 66 char LICENSE[] SEC("license") = "GPL"; 67