-
Notifications
You must be signed in to change notification settings - Fork 245
/
Copy pathexec-trace.bpf.c
133 lines (102 loc) · 3.3 KB
/
exec-trace.bpf.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#include <vmlinux.h>
#include <bpf/bpf_tracing.h>
#include "tracing.bpf.h"
#define BASH_PATH "/bin/bash"
#define EXE_LENGTH 64
struct exec_span_t {
struct span_base_t span_base;
char exe[64];
};
struct {
__uint(type, BPF_MAP_TYPE_LRU_HASH);
__uint(max_entries, 1024 * 10);
__type(key, u32);
__type(value, struct exec_span_t);
} traced_tgids SEC(".maps");
struct {
__uint(type, BPF_MAP_TYPE_RINGBUF);
__uint(max_entries, 256 * 1024);
} exec_spans SEC(".maps");
// Clang 14 in Ubuntu 22.04 does not inline __builtin_memcmp, so we have to reimplement it.
static inline int memcmp_fallback(const void *str1, const void *str2, size_t count)
{
const unsigned char *s1 = (const unsigned char *) str1;
const unsigned char *s2 = (const unsigned char *) str2;
while (count-- > 0) {
if (*s1++ != *s2++)
return s1[-1] < s2[-1] ? -1 : 1;
}
return 0;
}
SEC("tp_btf/sched_process_exec")
int BPF_PROG(sched_process_exec, struct task_struct *p, pid_t old_pid, struct linux_binprm *bprm)
{
u64 ts = bpf_ktime_get_ns();
u64 tgid = p->tgid, ptgid = p->real_parent->tgid;
struct exec_span_t *parent;
struct exec_span_t span = { 0 };
bool start;
if (!bprm) {
return 0;
}
if (bpf_probe_read_kernel_str(span.exe, sizeof(span.exe), bprm->filename) < 0) {
return 0;
}
parent = bpf_map_lookup_elem(&traced_tgids, &ptgid);
start = memcmp_fallback(span.exe, BASH_PATH, sizeof(BASH_PATH)) == 0;
if (parent) {
span.span_base.parent.trace_id_hi = parent->span_base.parent.trace_id_hi;
span.span_base.parent.trace_id_lo = parent->span_base.parent.trace_id_lo;
span.span_base.parent.span_id = parent->span_base.span_id;
span.span_base.span_id = ts;
} else if (start) {
span.span_base.parent.trace_id_lo = ts;
span.span_base.span_id = ts;
} else {
return 0;
}
span.span_base.span_monotonic_timestamp_ns = ts;
bpf_map_update_elem(&traced_tgids, &tgid, &span, BPF_ANY);
return 0;
}
SEC("tp_btf/sched_process_fork")
int BPF_PROG(sched_process_fork, struct task_struct *parent, struct task_struct *child)
{
u64 ts = bpf_ktime_get_ns();
u64 parent_tgid = parent->tgid, child_tgid = child->tgid;
struct exec_span_t *span, fork;
if (parent_tgid == child_tgid) {
return 0;
}
span = bpf_map_lookup_elem(&traced_tgids, &parent_tgid);
if (!span) {
return 0;
}
fork = *span;
fork.span_base.parent.span_id = fork.span_base.span_id;
fork.span_base.span_id = ts;
bpf_map_update_elem(&traced_tgids, &child_tgid, &fork, BPF_ANY);
return 0;
}
SEC("tp_btf/sched_process_exit")
int BPF_PROG(sched_process_exit, struct task_struct *p)
{
u64 ts = bpf_ktime_get_ns();
u64 tgid = p->tgid;
struct exec_span_t *span = bpf_map_lookup_elem(&traced_tgids, &tgid);
struct exec_span_t *submit;
if (!span) {
return 0;
}
span->span_base.span_duration_ns = ts - span->span_base.span_monotonic_timestamp_ns;
submit = bpf_ringbuf_reserve(&exec_spans, sizeof(struct exec_span_t), 0);
if (!submit) {
goto exit;
}
*submit = *span;
bpf_ringbuf_submit(submit, 0);
exit:
bpf_map_delete_elem(&traced_tgids, &tgid);
return 0;
}
char LICENSE[] SEC("license") = "GPL";