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 | int32_t real_tgid = (int32_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 | |