Skip to content

Commit 85d4388

Browse files
cosmo0920edsiper
authored andcommitted
in_ebpf: Add exec trace
Signed-off-by: Hiroshi Hatake <hiroshi@chronosphere.io>
1 parent eae3ebf commit 85d4388

6 files changed

Lines changed: 406 additions & 3 deletions

File tree

plugins/in_ebpf/in_ebpf.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ static struct flb_config_map config_map[] = {
262262
{
263263
FLB_CONFIG_MAP_STR, "Trace", NULL,
264264
FLB_CONFIG_MAP_MULT, FLB_FALSE, 0,
265-
"Set the eBPF trace to enable (for example, bind, malloc, signal, vfs, tcp). Can be set multiple times"
265+
"Set the eBPF trace to enable (for example, bind, exec, malloc, signal, vfs, tcp). Can be set multiple times"
266266
},
267267
/* EOF */
268268
{0}

plugins/in_ebpf/traces/exec/bpf.c

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
2+
3+
#include <vmlinux.h>
4+
5+
#define _LINUX_TYPES_H
6+
#define _LINUX_POSIX_TYPES_H
7+
8+
#include <bpf/bpf_helpers.h>
9+
#include <bpf/bpf_core_read.h>
10+
11+
#include <gadget/buffer.h>
12+
#include <gadget/macros.h>
13+
#include <gadget/mntns_filter.h>
14+
#include <gadget/types.h>
15+
16+
#include "common/events.h"
17+
18+
#define MAX_ENTRIES 10240
19+
#define ARGV_MAX_SCAN 20
20+
21+
struct execve_args {
22+
gadget_mntns_id mntns_id;
23+
char filename[PATH_MAX];
24+
char argv[EXECVE_ARG_MAX][EXECVE_ARG_LEN];
25+
char argv_last[EXECVE_ARG_LEN];
26+
__u32 argc;
27+
};
28+
29+
struct {
30+
__uint(type, BPF_MAP_TYPE_HASH);
31+
__uint(max_entries, MAX_ENTRIES);
32+
__type(key, __u32);
33+
__type(value, struct execve_args);
34+
} values SEC(".maps");
35+
36+
struct {
37+
__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
38+
__uint(max_entries, 1);
39+
__type(key, __u32);
40+
__type(value, struct execve_args);
41+
} heap SEC(".maps");
42+
43+
GADGET_TRACER_MAP(events, 1024 * 256);
44+
45+
static __always_inline __u32 get_ppid(void)
46+
{
47+
struct task_struct *task;
48+
49+
task = (struct task_struct *) bpf_get_current_task_btf();
50+
if (!task) {
51+
return 0;
52+
}
53+
54+
return BPF_CORE_READ(task, real_parent, tgid);
55+
}
56+
57+
static __always_inline int submit_exec_event(void *ctx,
58+
struct execve_args *args,
59+
enum execve_stage stage,
60+
int error_raw)
61+
{
62+
__u64 pid_tgid;
63+
__u64 uid_gid;
64+
struct event *event;
65+
66+
event = gadget_reserve_buf(&events, sizeof(*event));
67+
if (!event) {
68+
return -1;
69+
}
70+
71+
pid_tgid = bpf_get_current_pid_tgid();
72+
uid_gid = bpf_get_current_uid_gid();
73+
74+
event->common.timestamp_raw = bpf_ktime_get_boot_ns();
75+
event->common.pid = (__u32) (pid_tgid >> 32);
76+
event->common.tid = (__u32) pid_tgid;
77+
event->common.uid = (__u32) uid_gid;
78+
event->common.gid = (__u32) (uid_gid >> 32);
79+
event->common.mntns_id = args->mntns_id;
80+
bpf_get_current_comm(event->common.comm, sizeof(event->common.comm));
81+
82+
event->type = EVENT_TYPE_EXECVE;
83+
event->details.execve.stage = stage;
84+
event->details.execve.ppid = get_ppid();
85+
event->details.execve.argc = args->argc;
86+
event->details.execve.error_raw = error_raw;
87+
88+
bpf_probe_read_kernel_str(event->details.execve.filename,
89+
sizeof(event->details.execve.filename),
90+
args->filename);
91+
bpf_probe_read_kernel_str(event->details.execve.argv[0],
92+
sizeof(event->details.execve.argv[0]),
93+
args->argv[0]);
94+
bpf_probe_read_kernel_str(event->details.execve.argv[1],
95+
sizeof(event->details.execve.argv[1]),
96+
args->argv[1]);
97+
bpf_probe_read_kernel_str(event->details.execve.argv[2],
98+
sizeof(event->details.execve.argv[2]),
99+
args->argv[2]);
100+
bpf_probe_read_kernel_str(event->details.execve.argv_last,
101+
sizeof(event->details.execve.argv_last),
102+
args->argv_last);
103+
104+
gadget_submit_buf(ctx, &events, event, sizeof(*event));
105+
106+
return 0;
107+
}
108+
109+
SEC("tracepoint/syscalls/sys_enter_execve")
110+
int trace_execve_enter(struct syscall_trace_enter *ctx)
111+
{
112+
__u32 tid;
113+
__u32 i;
114+
__u64 pid_tgid;
115+
__u64 mntns_id;
116+
__u32 zero;
117+
const char *filename;
118+
const char *const *argv;
119+
const char *arg;
120+
struct execve_args *args;
121+
122+
mntns_id = gadget_get_mntns_id();
123+
if (gadget_should_discard_mntns_id(mntns_id)) {
124+
return 0;
125+
}
126+
127+
pid_tgid = bpf_get_current_pid_tgid();
128+
tid = (__u32) pid_tgid;
129+
130+
zero = 0;
131+
args = bpf_map_lookup_elem(&heap, &zero);
132+
if (!args) {
133+
return 0;
134+
}
135+
136+
args->mntns_id = mntns_id;
137+
args->argc = 0;
138+
args->filename[0] = '\0';
139+
args->argv[0][0] = '\0';
140+
args->argv[1][0] = '\0';
141+
args->argv[2][0] = '\0';
142+
args->argv_last[0] = '\0';
143+
144+
filename = (const char *) ctx->args[0];
145+
if (filename) {
146+
bpf_probe_read_user_str(args->filename, sizeof(args->filename), filename);
147+
}
148+
149+
argv = (const char *const *) ctx->args[1];
150+
if (argv) {
151+
#pragma unroll
152+
for (i = 0; i < ARGV_MAX_SCAN; i++) {
153+
arg = NULL;
154+
if (bpf_probe_read_user(&arg, sizeof(arg), &argv[i]) != 0 || arg == NULL) {
155+
break;
156+
}
157+
args->argc++;
158+
bpf_probe_read_user_str(args->argv_last, sizeof(args->argv_last), arg);
159+
160+
if (i == 0) {
161+
bpf_probe_read_user_str(args->argv[0], sizeof(args->argv[0]), arg);
162+
}
163+
else if (i == 1) {
164+
bpf_probe_read_user_str(args->argv[1], sizeof(args->argv[1]), arg);
165+
}
166+
else if (i == 2) {
167+
bpf_probe_read_user_str(args->argv[2], sizeof(args->argv[2]), arg);
168+
}
169+
}
170+
}
171+
172+
bpf_map_update_elem(&values, &tid, args, BPF_ANY);
173+
submit_exec_event(ctx, args, EXECVE_STAGE_ENTER, 0);
174+
175+
return 0;
176+
}
177+
178+
SEC("tracepoint/syscalls/sys_exit_execve")
179+
int trace_execve_exit(struct syscall_trace_exit *ctx)
180+
{
181+
__u32 tid;
182+
struct execve_args *args;
183+
int error_raw;
184+
185+
tid = (__u32) bpf_get_current_pid_tgid();
186+
187+
args = bpf_map_lookup_elem(&values, &tid);
188+
if (!args) {
189+
return 0;
190+
}
191+
192+
error_raw = ctx->ret < 0 ? -ctx->ret : 0;
193+
submit_exec_event(ctx, args, EXECVE_STAGE_EXIT, error_raw);
194+
195+
bpf_map_delete_elem(&values, &tid);
196+
197+
return 0;
198+
}
199+
200+
char LICENSE[] SEC("license") = "Dual BSD/GPL";
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
#include <fluent-bit/flb_input_plugin.h>
2+
#include <fluent-bit/flb_log_event_encoder.h>
3+
4+
#include "common/events.h"
5+
#include "common/event_context.h"
6+
#include "common/encoder.h"
7+
8+
#include "handler.h"
9+
10+
static const char *exec_stage_to_string(enum execve_stage stage)
11+
{
12+
if (stage == EXECVE_STAGE_ENTER) {
13+
return "enter";
14+
}
15+
16+
if (stage == EXECVE_STAGE_EXIT) {
17+
return "exit";
18+
}
19+
20+
return "unknown";
21+
}
22+
23+
int encode_exec_event(struct flb_input_instance *ins,
24+
struct flb_log_event_encoder *log_encoder,
25+
const struct event *ev)
26+
{
27+
const char *stage_name;
28+
int ret;
29+
30+
ret = flb_log_event_encoder_begin_record(log_encoder);
31+
if (ret != FLB_EVENT_ENCODER_SUCCESS) {
32+
return -1;
33+
}
34+
35+
ret = encode_common_fields(log_encoder, ev);
36+
if (ret != FLB_EVENT_ENCODER_SUCCESS) {
37+
flb_log_event_encoder_rollback_record(log_encoder);
38+
return -1;
39+
}
40+
41+
stage_name = exec_stage_to_string(ev->details.execve.stage);
42+
43+
ret = flb_log_event_encoder_append_body_cstring(log_encoder, "stage");
44+
if (ret != FLB_EVENT_ENCODER_SUCCESS) {
45+
flb_log_event_encoder_rollback_record(log_encoder);
46+
return -1;
47+
}
48+
ret = flb_log_event_encoder_append_body_cstring(log_encoder, stage_name);
49+
if (ret != FLB_EVENT_ENCODER_SUCCESS) {
50+
flb_log_event_encoder_rollback_record(log_encoder);
51+
return -1;
52+
}
53+
54+
ret = flb_log_event_encoder_append_body_cstring(log_encoder, "ppid");
55+
if (ret != FLB_EVENT_ENCODER_SUCCESS) {
56+
flb_log_event_encoder_rollback_record(log_encoder);
57+
return -1;
58+
}
59+
ret = flb_log_event_encoder_append_body_uint32(log_encoder, ev->details.execve.ppid);
60+
if (ret != FLB_EVENT_ENCODER_SUCCESS) {
61+
flb_log_event_encoder_rollback_record(log_encoder);
62+
return -1;
63+
}
64+
65+
ret = flb_log_event_encoder_append_body_cstring(log_encoder, "filename");
66+
if (ret != FLB_EVENT_ENCODER_SUCCESS) {
67+
flb_log_event_encoder_rollback_record(log_encoder);
68+
return -1;
69+
}
70+
ret = flb_log_event_encoder_append_body_cstring(log_encoder, ev->details.execve.filename);
71+
if (ret != FLB_EVENT_ENCODER_SUCCESS) {
72+
flb_log_event_encoder_rollback_record(log_encoder);
73+
return -1;
74+
}
75+
76+
ret = flb_log_event_encoder_append_body_cstring(log_encoder, "argv");
77+
if (ret != FLB_EVENT_ENCODER_SUCCESS) {
78+
flb_log_event_encoder_rollback_record(log_encoder);
79+
return -1;
80+
}
81+
ret = flb_log_event_encoder_append_body_cstring(log_encoder, ev->details.execve.argv[0]);
82+
if (ret != FLB_EVENT_ENCODER_SUCCESS) {
83+
flb_log_event_encoder_rollback_record(log_encoder);
84+
return -1;
85+
}
86+
87+
ret = flb_log_event_encoder_append_body_cstring(log_encoder, "argv1");
88+
if (ret != FLB_EVENT_ENCODER_SUCCESS) {
89+
flb_log_event_encoder_rollback_record(log_encoder);
90+
return -1;
91+
}
92+
ret = flb_log_event_encoder_append_body_cstring(log_encoder, ev->details.execve.argv[1]);
93+
if (ret != FLB_EVENT_ENCODER_SUCCESS) {
94+
flb_log_event_encoder_rollback_record(log_encoder);
95+
return -1;
96+
}
97+
98+
ret = flb_log_event_encoder_append_body_cstring(log_encoder, "argv2");
99+
if (ret != FLB_EVENT_ENCODER_SUCCESS) {
100+
flb_log_event_encoder_rollback_record(log_encoder);
101+
return -1;
102+
}
103+
ret = flb_log_event_encoder_append_body_cstring(log_encoder, ev->details.execve.argv[2]);
104+
if (ret != FLB_EVENT_ENCODER_SUCCESS) {
105+
flb_log_event_encoder_rollback_record(log_encoder);
106+
return -1;
107+
}
108+
109+
ret = flb_log_event_encoder_append_body_cstring(log_encoder, "argv_last");
110+
if (ret != FLB_EVENT_ENCODER_SUCCESS) {
111+
flb_log_event_encoder_rollback_record(log_encoder);
112+
return -1;
113+
}
114+
ret = flb_log_event_encoder_append_body_cstring(log_encoder, ev->details.execve.argv_last);
115+
if (ret != FLB_EVENT_ENCODER_SUCCESS) {
116+
flb_log_event_encoder_rollback_record(log_encoder);
117+
return -1;
118+
}
119+
120+
ret = flb_log_event_encoder_append_body_cstring(log_encoder, "argc");
121+
if (ret != FLB_EVENT_ENCODER_SUCCESS) {
122+
flb_log_event_encoder_rollback_record(log_encoder);
123+
return -1;
124+
}
125+
ret = flb_log_event_encoder_append_body_uint32(log_encoder, ev->details.execve.argc);
126+
if (ret != FLB_EVENT_ENCODER_SUCCESS) {
127+
flb_log_event_encoder_rollback_record(log_encoder);
128+
return -1;
129+
}
130+
131+
ret = flb_log_event_encoder_append_body_cstring(log_encoder, "error_raw");
132+
if (ret != FLB_EVENT_ENCODER_SUCCESS) {
133+
flb_log_event_encoder_rollback_record(log_encoder);
134+
return -1;
135+
}
136+
ret = flb_log_event_encoder_append_body_int32(log_encoder, ev->details.execve.error_raw);
137+
if (ret != FLB_EVENT_ENCODER_SUCCESS) {
138+
flb_log_event_encoder_rollback_record(log_encoder);
139+
return -1;
140+
}
141+
142+
ret = flb_log_event_encoder_commit_record(log_encoder);
143+
if (ret != FLB_EVENT_ENCODER_SUCCESS) {
144+
flb_log_event_encoder_rollback_record(log_encoder);
145+
return -1;
146+
}
147+
148+
return 0;
149+
}
150+
151+
int trace_exec_handler(void *ctx, void *data, size_t data_sz)
152+
{
153+
struct trace_event_context *event_ctx = (struct trace_event_context *) ctx;
154+
struct event *ev = (struct event *) data;
155+
struct flb_log_event_encoder *encoder = event_ctx->log_encoder;
156+
int ret;
157+
158+
if (data_sz < sizeof(struct event) || ev->type != EVENT_TYPE_EXECVE) {
159+
return -1;
160+
}
161+
162+
ret = encode_exec_event(event_ctx->ins, encoder, ev);
163+
if (ret != 0) {
164+
return -1;
165+
}
166+
167+
ret = flb_input_log_append(event_ctx->ins, NULL, 0,
168+
encoder->output_buffer, encoder->output_length);
169+
flb_log_event_encoder_reset(encoder);
170+
if (ret == -1) {
171+
return -1;
172+
}
173+
174+
return 0;
175+
}

0 commit comments

Comments
 (0)