@@ -182,6 +182,111 @@ def module_load() -> str:
182182"""
183183
184184
185+ def execve () -> str :
186+ """Trace all execve syscalls (process execution)."""
187+ return """
188+ #include <uapi/linux/ptrace.h>
189+ #include <linux/sched.h>
190+
191+ #define TASK_COMM_LEN 16
192+ #define PAYLOAD_LEN 256
193+
194+ struct event_t {
195+ u64 ts;
196+ u32 pid;
197+ char comm[TASK_COMM_LEN];
198+ char payload[PAYLOAD_LEN];
199+ };
200+
201+ BPF_PERF_OUTPUT(events);
202+
203+ TRACEPOINT_PROBE(syscalls, sys_enter_execve) {
204+ struct event_t ev = {};
205+ ev.ts = bpf_ktime_get_ns();
206+ ev.pid = bpf_get_current_pid_tgid() >> 32;
207+ bpf_get_current_comm(&ev.comm, sizeof(ev.comm));
208+ bpf_probe_read_user_str(ev.payload, sizeof(ev.payload), args->filename);
209+ events.perf_submit(args, &ev, sizeof(ev));
210+ return 0;
211+ }
212+ """
213+
214+
215+ def ptrace () -> str :
216+ """Trace ptrace calls via security_ptrace_access_check (process injection / debugging)."""
217+ return """
218+ #include <uapi/linux/ptrace.h>
219+ #include <linux/sched.h>
220+
221+ #define TASK_COMM_LEN 16
222+ #define PAYLOAD_LEN 256
223+
224+ struct event_t {
225+ u64 ts;
226+ u32 pid;
227+ char comm[TASK_COMM_LEN];
228+ char payload[PAYLOAD_LEN];
229+ };
230+
231+ BPF_PERF_OUTPUT(events);
232+
233+ int kprobe__security_ptrace_access_check(struct pt_regs *ctx, struct task_struct *child, unsigned int mode) {
234+ struct event_t ev = {};
235+ ev.ts = bpf_ktime_get_ns();
236+ ev.pid = bpf_get_current_pid_tgid() >> 32;
237+ bpf_get_current_comm(&ev.comm, sizeof(ev.comm));
238+ bpf_probe_read_kernel_str(ev.payload, sizeof(ev.payload), child->comm);
239+ events.perf_submit(ctx, &ev, sizeof(ev));
240+ return 0;
241+ }
242+ """
243+
244+
245+ def sensitive_file_open (path : str ) -> str :
246+ """Trace opens of a specific absolute file path (e.g. /etc/shadow).
247+
248+ Uses compile-time unrolled byte comparison — no BPF loops, works on all kernel versions.
249+ """
250+ if not path .startswith ("/" ):
251+ raise ValueError (f"path must be absolute: { path !r} " )
252+ path_bytes = path .encode ("utf-8" )
253+ if len (path_bytes ) > 255 :
254+ raise ValueError (f"path too long (max 255 bytes): { path !r} " )
255+ comparisons = " ||\n " .join (
256+ f"fname[{ i } ] != { b } " for i , b in enumerate (path_bytes )
257+ ) + f" ||\n fname[{ len (path_bytes )} ] != 0"
258+ return f"""
259+ #include <uapi/linux/ptrace.h>
260+ #include <linux/sched.h>
261+
262+ #define TASK_COMM_LEN 16
263+ #define PAYLOAD_LEN 256
264+
265+ struct event_t {{
266+ u64 ts;
267+ u32 pid;
268+ char comm[TASK_COMM_LEN];
269+ char payload[PAYLOAD_LEN];
270+ }};
271+
272+ BPF_PERF_OUTPUT(events);
273+
274+ TRACEPOINT_PROBE(syscalls, sys_enter_openat) {{
275+ char fname[PAYLOAD_LEN];
276+ bpf_probe_read_user_str(fname, sizeof(fname), args->filename);
277+ if ({ comparisons } ) return 0;
278+
279+ struct event_t ev = {{}};
280+ ev.ts = bpf_ktime_get_ns();
281+ ev.pid = bpf_get_current_pid_tgid() >> 32;
282+ bpf_get_current_comm(&ev.comm, sizeof(ev.comm));
283+ __builtin_memcpy(ev.payload, fname, sizeof(ev.payload));
284+ events.perf_submit(args, &ev, sizeof(ev));
285+ return 0;
286+ }}
287+ """
288+
289+
185290def ip_host (addr : str ) -> str :
186291 """Trace TCP connections to or from the given IPv4 address (dotted decimal)."""
187292 octets = [int (o ) for o in addr .split ("." )]
0 commit comments