this repo has no description
1#include "vmlinux.h"
2#include "uring.h"
3#include <bpf/bpf_helpers.h>
4#include <bpf/bpf_tracing.h>
5#include <bpf/bpf_core_read.h>
6
7char LICENSE[] SEC("license") = "Dual BSD/GPL";
8
9const volatile int pid_target = 0;
10const volatile int cgroup_target = 0;
11
12struct {
13 __uint(type, BPF_MAP_TYPE_RINGBUF);
14 __uint(max_entries, 256 * 1024);
15} rb SEC(".maps");
16
17#define FILE_NAME_LEN 256
18
19#define OPEN_KIND 0
20#define OPENAT_KIND 1
21#define OPENAT2_KIND 2
22#define URING_KIND 3
23
24// An open event
25struct open_event
26{
27 uint32_t e_pid;
28 uint64_t e_cgid;
29 char e_comm[TASK_COMM_LEN];
30 int e_kind;
31 int e_flags;
32 uint32_t e_mode;
33 char e_filename[FILE_NAME_LEN];
34 int e_ret;
35};
36
37// Temporary memory between the syscall event and the exit
38// of the event.
39struct {
40 __uint(type, BPF_MAP_TYPE_HASH);
41 __uint(max_entries, 10240);
42 __type(key, u32); // PID/User Data
43 __type(value, struct open_event); // The event
44} tmpmap SEC(".maps");
45
46SEC("tracepoint/syscalls/sys_enter_openat")
47int tracepoint__syscalls__sys_enter_openat(struct trace_event_raw_sys_enter* ctx)
48{
49 u64 id = bpf_get_current_pid_tgid();
50 u32 pid = id >> 32;
51
52 if (pid_target && pid_target != pid)
53 return false;
54
55 struct open_event oet = {0};
56 oet.e_flags = (int)ctx->args[2];
57 oet.e_mode = (__u32)ctx->args[3];
58 bpf_probe_read(oet.e_filename, FILE_NAME_LEN, (char *) ctx->args[1]);
59 bpf_map_update_elem(&tmpmap, &pid, &oet, BPF_NOEXIST);
60
61 return 0;
62}
63
64SEC("tracepoint/syscalls/sys_enter_openat2")
65int tracepoint__syscalls__sys_enter_openat2(struct trace_event_raw_sys_enter* ctx)
66{
67 u64 id = bpf_get_current_pid_tgid();
68 u32 pid = id >> 32;
69
70 if (pid_target && pid_target != pid)
71 return false;
72
73 struct open_event oet = {0};
74 struct open_how how = {0};
75 bpf_probe_read_user(&how, sizeof(how), (void *)ctx->args[2]);
76 oet.e_flags = (int)how.flags;
77 oet.e_mode = (__u32)how.mode;
78 bpf_probe_read(oet.e_filename, FILE_NAME_LEN, (char *) ctx->args[1]);
79
80 // Add it to the hash map
81 bpf_map_update_elem(&tmpmap, &pid, &oet, BPF_NOEXIST);
82 return 0;
83}
84
85SEC("tracepoint/syscalls/sys_enter_open")
86int tracepoint__syscalls__sys_enter_open(struct trace_event_raw_sys_enter* ctx)
87{
88 u64 id = bpf_get_current_pid_tgid();
89 u32 pid = id >> 32;
90
91 if (pid_target && pid_target != pid)
92 return false;
93
94 struct open_event oet = {0};
95 oet.e_flags = (int)ctx->args[2];
96 oet.e_mode = (__u32)ctx->args[3];
97 bpf_probe_read(oet.e_filename, FILE_NAME_LEN, (char *) ctx->args[1]);
98
99 // Add it to the hash map
100 bpf_map_update_elem(&tmpmap, &pid, &oet, BPF_NOEXIST);
101
102 return 0;
103}
104
105
106SEC("tracepoint/syscalls/sys_exit_openat")
107int tracepoint__syscalls__sys_exit_openat(struct syscall_trace_exit* ctx)
108{
109 struct open_event *ev;
110 u64 id = bpf_get_current_pid_tgid();
111 u32 pid = id >> 32;
112
113 struct open_event *oet;
114 oet = bpf_ringbuf_reserve(&rb, sizeof(struct open_event), 0);
115 if (!oet)
116 return 0;
117
118 // Find our event
119 ev = bpf_map_lookup_elem(&tmpmap, &pid);
120 if (!ev) {
121 // Tidy up
122 bpf_ringbuf_discard(oet, 0);
123 bpf_map_delete_elem(&tmpmap, &pid);
124 return 0;
125 }
126
127 oet->e_ret = ctx->ret;
128 oet->e_cgid = bpf_get_current_cgroup_id();
129 bpf_probe_read_str(&oet->e_filename, sizeof(oet->e_filename), ev->e_filename);
130 bpf_get_current_comm(oet->e_comm, TASK_COMM_LEN);
131 oet->e_flags = ev->e_flags;
132 oet->e_pid = pid;
133 oet->e_mode = ev->e_mode;
134 oet->e_kind = OPENAT_KIND;
135
136 // Tidy up
137 bpf_map_delete_elem(&tmpmap, &pid);
138
139 /* emit event */
140 bpf_ringbuf_submit(oet, 0);
141
142 return 0;
143}
144
145SEC("tracepoint/syscalls/sys_exit_openat2")
146int tracepoint__syscalls__sys_exit_openat2(struct syscall_trace_exit* ctx)
147{
148 struct open_event *ev;
149 u64 id = bpf_get_current_pid_tgid();
150 u32 pid = id >> 32;
151
152 struct open_event *oet;
153 oet = bpf_ringbuf_reserve(&rb, sizeof(struct open_event), 0);
154 if (!oet)
155 return 0;
156
157 // Find our event
158 ev = bpf_map_lookup_elem(&tmpmap, &pid);
159 if (!ev) {
160 // Tidy up
161 bpf_ringbuf_discard(oet, 0);
162 bpf_map_delete_elem(&tmpmap, &pid);
163 return 0;
164 }
165
166 oet->e_ret = ctx->ret;
167 oet->e_cgid = bpf_get_current_cgroup_id();
168 bpf_probe_read_str(&oet->e_filename, sizeof(oet->e_filename), ev->e_filename);
169 bpf_get_current_comm(oet->e_comm, TASK_COMM_LEN);
170 oet->e_flags = ev->e_flags;
171 oet->e_pid = pid;
172 oet->e_mode = ev->e_mode;
173 oet->e_kind = OPENAT2_KIND;
174
175 // Tidy up
176 bpf_map_delete_elem(&tmpmap, &pid);
177
178 /* emit event */
179 bpf_ringbuf_submit(oet, 0);
180
181 return 0;
182}
183
184/* IO_URING is not so clean :S */
185SEC("kprobe/io_openat2")
186int BPF_KPROBE(trace_io_uring_openat_entry, struct io_kiocb *req, int issue_flags)
187{
188 struct io_open open;
189 int res = bpf_probe_read(&open, sizeof(open), req);
190 if (res != 0) {
191 static const char fmt[] = "openat read failed %i\n";
192 bpf_trace_printk(fmt, sizeof(fmt), res);
193 return 0;
194 }
195 struct task_struct *task = (struct task_struct *)bpf_get_current_task_btf();
196 char commit[TASK_COMM_LEN];
197
198 bpf_get_current_comm(&commit, TASK_COMM_LEN);
199
200 u64 pid_tgid = bpf_get_current_pid_tgid();
201
202 struct open_event oet = {0};
203 struct open_how how = {0};
204 bpf_probe_read_user(&how, sizeof(how), (void *)&open.how);
205 oet.e_flags = (int)open.how.flags;
206 oet.e_mode = (__u32)open.how.mode;
207 oet.e_filename[0] = '\0';
208
209 bpf_map_update_elem(&tmpmap, &pid_tgid, &oet, BPF_ANY);
210 return 0;
211}
212
213// Return probe
214SEC("kretprobe/io_openat2")
215int BPF_KRETPROBE(trace_io_uring_openat_ret)
216{
217 u64 pid_tgid = bpf_get_current_pid_tgid();
218
219 struct open_event *ev = bpf_map_lookup_elem(&tmpmap, &pid_tgid);
220 if (!ev) {
221 static const char fmt[] = "no event\n";
222 bpf_trace_printk(fmt, sizeof(fmt));
223 return 0;
224 }
225
226 struct open_event *oet = bpf_ringbuf_reserve(&rb, sizeof(struct open_event), 0);
227 if (!oet)
228 return 0;
229
230 bpf_get_current_comm(oet->e_comm, TASK_COMM_LEN);
231 static const char fmt[] = "opening %s\n";
232 bpf_trace_printk(fmt, sizeof(fmt), ev->e_filename);
233
234 oet->e_ret = 0; // TODO: PT_REGS_RC(ctx);
235 oet->e_cgid = bpf_get_current_cgroup_id();
236 bpf_probe_read_str(&oet->e_filename, sizeof(oet->e_filename), ev->e_filename);
237 oet->e_flags = ev->e_flags;
238 oet->e_mode = ev->e_mode;
239 oet->e_kind = URING_KIND;
240 oet->e_pid = pid_tgid >> 32;
241
242 bpf_ringbuf_submit(oet, 0);
243 bpf_map_delete_elem(&tmpmap, &pid_tgid);
244 return 0;
245}