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