diff --git a/plugins/in_ebpf/in_ebpf.c b/plugins/in_ebpf/in_ebpf.c index 2d08dda03f2..c4371700384 100644 --- a/plugins/in_ebpf/in_ebpf.c +++ b/plugins/in_ebpf/in_ebpf.c @@ -244,7 +244,7 @@ static struct flb_config_map config_map[] = { { FLB_CONFIG_MAP_STR, "Trace", NULL, FLB_CONFIG_MAP_MULT, FLB_FALSE, 0, - "Set the eBPF trace to enable (for example, bind, malloc, signal). Can be set multiple times" + "Set the eBPF trace to enable (for example, bind, malloc, signal, vfs). Can be set multiple times" }, /* EOF */ {0} diff --git a/plugins/in_ebpf/traces/includes/common/encoder.h b/plugins/in_ebpf/traces/includes/common/encoder.h index 7f88ab140a8..ae0c0b33ff0 100644 --- a/plugins/in_ebpf/traces/includes/common/encoder.h +++ b/plugins/in_ebpf/traces/includes/common/encoder.h @@ -17,6 +17,8 @@ static inline char *event_type_to_string(enum event_type type) { return "malloc"; case EVENT_TYPE_BIND: return "bind"; + case EVENT_TYPE_VFS: + return "vfs"; default: return "unknown"; } diff --git a/plugins/in_ebpf/traces/includes/common/events.h b/plugins/in_ebpf/traces/includes/common/events.h index bef34c54ba5..34051c4e0f4 100644 --- a/plugins/in_ebpf/traces/includes/common/events.h +++ b/plugins/in_ebpf/traces/includes/common/events.h @@ -5,12 +5,18 @@ #include // For __u32, __u64, etc. #define TASK_COMM_LEN 16 +#define VFS_PATH_MAX 256 enum event_type { EVENT_TYPE_EXECVE, EVENT_TYPE_SIGNAL, EVENT_TYPE_MEM, // For memory operations EVENT_TYPE_BIND, // Added event type for bind operations + EVENT_TYPE_VFS, +}; + +enum vfs_op { + VFS_OP_OPENAT, }; /* Define memory operation types */ @@ -78,6 +84,15 @@ struct bind_event { int error_raw; // Error code for the bind operation }; +struct vfs_event { + enum vfs_op operation; + char path[VFS_PATH_MAX]; + __u32 flags; + __u32 mode; + int fd; + int error_raw; +}; + /* The main event structure */ struct event { enum event_type type; // Type of event (execve, signal, mem, bind) @@ -87,6 +102,7 @@ struct event { struct signal_event signal; struct mem_event mem; // Memory event details struct bind_event bind; // Bind event details + struct vfs_event vfs; // VFS event details } details; // Event-specific details }; diff --git a/plugins/in_ebpf/traces/traces.h b/plugins/in_ebpf/traces/traces.h index 70342608946..9e5a9a0ae87 100644 --- a/plugins/in_ebpf/traces/traces.h +++ b/plugins/in_ebpf/traces/traces.h @@ -6,10 +6,12 @@ #include "generated/trace_signal.skel.h" #include "generated/trace_malloc.skel.h" #include "generated/trace_bind.skel.h" +#include "generated/trace_vfs.skel.h" #include "bind/handler.h" #include "signal/handler.h" // Include signal handler #include "malloc/handler.h" // Include malloc handler +#include "vfs/handler.h" /* Skeleton function pointer types */ typedef void *(*trace_skel_open_func_t)(void); @@ -58,11 +60,13 @@ struct trace_registration { DEFINE_GET_BPF_OBJECT(trace_signal) DEFINE_GET_BPF_OBJECT(trace_malloc) DEFINE_GET_BPF_OBJECT(trace_bind) +DEFINE_GET_BPF_OBJECT(trace_vfs) static struct trace_registration trace_table[] = { REGISTER_TRACE(trace_signal, trace_signal_handler), REGISTER_TRACE(trace_malloc, trace_malloc_handler), REGISTER_TRACE(trace_bind, trace_bind_handler), + REGISTER_TRACE(trace_vfs, trace_vfs_handler), }; #endif // TRACE_TRACES_H diff --git a/plugins/in_ebpf/traces/vfs/bpf.c b/plugins/in_ebpf/traces/vfs/bpf.c new file mode 100644 index 00000000000..b77212d5f77 --- /dev/null +++ b/plugins/in_ebpf/traces/vfs/bpf.c @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) + +#include + +#define _LINUX_TYPES_H +#define _LINUX_POSIX_TYPES_H + +#include +#include + +#include +#include +#include +#include + +#include "common/events.h" + +#define MAX_ENTRIES 10240 + +struct vfs_open_args { + gadget_mntns_id mntns_id; + __u32 flags; + __u32 mode; + char path[VFS_PATH_MAX]; +}; + +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, MAX_ENTRIES); + __type(key, __u32); + __type(value, struct vfs_open_args); +} values SEC(".maps"); + +GADGET_TRACER_MAP(events, 1024 * 256); + +SEC("tracepoint/syscalls/sys_enter_openat") +int trace_vfs_openat_enter(struct syscall_trace_enter *ctx) +{ + __u32 tid; + __u64 pid_tgid; + __u64 mntns_id; + const char *filename; + struct vfs_open_args val = {}; + + mntns_id = gadget_get_mntns_id(); + if (gadget_should_discard_mntns_id(mntns_id)) { + return 0; + } + + pid_tgid = bpf_get_current_pid_tgid(); + tid = (__u32) pid_tgid; + + filename = (const char *) ctx->args[1]; + bpf_probe_read_user_str(val.path, sizeof(val.path), filename); + + val.flags = (__u32) ctx->args[2]; + val.mode = (__u32) ctx->args[3]; + val.mntns_id = mntns_id; + + bpf_map_update_elem(&values, &tid, &val, BPF_ANY); + + return 0; +} + +SEC("tracepoint/syscalls/sys_exit_openat") +int trace_vfs_openat_exit(struct syscall_trace_exit *ctx) +{ + __u32 tid; + __u64 pid_tgid; + __u64 uid_gid; + struct vfs_open_args *val; + struct event *event; + + pid_tgid = bpf_get_current_pid_tgid(); + tid = (__u32) pid_tgid; + + val = bpf_map_lookup_elem(&values, &tid); + if (!val) { + return 0; + } + + event = gadget_reserve_buf(&events, sizeof(*event)); + if (!event) { + bpf_map_delete_elem(&values, &tid); + return 0; + } + + uid_gid = bpf_get_current_uid_gid(); + + event->common.timestamp_raw = bpf_ktime_get_boot_ns(); + event->common.pid = pid_tgid >> 32; + event->common.tid = tid; + event->common.uid = (u32) uid_gid; + event->common.gid = (u32) (uid_gid >> 32); + event->common.mntns_id = val->mntns_id; + bpf_get_current_comm(event->common.comm, sizeof(event->common.comm)); + + event->type = EVENT_TYPE_VFS; + event->details.vfs.operation = VFS_OP_OPENAT; + event->details.vfs.flags = val->flags; + event->details.vfs.mode = val->mode; + event->details.vfs.fd = (int) ctx->ret; + event->details.vfs.error_raw = ctx->ret < 0 ? -ctx->ret : 0; + + __builtin_memcpy(event->details.vfs.path, val->path, sizeof(event->details.vfs.path)); + + gadget_submit_buf(ctx, &events, event, sizeof(*event)); + + bpf_map_delete_elem(&values, &tid); + + return 0; +} + +char LICENSE[] SEC("license") = "Dual BSD/GPL"; diff --git a/plugins/in_ebpf/traces/vfs/handler.c b/plugins/in_ebpf/traces/vfs/handler.c new file mode 100644 index 00000000000..9a9b6a11d13 --- /dev/null +++ b/plugins/in_ebpf/traces/vfs/handler.c @@ -0,0 +1,126 @@ +#include +#include + +#include "common/events.h" +#include "common/event_context.h" +#include "common/encoder.h" + +#include "handler.h" + +int encode_vfs_event(struct flb_input_instance *ins, + struct flb_log_event_encoder *log_encoder, + const struct event *ev) +{ + int ret; + + ret = flb_log_event_encoder_begin_record(log_encoder); + if (ret != FLB_EVENT_ENCODER_SUCCESS) { + return -1; + } + + ret = encode_common_fields(log_encoder, ev); + if (ret != FLB_EVENT_ENCODER_SUCCESS) { + flb_log_event_encoder_rollback_record(log_encoder); + return -1; + } + + ret = flb_log_event_encoder_append_body_cstring(log_encoder, "operation"); + if (ret != FLB_EVENT_ENCODER_SUCCESS) { + flb_log_event_encoder_rollback_record(log_encoder); + return -1; + } + ret = flb_log_event_encoder_append_body_int32(log_encoder, ev->details.vfs.operation); + if (ret != FLB_EVENT_ENCODER_SUCCESS) { + flb_log_event_encoder_rollback_record(log_encoder); + return -1; + } + + ret = flb_log_event_encoder_append_body_cstring(log_encoder, "path"); + if (ret != FLB_EVENT_ENCODER_SUCCESS) { + flb_log_event_encoder_rollback_record(log_encoder); + return -1; + } + ret = flb_log_event_encoder_append_body_cstring(log_encoder, ev->details.vfs.path); + if (ret != FLB_EVENT_ENCODER_SUCCESS) { + flb_log_event_encoder_rollback_record(log_encoder); + return -1; + } + + ret = flb_log_event_encoder_append_body_cstring(log_encoder, "flags"); + if (ret != FLB_EVENT_ENCODER_SUCCESS) { + flb_log_event_encoder_rollback_record(log_encoder); + return -1; + } + ret = flb_log_event_encoder_append_body_uint32(log_encoder, ev->details.vfs.flags); + if (ret != FLB_EVENT_ENCODER_SUCCESS) { + flb_log_event_encoder_rollback_record(log_encoder); + return -1; + } + + ret = flb_log_event_encoder_append_body_cstring(log_encoder, "mode"); + if (ret != FLB_EVENT_ENCODER_SUCCESS) { + flb_log_event_encoder_rollback_record(log_encoder); + return -1; + } + ret = flb_log_event_encoder_append_body_uint32(log_encoder, ev->details.vfs.mode); + if (ret != FLB_EVENT_ENCODER_SUCCESS) { + flb_log_event_encoder_rollback_record(log_encoder); + return -1; + } + + ret = flb_log_event_encoder_append_body_cstring(log_encoder, "fd"); + if (ret != FLB_EVENT_ENCODER_SUCCESS) { + flb_log_event_encoder_rollback_record(log_encoder); + return -1; + } + ret = flb_log_event_encoder_append_body_int32(log_encoder, ev->details.vfs.fd); + if (ret != FLB_EVENT_ENCODER_SUCCESS) { + flb_log_event_encoder_rollback_record(log_encoder); + return -1; + } + + ret = flb_log_event_encoder_append_body_cstring(log_encoder, "error_raw"); + if (ret != FLB_EVENT_ENCODER_SUCCESS) { + flb_log_event_encoder_rollback_record(log_encoder); + return -1; + } + ret = flb_log_event_encoder_append_body_int32(log_encoder, ev->details.vfs.error_raw); + if (ret != FLB_EVENT_ENCODER_SUCCESS) { + flb_log_event_encoder_rollback_record(log_encoder); + return -1; + } + + ret = flb_log_event_encoder_commit_record(log_encoder); + if (ret != FLB_EVENT_ENCODER_SUCCESS) { + return -1; + } + + return 0; +} + +int trace_vfs_handler(void *ctx, void *data, size_t data_sz) +{ + struct trace_event_context *event_ctx = (struct trace_event_context *) ctx; + struct event *ev = (struct event *) data; + struct flb_log_event_encoder *encoder = event_ctx->log_encoder; + int ret; + + if (data_sz < sizeof(struct event) || ev->type != EVENT_TYPE_VFS) { + return -1; + } + + ret = encode_vfs_event(event_ctx->ins, encoder, ev); + if (ret != 0) { + return -1; + } + + ret = flb_input_log_append(event_ctx->ins, NULL, 0, + encoder->output_buffer, encoder->output_length); + if (ret == -1) { + return -1; + } + + flb_log_event_encoder_reset(encoder); + + return 0; +} diff --git a/plugins/in_ebpf/traces/vfs/handler.h b/plugins/in_ebpf/traces/vfs/handler.h new file mode 100644 index 00000000000..987d10defff --- /dev/null +++ b/plugins/in_ebpf/traces/vfs/handler.h @@ -0,0 +1,12 @@ +#ifndef VFS_HANDLER_H +#define VFS_HANDLER_H + +#include +#include "common/events.h" + +int trace_vfs_handler(void *ctx, void *data, size_t data_sz); +int encode_vfs_event(struct flb_input_instance *ins, + struct flb_log_event_encoder *log_encoder, + const struct event *ev); + +#endif