1 /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
2 /* Copyright (c) 2021 Hengqi Chen */
3 #include <vmlinux.h>
4 #include <bpf/bpf_helpers.h>
5 #include <bpf/bpf_core_read.h>
6 #include "exitsnoop.h"
7
8 const volatile bool filter_cg = false;
9 const volatile pid_t target_pid = 0;
10 const volatile bool trace_failed_only = false;
11 const volatile bool trace_by_process = true;
12
13 struct {
14 __uint(type, BPF_MAP_TYPE_CGROUP_ARRAY);
15 __type(key, u32);
16 __type(value, u32);
17 __uint(max_entries, 1);
18 } cgroup_map SEC(".maps");
19
20 struct {
21 __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
22 __uint(key_size, sizeof(__u32));
23 __uint(value_size, sizeof(__u32));
24 } events SEC(".maps");
25
26 SEC("tracepoint/sched/sched_process_exit")
sched_process_exit(void * ctx)27 int sched_process_exit(void *ctx)
28 {
29 __u64 pid_tgid = bpf_get_current_pid_tgid();
30 __u32 pid = pid_tgid >> 32;
31 __u32 tid = (__u32)pid_tgid;
32 int exit_code;
33 struct task_struct *task;
34 struct event event = {};
35
36 if (filter_cg && !bpf_current_task_under_cgroup(&cgroup_map, 0))
37 return 0;
38
39 if (target_pid && target_pid != pid)
40 return 0;
41
42 if (trace_by_process && pid != tid)
43 return 0;
44
45 task = (struct task_struct *)bpf_get_current_task();
46 exit_code = BPF_CORE_READ(task, exit_code);
47 if (trace_failed_only && exit_code == 0)
48 return 0;
49
50 event.start_time = BPF_CORE_READ(task, start_time);
51 event.exit_time = bpf_ktime_get_ns();
52 event.pid = pid;
53 event.tid = tid;
54 event.ppid = BPF_CORE_READ(task, real_parent, tgid);
55 event.sig = exit_code & 0xff;
56 event.exit_code = exit_code >> 8;
57 bpf_get_current_comm(event.comm, sizeof(event.comm));
58 bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, &event, sizeof(event));
59 return 0;
60 }
61
62 char LICENSE[] SEC("license") = "Dual BSD/GPL";
63