1 // SPDX-License-Identifier: GPL-2.0 2 // Copyright (c) 2019 Facebook 3 4 #include <linux/bpf.h> 5 #include <stdint.h> 6 #include <stdbool.h> 7 #include <bpf/bpf_helpers.h> 8 #include <bpf/bpf_core_read.h> 9 10 char _license[] SEC("license") = "GPL"; 11 12 struct { 13 char in[256]; 14 char out[256]; 15 bool skip; 16 uint64_t my_pid_tgid; 17 } data = {}; 18 19 struct core_reloc_kernel_output { 20 int valid[10]; 21 /* we have test_progs[-flavor], so cut flavor part */ 22 char comm[sizeof("test_progs")]; 23 int comm_len; 24 bool local_task_struct_matches; 25 }; 26 27 struct task_struct { 28 int pid; 29 int tgid; 30 char comm[16]; 31 struct task_struct *group_leader; 32 }; 33 34 struct mm_struct___wrong { 35 int abc_whatever_should_not_exist; 36 }; 37 38 struct task_struct___local { 39 int pid; 40 struct mm_struct___wrong *mm; 41 }; 42 43 #define CORE_READ(dst, src) bpf_core_read(dst, sizeof(*(dst)), src) 44 45 SEC("raw_tracepoint/sys_enter") 46 int test_core_kernel(void *ctx) 47 { 48 /* Support for the BPF_TYPE_MATCHES argument to the 49 * __builtin_preserve_type_info builtin was added at some point during 50 * development of clang 15 and it's what we require for this test. 51 */ 52 #if __has_builtin(__builtin_preserve_type_info) && __clang_major__ >= 15 53 struct task_struct *task = (void *)bpf_get_current_task(); 54 struct core_reloc_kernel_output *out = (void *)&data.out; 55 uint64_t pid_tgid = bpf_get_current_pid_tgid(); 56 uint32_t real_tgid = (uint32_t)pid_tgid; 57 int pid, tgid; 58 59 if (data.my_pid_tgid != pid_tgid) 60 return 0; 61 62 if (CORE_READ(&pid, &task->pid) || 63 CORE_READ(&tgid, &task->tgid)) 64 return 1; 65 66 /* validate pid + tgid matches */ 67 out->valid[0] = (((uint64_t)pid << 32) | tgid) == pid_tgid; 68 69 /* test variadic BPF_CORE_READ macros */ 70 out->valid[1] = BPF_CORE_READ(task, 71 tgid) == real_tgid; 72 out->valid[2] = BPF_CORE_READ(task, 73 group_leader, 74 tgid) == real_tgid; 75 out->valid[3] = BPF_CORE_READ(task, 76 group_leader, group_leader, 77 tgid) == real_tgid; 78 out->valid[4] = BPF_CORE_READ(task, 79 group_leader, group_leader, group_leader, 80 tgid) == real_tgid; 81 out->valid[5] = BPF_CORE_READ(task, 82 group_leader, group_leader, group_leader, 83 group_leader, 84 tgid) == real_tgid; 85 out->valid[6] = BPF_CORE_READ(task, 86 group_leader, group_leader, group_leader, 87 group_leader, group_leader, 88 tgid) == real_tgid; 89 out->valid[7] = BPF_CORE_READ(task, 90 group_leader, group_leader, group_leader, 91 group_leader, group_leader, group_leader, 92 tgid) == real_tgid; 93 out->valid[8] = BPF_CORE_READ(task, 94 group_leader, group_leader, group_leader, 95 group_leader, group_leader, group_leader, 96 group_leader, 97 tgid) == real_tgid; 98 out->valid[9] = BPF_CORE_READ(task, 99 group_leader, group_leader, group_leader, 100 group_leader, group_leader, group_leader, 101 group_leader, group_leader, 102 tgid) == real_tgid; 103 104 /* test BPF_CORE_READ_STR_INTO() returns correct code and contents */ 105 out->comm_len = BPF_CORE_READ_STR_INTO( 106 &out->comm, task, 107 group_leader, group_leader, group_leader, group_leader, 108 group_leader, group_leader, group_leader, group_leader, 109 comm); 110 111 out->local_task_struct_matches = bpf_core_type_matches(struct task_struct___local); 112 #else 113 data.skip = true; 114 #endif 115 return 0; 116 } 117 118