1 #include "vmlinux.h" 2 #include <bpf/bpf_helpers.h> 3 #include <bpf/bpf_core_read.h> 4 5 const char LICENSE[] SEC("license") = "GPL"; 6 7 struct { 8 __uint(type, BPF_MAP_TYPE_ARRAY); 9 __uint(max_entries, 1); 10 __type(key, __u32); 11 __type(value, __u64); 12 } array SEC(".maps"); 13 14 __noinline int sub1(int x) 15 { 16 int key = 0; 17 18 bpf_map_lookup_elem(&array, &key); 19 return x + 1; 20 } 21 22 static __noinline int sub5(int v); 23 24 __noinline int sub2(int y) 25 { 26 return sub5(y + 2); 27 } 28 29 static __noinline int sub3(int z) 30 { 31 return z + 3 + sub1(4); 32 } 33 34 static __noinline int sub4(int w) 35 { 36 int key = 0; 37 38 bpf_map_lookup_elem(&array, &key); 39 return w + sub3(5) + sub1(6); 40 } 41 42 /* sub5() is an identitify function, just to test weirder functions layout and 43 * call patterns 44 */ 45 static __noinline int sub5(int v) 46 { 47 return sub1(v) - 1; /* compensates sub1()'s + 1 */ 48 } 49 50 /* unfortunately verifier rejects `struct task_struct *t` as an unknown pointer 51 * type, so we need to accept pointer as integer and then cast it inside the 52 * function 53 */ 54 __noinline int get_task_tgid(uintptr_t t) 55 { 56 /* this ensures that CO-RE relocs work in multi-subprogs .text */ 57 return BPF_CORE_READ((struct task_struct *)(void *)t, tgid); 58 } 59 60 int res1 = 0; 61 int res2 = 0; 62 int res3 = 0; 63 int res4 = 0; 64 65 SEC("raw_tp/sys_enter") 66 int prog1(void *ctx) 67 { 68 /* perform some CO-RE relocations to ensure they work with multi-prog 69 * sections correctly 70 */ 71 struct task_struct *t = (void *)bpf_get_current_task(); 72 73 if (!BPF_CORE_READ(t, pid) || !get_task_tgid((uintptr_t)t)) 74 return 1; 75 76 res1 = sub1(1) + sub3(2); /* (1 + 1) + (2 + 3 + (4 + 1)) = 12 */ 77 return 0; 78 } 79 80 SEC("raw_tp/sys_exit") 81 int prog2(void *ctx) 82 { 83 struct task_struct *t = (void *)bpf_get_current_task(); 84 85 if (!BPF_CORE_READ(t, pid) || !get_task_tgid((uintptr_t)t)) 86 return 1; 87 88 res2 = sub2(3) + sub3(4); /* (3 + 2) + (4 + 3 + (4 + 1)) = 17 */ 89 return 0; 90 } 91 92 static int empty_callback(__u32 index, void *data) 93 { 94 return 0; 95 } 96 97 /* prog3 has the same section name as prog1 */ 98 SEC("raw_tp/sys_enter") 99 int prog3(void *ctx) 100 { 101 struct task_struct *t = (void *)bpf_get_current_task(); 102 103 if (!BPF_CORE_READ(t, pid) || !get_task_tgid((uintptr_t)t)) 104 return 1; 105 106 /* test that ld_imm64 with BPF_PSEUDO_FUNC doesn't get blinded */ 107 bpf_loop(1, empty_callback, NULL, 0); 108 109 res3 = sub3(5) + 6; /* (5 + 3 + (4 + 1)) + 6 = 19 */ 110 return 0; 111 } 112 113 /* prog4 has the same section name as prog2 */ 114 SEC("raw_tp/sys_exit") 115 int prog4(void *ctx) 116 { 117 struct task_struct *t = (void *)bpf_get_current_task(); 118 119 if (!BPF_CORE_READ(t, pid) || !get_task_tgid((uintptr_t)t)) 120 return 1; 121 122 res4 = sub4(7) + sub1(8); /* (7 + (5 + 3 + (4 + 1)) + (6 + 1)) + (8 + 1) = 36 */ 123 return 0; 124 } 125