1 // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
2 /* Copyright (c) 2021~2022 Hengqi Chen */
3 #include <vmlinux.h>
4 #include <bpf/bpf_helpers.h>
5 #include "sigsnoop.h"
6
7 #define MAX_ENTRIES 10240
8
9 const volatile pid_t filtered_pid = 0;
10 const volatile int target_signal = 0;
11 const volatile bool failed_only = false;
12
13 struct {
14 __uint(type, BPF_MAP_TYPE_HASH);
15 __uint(max_entries, MAX_ENTRIES);
16 __type(key, __u32);
17 __type(value, struct event);
18 } values 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
probe_entry(pid_t tpid,int sig)26 static int probe_entry(pid_t tpid, int sig)
27 {
28 struct event event = {};
29 __u64 pid_tgid;
30 __u32 pid, tid;
31
32 if (target_signal && sig != target_signal)
33 return 0;
34
35 pid_tgid = bpf_get_current_pid_tgid();
36 pid = pid_tgid >> 32;
37 tid = (__u32)pid_tgid;
38 if (filtered_pid && pid != filtered_pid)
39 return 0;
40
41 event.pid = pid;
42 event.tpid = tpid;
43 event.sig = sig;
44 bpf_get_current_comm(event.comm, sizeof(event.comm));
45 bpf_map_update_elem(&values, &tid, &event, BPF_ANY);
46 return 0;
47 }
48
probe_exit(void * ctx,int ret)49 static int probe_exit(void *ctx, int ret)
50 {
51 __u64 pid_tgid = bpf_get_current_pid_tgid();
52 __u32 tid = (__u32)pid_tgid;
53 struct event *eventp;
54
55 eventp = bpf_map_lookup_elem(&values, &tid);
56 if (!eventp)
57 return 0;
58
59 if (failed_only && ret >= 0)
60 goto cleanup;
61
62 eventp->ret = ret;
63 bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, eventp, sizeof(*eventp));
64
65 cleanup:
66 bpf_map_delete_elem(&values, &tid);
67 return 0;
68 }
69
70 SEC("tracepoint/syscalls/sys_enter_kill")
kill_entry(struct trace_event_raw_sys_enter * ctx)71 int kill_entry(struct trace_event_raw_sys_enter *ctx)
72 {
73 pid_t tpid = (pid_t)ctx->args[0];
74 int sig = (int)ctx->args[1];
75
76 return probe_entry(tpid, sig);
77 }
78
79 SEC("tracepoint/syscalls/sys_exit_kill")
kill_exit(struct trace_event_raw_sys_exit * ctx)80 int kill_exit(struct trace_event_raw_sys_exit *ctx)
81 {
82 return probe_exit(ctx, ctx->ret);
83 }
84
85 SEC("tracepoint/syscalls/sys_enter_tkill")
tkill_entry(struct trace_event_raw_sys_enter * ctx)86 int tkill_entry(struct trace_event_raw_sys_enter *ctx)
87 {
88 pid_t tpid = (pid_t)ctx->args[0];
89 int sig = (int)ctx->args[1];
90
91 return probe_entry(tpid, sig);
92 }
93
94 SEC("tracepoint/syscalls/sys_exit_tkill")
tkill_exit(struct trace_event_raw_sys_exit * ctx)95 int tkill_exit(struct trace_event_raw_sys_exit *ctx)
96 {
97 return probe_exit(ctx, ctx->ret);
98 }
99
100 SEC("tracepoint/syscalls/sys_enter_tgkill")
tgkill_entry(struct trace_event_raw_sys_enter * ctx)101 int tgkill_entry(struct trace_event_raw_sys_enter *ctx)
102 {
103 pid_t tpid = (pid_t)ctx->args[1];
104 int sig = (int)ctx->args[2];
105
106 return probe_entry(tpid, sig);
107 }
108
109 SEC("tracepoint/syscalls/sys_exit_tgkill")
tgkill_exit(struct trace_event_raw_sys_exit * ctx)110 int tgkill_exit(struct trace_event_raw_sys_exit *ctx)
111 {
112 return probe_exit(ctx, ctx->ret);
113 }
114
115 SEC("tracepoint/signal/signal_generate")
sig_trace(struct trace_event_raw_signal_generate * ctx)116 int sig_trace(struct trace_event_raw_signal_generate *ctx)
117 {
118 struct event event = {};
119 pid_t tpid = ctx->pid;
120 int ret = ctx->errno;
121 int sig = ctx->sig;
122 __u64 pid_tgid;
123 __u32 pid;
124
125 if (failed_only && ret == 0)
126 return 0;
127
128 if (target_signal && sig != target_signal)
129 return 0;
130
131 pid_tgid = bpf_get_current_pid_tgid();
132 pid = pid_tgid >> 32;
133 if (filtered_pid && pid != filtered_pid)
134 return 0;
135
136 event.pid = pid;
137 event.tpid = tpid;
138 event.sig = sig;
139 event.ret = ret;
140 bpf_get_current_comm(event.comm, sizeof(event.comm));
141 bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, &event, sizeof(event));
142 return 0;
143 }
144
145 char LICENSE[] SEC("license") = "Dual BSD/GPL";
146