diff --git a/plugins/in_ebpf/CMakeLists.txt b/plugins/in_ebpf/CMakeLists.txt index 476c077746d..97dd2af6509 100644 --- a/plugins/in_ebpf/CMakeLists.txt +++ b/plugins/in_ebpf/CMakeLists.txt @@ -27,6 +27,38 @@ target_include_directories(gadget INTERFACE ${CMAKE_SOURCE_DIR}/plugins/in_ebpf/ set(LIBC_PATH "/lib64/libc.so.6") +set(FLB_IN_EBPF_LIBSSL_PATH "" CACHE FILEPATH + "Path to libssl shared object used by eBPF OpenSSL uprobes") + +if (FLB_IN_EBPF_LIBSSL_PATH) + set(LIBSSL_PATH "${FLB_IN_EBPF_LIBSSL_PATH}") +else() + find_package(OpenSSL QUIET) + + if (OPENSSL_SSL_LIBRARY) + set(LIBSSL_PATH "${OPENSSL_SSL_LIBRARY}") + elseif (TARGET OpenSSL::SSL) + get_target_property(_libssl_path OpenSSL::SSL IMPORTED_LOCATION) + if (_libssl_path) + set(LIBSSL_PATH "${_libssl_path}") + endif() + endif() + + if (NOT LIBSSL_PATH) + find_library(LIBSSL_PATH NAMES ssl libssl.so libssl.so.3 libssl.so.1.1) + endif() + + if (NOT LIBSSL_PATH) + set(LIBSSL_PATH "/lib64/libssl.so.3") + endif() +endif() + +if (LIBSSL_PATH MATCHES "\\.(a|lib)$") + message(WARNING + "eBPF OpenSSL uprobes resolved a static OpenSSL library: ${LIBSSL_PATH}. " + "Set FLB_IN_EBPF_LIBSSL_PATH to the target host libssl shared object.") +endif() + find_program(LSB_RELEASE_EXEC lsb_release) if (LSB_RELEASE_EXEC) execute_process(COMMAND ${LSB_RELEASE_EXEC} -i @@ -50,12 +82,19 @@ if (LSB_RELEASE_EXEC) endif() endif() +message(STATUS "eBPF OpenSSL uprobes libssl path: ${LIBSSL_PATH}") + # Generate the malloc trace from the template configure_file( "${CMAKE_SOURCE_DIR}/plugins/in_ebpf/traces/malloc/bpf.c.in" "${CMAKE_SOURCE_DIR}/plugins/in_ebpf/traces/malloc/bpf.c" ) +configure_file( + "${CMAKE_SOURCE_DIR}/plugins/in_ebpf/traces/openssl/bpf.c.in" + "${CMAKE_SOURCE_DIR}/plugins/in_ebpf/traces/openssl/bpf.c" + ) + # Find all bpf.c files in the traces directory file(GLOB_RECURSE TRACE_C_FILES ${CMAKE_SOURCE_DIR}/plugins/in_ebpf/traces/*/bpf.c) diff --git a/plugins/in_ebpf/traces/bind/bpf.c b/plugins/in_ebpf/traces/bind/bpf.c index 1712bf67ec7..fd7b42d5aa4 100644 --- a/plugins/in_ebpf/traces/bind/bpf.c +++ b/plugins/in_ebpf/traces/bind/bpf.c @@ -20,6 +20,7 @@ #include #include "common/events.h" +#include "common/event_id.bpf.h" #define MAX_ENTRIES 10240 @@ -75,6 +76,7 @@ static int handle_bind_exit(struct pt_regs *ctx, short ver) { event->common.gid = (u32)(uid_gid >> 32); event->common.mntns_id = mntns_id; event->type = EVENT_TYPE_BIND; + generate_event_id(&event->common.event_id); event->common.timestamp_raw = bpf_ktime_get_boot_ns(); bpf_get_current_comm(&event->common.comm, sizeof(event->common.comm)); diff --git a/plugins/in_ebpf/traces/dns/bpf.c b/plugins/in_ebpf/traces/dns/bpf.c index 9a944bec35d..3d9187e8fce 100644 --- a/plugins/in_ebpf/traces/dns/bpf.c +++ b/plugins/in_ebpf/traces/dns/bpf.c @@ -14,6 +14,7 @@ #include #include "common/events.h" +#include "common/event_id.bpf.h" #ifndef AF_INET #define AF_INET 2 @@ -96,6 +97,7 @@ static __always_inline void fill_common(struct event *event, __u64 mntns_id) pid_tgid = bpf_get_current_pid_tgid(); uid_gid = bpf_get_current_uid_gid(); + generate_event_id(&event->common.event_id); event->common.timestamp_raw = bpf_ktime_get_boot_ns(); event->common.pid = (__u32) (pid_tgid >> 32); event->common.tid = (__u32) pid_tgid; diff --git a/plugins/in_ebpf/traces/exec/bpf.c b/plugins/in_ebpf/traces/exec/bpf.c index 21b6dec524b..0c9326f4e67 100644 --- a/plugins/in_ebpf/traces/exec/bpf.c +++ b/plugins/in_ebpf/traces/exec/bpf.c @@ -14,6 +14,7 @@ #include #include "common/events.h" +#include "common/event_id.bpf.h" #define MAX_ENTRIES 10240 #define ARGV_MAX_SCAN 20 @@ -71,6 +72,7 @@ static __always_inline int submit_exec_event(void *ctx, pid_tgid = bpf_get_current_pid_tgid(); uid_gid = bpf_get_current_uid_gid(); + generate_event_id(&event->common.event_id); event->common.timestamp_raw = bpf_ktime_get_boot_ns(); event->common.pid = (__u32) (pid_tgid >> 32); event->common.tid = (__u32) pid_tgid; diff --git a/plugins/in_ebpf/traces/includes/common/encoder.h b/plugins/in_ebpf/traces/includes/common/encoder.h index bb89b0810ba..5674c4a26ff 100644 --- a/plugins/in_ebpf/traces/includes/common/encoder.h +++ b/plugins/in_ebpf/traces/includes/common/encoder.h @@ -29,6 +29,14 @@ static inline char *event_type_to_string(enum event_type type) { return "dns"; case EVENT_TYPE_SCHED: return "sched"; + case EVENT_TYPE_TLS_HANDSHAKE: + return "tls_handshake"; + case EVENT_TYPE_TLS_READ: + return "tls_read"; + case EVENT_TYPE_TLS_WRITE: + return "tls_write"; + case EVENT_TYPE_TLS_SHUTDOWN: + return "tls_shutdown"; default: return "unknown"; } @@ -58,6 +66,16 @@ static inline int encode_common_fields(struct flb_log_event_encoder *log_encoder return -1; } + /* Encode event ID */ + ret = flb_log_event_encoder_append_body_cstring(log_encoder, "event_id"); + if (ret != FLB_EVENT_ENCODER_SUCCESS) { + return -1; + } + ret = flb_log_event_encoder_append_body_uint64(log_encoder, e->common.event_id); + if (ret != FLB_EVENT_ENCODER_SUCCESS) { + return -1; + } + /* Encode process ID */ ret = flb_log_event_encoder_append_body_cstring(log_encoder, "pid"); if (ret != FLB_EVENT_ENCODER_SUCCESS) { diff --git a/plugins/in_ebpf/traces/includes/common/event_id.bpf.h b/plugins/in_ebpf/traces/includes/common/event_id.bpf.h new file mode 100644 index 00000000000..77afbcd8ceb --- /dev/null +++ b/plugins/in_ebpf/traces/includes/common/event_id.bpf.h @@ -0,0 +1,27 @@ +#ifndef EBPF_EVENT_ID_H +#define EBPF_EVENT_ID_H + +#include + +struct { + __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); + __type(key, __u32); + __type(value, __u64); + __uint(max_entries, 1); +} seq_counter SEC(".maps"); + +static __always_inline void generate_event_id(__u64 *event_id) +{ + __u32 key = 0; + __u64 *counter = bpf_map_lookup_elem(&seq_counter, &key); + if (counter) { + /* ID is CPU shifted left by 48 bits, OR'd with per-CPU counter */ + *event_id = ((__u64)bpf_get_smp_processor_id() << 48) | (*counter); + (*counter)++; + } + else { + *event_id = 0; + } +} + +#endif /* EBPF_EVENT_ID_H */ diff --git a/plugins/in_ebpf/traces/includes/common/events.h b/plugins/in_ebpf/traces/includes/common/events.h index 1ecb5ce9f5a..6f84b9571a4 100644 --- a/plugins/in_ebpf/traces/includes/common/events.h +++ b/plugins/in_ebpf/traces/includes/common/events.h @@ -22,6 +22,10 @@ enum event_type { EVENT_TYPE_CONNECT, EVENT_TYPE_DNS, EVENT_TYPE_SCHED, + EVENT_TYPE_TLS_HANDSHAKE, + EVENT_TYPE_TLS_READ, + EVENT_TYPE_TLS_WRITE, + EVENT_TYPE_TLS_SHUTDOWN, }; enum vfs_op { @@ -45,6 +49,7 @@ enum memop { }; struct event_common { + __u64 event_id; __u64 timestamp_raw; __u32 pid; __u32 tid; @@ -163,6 +168,18 @@ struct sched_sample { struct sched_event details; }; +struct tls_handshake_event { + __u64 ssl_ptr; + __s64 latency_ns; + int ret; +}; + +struct tls_io_event { + __u64 ssl_ptr; + __s64 latency_ns; + int ret; +}; + struct event { enum event_type type; // Type of event (execve, signal, mem, bind) struct event_common common; // Common fields for all events @@ -177,6 +194,8 @@ struct event { struct connect_event connect; struct dns_event dns; struct sched_event sched; + struct tls_handshake_event tls_handshake; + struct tls_io_event tls_io; } details; }; diff --git a/plugins/in_ebpf/traces/malloc/bpf.c.in b/plugins/in_ebpf/traces/malloc/bpf.c.in index c37d3952a20..420da823d32 100644 --- a/plugins/in_ebpf/traces/malloc/bpf.c.in +++ b/plugins/in_ebpf/traces/malloc/bpf.c.in @@ -15,6 +15,7 @@ #include #include "common/events.h" +#include "common/event_id.bpf.h" #define MAX_ENTRIES 10240 @@ -72,6 +73,7 @@ static int gen_alloc_exit(struct pt_regs *ctx, enum memop op, u64 addr) { u64 uid_gid = bpf_get_current_uid_gid(); + generate_event_id(&eventp->common.event_id); eventp->common.timestamp_raw = bpf_ktime_get_ns(); eventp->common.pid = tid >> 32; eventp->common.tid = tid; @@ -102,6 +104,7 @@ static int gen_free_enter(struct pt_regs *ctx, enum memop op, u64 addr) { u32 tid = (u32)bpf_get_current_pid_tgid(); + generate_event_id(&eventp->common.event_id); eventp->common.timestamp_raw = bpf_ktime_get_ns(); eventp->common.pid = tid >> 32; eventp->common.tid = tid; diff --git a/plugins/in_ebpf/traces/openssl/bpf.c.in b/plugins/in_ebpf/traces/openssl/bpf.c.in new file mode 100644 index 00000000000..983cee2409b --- /dev/null +++ b/plugins/in_ebpf/traces/openssl/bpf.c.in @@ -0,0 +1,244 @@ +// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) + +#include + +#define _LINUX_TYPES_H +#define _LINUX_POSIX_TYPES_H + +#if defined(__TARGET_ARCH_x86_64) && !defined(__TARGET_ARCH_x86) +#define __TARGET_ARCH_x86 +#endif + +#include +#include + +#include +#include +#include +#include + +#include "common/events.h" +#include "common/event_id.bpf.h" + +#define MAX_ENTRIES 10240 + +struct tls_state { + __u64 ssl_ptr; + __u64 start_ns; + __u64 bytes_ptr; + __u32 type; +}; + +#define TLS_EVENT_HANDSHAKE EVENT_TYPE_TLS_HANDSHAKE +#define TLS_EVENT_READ EVENT_TYPE_TLS_READ +#define TLS_EVENT_WRITE EVENT_TYPE_TLS_WRITE +#define TLS_EVENT_SHUTDOWN EVENT_TYPE_TLS_SHUTDOWN + +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, MAX_ENTRIES); + __type(key, __u64); /* pid_tgid */ + __type(value, struct tls_state); +} tls_start SEC(".maps"); + +GADGET_TRACER_MAP(events, 1024 * 256); + +static __always_inline void fill_common(struct event *event) +{ + __u64 pid_tgid; + __u64 uid_gid; + + pid_tgid = bpf_get_current_pid_tgid(); + uid_gid = bpf_get_current_uid_gid(); + + generate_event_id(&event->common.event_id); + event->common.timestamp_raw = bpf_ktime_get_boot_ns(); + event->common.pid = (__u32) (pid_tgid >> 32); + event->common.tid = (__u32) pid_tgid; + event->common.uid = (__u32) uid_gid; + event->common.gid = (__u32) (uid_gid >> 32); + event->common.mntns_id = 0; + bpf_get_current_comm(event->common.comm, sizeof(event->common.comm)); +} + +static __always_inline int trace_tls_entry(void *ssl, __u32 type) +{ + __u64 pid_tgid = bpf_get_current_pid_tgid(); + struct tls_state state = {}; + + state.ssl_ptr = (__u64) ssl; + state.start_ns = bpf_ktime_get_ns(); + state.type = type; + + bpf_map_update_elem(&tls_start, &pid_tgid, &state, BPF_ANY); + return 0; +} + +static __always_inline int trace_tls_entry_ex(void *ssl, __u32 type, + size_t *bytes_ptr) +{ + __u64 pid_tgid = bpf_get_current_pid_tgid(); + struct tls_state state = {}; + + state.ssl_ptr = (__u64) ssl; + state.start_ns = bpf_ktime_get_ns(); + state.bytes_ptr = (__u64) bytes_ptr; + state.type = type; + + bpf_map_update_elem(&tls_start, &pid_tgid, &state, BPF_ANY); + return 0; +} + +static __always_inline int get_openssl_ex_ret(int ret, __u64 bytes_ptr) +{ + size_t byte_count = 0; + + if (ret <= 0) { + return ret; + } + + if (bytes_ptr == 0) { + return -1; + } + + if (bpf_probe_read_user(&byte_count, sizeof(byte_count), + (const void *) bytes_ptr) != 0) { + return -1; + } + + if (byte_count > 0x7fffffffULL) { + return 0x7fffffff; + } + + return (int) byte_count; +} + +static __always_inline int trace_tls_return(struct pt_regs *ctx) +{ + __u64 pid_tgid = bpf_get_current_pid_tgid(); + struct tls_state *state; + __u64 now_ns; + __s64 latency_ns; + struct event *eventp; + int ret; + + state = bpf_map_lookup_elem(&tls_start, &pid_tgid); + if (!state) { + return 0; + } + + now_ns = bpf_ktime_get_ns(); + latency_ns = (__s64)(now_ns - state->start_ns); + + eventp = gadget_reserve_buf(&events, sizeof(*eventp)); + if (!eventp) { + bpf_map_delete_elem(&tls_start, &pid_tgid); + return 0; + } + + fill_common(eventp); + eventp->type = state->type; + if (state->type == TLS_EVENT_HANDSHAKE) { + eventp->details.tls_handshake.ssl_ptr = state->ssl_ptr; + eventp->details.tls_handshake.latency_ns = latency_ns; +#if defined(__TARGET_ARCH_arm64) + ret = (int) ctx->regs[0]; +#else + ret = (int) PT_REGS_RC(ctx); +#endif + eventp->details.tls_handshake.ret = ret; + } + else { + eventp->details.tls_io.ssl_ptr = state->ssl_ptr; + eventp->details.tls_io.latency_ns = latency_ns; +#if defined(__TARGET_ARCH_arm64) + ret = (int) ctx->regs[0]; +#else + ret = (int) PT_REGS_RC(ctx); +#endif + if (state->bytes_ptr != 0) { + ret = get_openssl_ex_ret(ret, state->bytes_ptr); + } + eventp->details.tls_io.ret = ret; + } + + gadget_submit_buf(ctx, &events, eventp, sizeof(*eventp)); + bpf_map_delete_elem(&tls_start, &pid_tgid); + return 0; +} + +SEC("uprobe/@LIBSSL_PATH@:SSL_do_handshake") +int BPF_UPROBE(trace_uprobe_ssl_do_handshake, void *ssl) +{ + return trace_tls_entry(ssl, TLS_EVENT_HANDSHAKE); +} + +SEC("uretprobe/@LIBSSL_PATH@:SSL_do_handshake") +int trace_uretprobe_ssl_do_handshake(struct pt_regs *ctx) +{ + return trace_tls_return(ctx); +} + +SEC("uprobe/@LIBSSL_PATH@:SSL_read") +int BPF_UPROBE(trace_uprobe_ssl_read, void *ssl) +{ + return trace_tls_entry(ssl, TLS_EVENT_READ); +} + +SEC("uretprobe/@LIBSSL_PATH@:SSL_read") +int trace_uretprobe_ssl_read(struct pt_regs *ctx) +{ + return trace_tls_return(ctx); +} + +SEC("uprobe/@LIBSSL_PATH@:SSL_read_ex") +int BPF_UPROBE(trace_uprobe_ssl_read_ex, void *ssl, void *buf, size_t num, + size_t *readbytes) +{ + return trace_tls_entry_ex(ssl, TLS_EVENT_READ, readbytes); +} + +SEC("uretprobe/@LIBSSL_PATH@:SSL_read_ex") +int trace_uretprobe_ssl_read_ex(struct pt_regs *ctx) +{ + return trace_tls_return(ctx); +} + +SEC("uprobe/@LIBSSL_PATH@:SSL_write") +int BPF_UPROBE(trace_uprobe_ssl_write, void *ssl) +{ + return trace_tls_entry(ssl, TLS_EVENT_WRITE); +} + +SEC("uretprobe/@LIBSSL_PATH@:SSL_write") +int trace_uretprobe_ssl_write(struct pt_regs *ctx) +{ + return trace_tls_return(ctx); +} + +SEC("uprobe/@LIBSSL_PATH@:SSL_write_ex") +int BPF_UPROBE(trace_uprobe_ssl_write_ex, void *ssl, const void *buf, size_t num, + size_t *written) +{ + return trace_tls_entry_ex(ssl, TLS_EVENT_WRITE, written); +} + +SEC("uretprobe/@LIBSSL_PATH@:SSL_write_ex") +int trace_uretprobe_ssl_write_ex(struct pt_regs *ctx) +{ + return trace_tls_return(ctx); +} + +SEC("uprobe/@LIBSSL_PATH@:SSL_shutdown") +int BPF_UPROBE(trace_uprobe_ssl_shutdown, void *ssl) +{ + return trace_tls_entry(ssl, TLS_EVENT_SHUTDOWN); +} + +SEC("uretprobe/@LIBSSL_PATH@:SSL_shutdown") +int trace_uretprobe_ssl_shutdown(struct pt_regs *ctx) +{ + return trace_tls_return(ctx); +} + +char LICENSE[] SEC("license") = "Dual BSD/GPL"; diff --git a/plugins/in_ebpf/traces/openssl/handler.c b/plugins/in_ebpf/traces/openssl/handler.c new file mode 100644 index 00000000000..23b036e84c0 --- /dev/null +++ b/plugins/in_ebpf/traces/openssl/handler.c @@ -0,0 +1,167 @@ +#include +#include + +#include "common/events.h" +#include "common/event_context.h" +#include "common/encoder.h" + +#include "handler.h" + +static int is_openssl_tls_event(enum event_type type) +{ + if (type == EVENT_TYPE_TLS_HANDSHAKE || + type == EVENT_TYPE_TLS_READ || + type == EVENT_TYPE_TLS_WRITE || + type == EVENT_TYPE_TLS_SHUTDOWN) { + return FLB_TRUE; + } + + return FLB_FALSE; +} + +int encode_openssl_event(struct flb_log_event_encoder *log_encoder, + const struct event *ev) +{ + int ret; + const char *trace_name; + + if (!is_openssl_tls_event(ev->type)) { + return -1; + } + + 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, "trace"); + if (ret != FLB_EVENT_ENCODER_SUCCESS) { + flb_log_event_encoder_rollback_record(log_encoder); + return -1; + } + + if (ev->type == EVENT_TYPE_TLS_READ) { + trace_name = "openssl_tls_read"; + } + else if (ev->type == EVENT_TYPE_TLS_WRITE) { + trace_name = "openssl_tls_write"; + } + else if (ev->type == EVENT_TYPE_TLS_SHUTDOWN) { + trace_name = "openssl_tls_shutdown"; + } + else if (ev->type == EVENT_TYPE_TLS_HANDSHAKE) { + trace_name = "openssl_tls_handshake"; + } + else { + flb_log_event_encoder_rollback_record(log_encoder); + return -1; + } + + ret = flb_log_event_encoder_append_body_cstring(log_encoder, trace_name); + 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, "ssl_ptr"); + if (ret != FLB_EVENT_ENCODER_SUCCESS) { + flb_log_event_encoder_rollback_record(log_encoder); + return -1; + } + if (ev->type == EVENT_TYPE_TLS_HANDSHAKE) { + ret = flb_log_event_encoder_append_body_uint64(log_encoder, + ev->details.tls_handshake.ssl_ptr); + } + else { + ret = flb_log_event_encoder_append_body_uint64(log_encoder, + ev->details.tls_io.ssl_ptr); + } + 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, "latency_ns"); + if (ret != FLB_EVENT_ENCODER_SUCCESS) { + flb_log_event_encoder_rollback_record(log_encoder); + return -1; + } + if (ev->type == EVENT_TYPE_TLS_HANDSHAKE) { + ret = flb_log_event_encoder_append_body_int64(log_encoder, + ev->details.tls_handshake.latency_ns); + } + else { + ret = flb_log_event_encoder_append_body_int64(log_encoder, + ev->details.tls_io.latency_ns); + } + 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, "ret"); + if (ret != FLB_EVENT_ENCODER_SUCCESS) { + flb_log_event_encoder_rollback_record(log_encoder); + return -1; + } + if (ev->type == EVENT_TYPE_TLS_HANDSHAKE) { + ret = flb_log_event_encoder_append_body_int32(log_encoder, + ev->details.tls_handshake.ret); + } + else { + ret = flb_log_event_encoder_append_body_int32(log_encoder, + ev->details.tls_io.ret); + } + 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) { + flb_log_event_encoder_rollback_record(log_encoder); + return -1; + } + + return 0; +} + +int trace_openssl_handler(void *ctx, void *data, size_t data_sz) +{ + struct trace_event_context *event_ctx; + struct event *ev; + struct flb_log_event_encoder *encoder; + int ret; + + event_ctx = (struct trace_event_context *) ctx; + ev = (struct event *) data; + encoder = event_ctx->log_encoder; + + if (data_sz < sizeof(struct event)) { + return -1; + } + + if (!is_openssl_tls_event(ev->type)) { + return -1; + } + + ret = encode_openssl_event(encoder, ev); + if (ret != 0) { + return -1; + } + + ret = flb_input_log_append(event_ctx->ins, NULL, 0, + encoder->output_buffer, encoder->output_length); + flb_log_event_encoder_reset(encoder); + if (ret == -1) { + return -1; + } + + return 0; +} diff --git a/plugins/in_ebpf/traces/openssl/handler.h b/plugins/in_ebpf/traces/openssl/handler.h new file mode 100644 index 00000000000..235a3edbe7c --- /dev/null +++ b/plugins/in_ebpf/traces/openssl/handler.h @@ -0,0 +1,13 @@ +#ifndef TRACE_OPENSSL_HANDLER_H +#define TRACE_OPENSSL_HANDLER_H + +#include + +struct event; +struct flb_log_event_encoder; + +int encode_openssl_event(struct flb_log_event_encoder *log_encoder, + const struct event *ev); +int trace_openssl_handler(void *ctx, void *data, size_t data_sz); + +#endif diff --git a/plugins/in_ebpf/traces/sched/bpf.c b/plugins/in_ebpf/traces/sched/bpf.c index 56ded2fe389..db404c7feaf 100644 --- a/plugins/in_ebpf/traces/sched/bpf.c +++ b/plugins/in_ebpf/traces/sched/bpf.c @@ -14,6 +14,7 @@ #include #include "common/events.h" +#include "common/event_id.bpf.h" struct wakeup_info { __u64 wakeup_ns; @@ -102,6 +103,7 @@ int BPF_PROG(trace_sched_switch, bool preempt, struct task_struct *prev, } event->type = EVENT_TYPE_SCHED; + generate_event_id(&event->common.event_id); event->common.timestamp_raw = bpf_ktime_get_boot_ns(); event->common.pid = next_pid; event->common.tid = next_tid; diff --git a/plugins/in_ebpf/traces/signal/bpf.c b/plugins/in_ebpf/traces/signal/bpf.c index 7d4503c220d..b5c30c76942 100644 --- a/plugins/in_ebpf/traces/signal/bpf.c +++ b/plugins/in_ebpf/traces/signal/bpf.c @@ -16,6 +16,7 @@ #include #include "common/events.h" +#include "common/event_id.bpf.h" struct value { @@ -81,6 +82,7 @@ static int handle_signal_exit(void *ctx, int ret) { return 0; /* Populate the event with data */ + generate_event_id(&eventp->common.event_id); eventp->common.timestamp_raw = bpf_ktime_get_boot_ns(); eventp->common.pid = pid_tgid >> 32; eventp->common.tid = tid; @@ -167,6 +169,7 @@ int ig_sig_generate(struct trace_event_raw_signal_generate *ctx) { return 0; /* Populate the event with data */ + generate_event_id(&event->common.event_id); event->common.timestamp_raw = bpf_ktime_get_boot_ns(); event->common.pid = pid; event->common.tid = (__u32)pid_tgid; diff --git a/plugins/in_ebpf/traces/tcp/bpf.c b/plugins/in_ebpf/traces/tcp/bpf.c index c5b39e452fd..c1312ba1ad8 100644 --- a/plugins/in_ebpf/traces/tcp/bpf.c +++ b/plugins/in_ebpf/traces/tcp/bpf.c @@ -15,6 +15,7 @@ #include #include "common/events.h" +#include "common/event_id.bpf.h" #ifndef AF_UNSPEC #define AF_UNSPEC 0 @@ -81,6 +82,7 @@ static __always_inline void fill_common(struct event *event, __u64 mntns_id) pid_tgid = bpf_get_current_pid_tgid(); uid_gid = bpf_get_current_uid_gid(); + generate_event_id(&event->common.event_id); event->common.timestamp_raw = bpf_ktime_get_boot_ns(); event->common.pid = (__u32) (pid_tgid >> 32); event->common.tid = (__u32) pid_tgid; diff --git a/plugins/in_ebpf/traces/traces.h b/plugins/in_ebpf/traces/traces.h index a32edcb061f..aa8a3db5a2e 100644 --- a/plugins/in_ebpf/traces/traces.h +++ b/plugins/in_ebpf/traces/traces.h @@ -11,6 +11,7 @@ #include "generated/trace_exec.skel.h" #include "generated/trace_dns.skel.h" #include "generated/trace_sched.skel.h" +#include "generated/trace_openssl.skel.h" #include "bind/handler.h" #include "signal/handler.h" // Include signal handler @@ -20,6 +21,7 @@ #include "exec/handler.h" #include "dns/handler.h" #include "sched/handler.h" +#include "openssl/handler.h" /* Skeleton function pointer types */ typedef void *(*trace_skel_open_func_t)(void); @@ -75,6 +77,7 @@ DEFINE_GET_BPF_OBJECT(trace_tcp) DEFINE_GET_BPF_OBJECT(trace_exec) DEFINE_GET_BPF_OBJECT(trace_dns) DEFINE_GET_BPF_OBJECT(trace_sched) +DEFINE_GET_BPF_OBJECT(trace_openssl) static struct trace_registration trace_table[] = { REGISTER_TRACE(trace_signal, trace_signal_handler), @@ -85,6 +88,7 @@ static struct trace_registration trace_table[] = { REGISTER_TRACE(trace_exec, trace_exec_handler), REGISTER_TRACE(trace_dns, trace_dns_handler), REGISTER_TRACE(trace_sched, trace_sched_handler), + REGISTER_TRACE(trace_openssl, trace_openssl_handler), }; #endif // TRACE_TRACES_H diff --git a/plugins/in_ebpf/traces/vfs/bpf.c b/plugins/in_ebpf/traces/vfs/bpf.c index b77212d5f77..efa424e57f6 100644 --- a/plugins/in_ebpf/traces/vfs/bpf.c +++ b/plugins/in_ebpf/traces/vfs/bpf.c @@ -14,6 +14,7 @@ #include #include "common/events.h" +#include "common/event_id.bpf.h" #define MAX_ENTRIES 10240 @@ -87,6 +88,7 @@ int trace_vfs_openat_exit(struct syscall_trace_exit *ctx) uid_gid = bpf_get_current_uid_gid(); + generate_event_id(&event->common.event_id); event->common.timestamp_raw = bpf_ktime_get_boot_ns(); event->common.pid = pid_tgid >> 32; event->common.tid = tid; diff --git a/tests/runtime/CMakeLists.txt b/tests/runtime/CMakeLists.txt index 104750b456e..be91112e958 100644 --- a/tests/runtime/CMakeLists.txt +++ b/tests/runtime/CMakeLists.txt @@ -181,6 +181,12 @@ if(FLB_IN_EBPF) "../../plugins/in_ebpf/traces/exec/handler.c" ) + add_ebpf_handler_test( + "openssl" + "in_ebpf_openssl_handler.c" + "../../plugins/in_ebpf/traces/openssl/handler.c" + ) + add_ebpf_handler_test( "sched" "in_ebpf_sched_handler.c" @@ -192,6 +198,7 @@ if(FLB_IN_EBPF) add_dependencies(flb-rt-in_ebpf_malloc_handler fluent-bit-static) add_dependencies(flb-rt-in_ebpf_tcp_handler fluent-bit-static) add_dependencies(flb-rt-in_ebpf_exec_handler fluent-bit-static) + add_dependencies(flb-rt-in_ebpf_openssl_handler fluent-bit-static) add_dependencies(flb-rt-in_ebpf_sched_handler fluent-bit-static) endif() diff --git a/tests/runtime/in_ebpf_openssl_handler.c b/tests/runtime/in_ebpf_openssl_handler.c new file mode 100644 index 00000000000..307f4c4cb11 --- /dev/null +++ b/tests/runtime/in_ebpf_openssl_handler.c @@ -0,0 +1,122 @@ +#include +#include + +#include +#include + +#include "flb_tests_runtime.h" + +#include "../../plugins/in_ebpf/traces/includes/common/event_context.h" +#include "../../plugins/in_ebpf/traces/includes/common/events.h" +#include "../../plugins/in_ebpf/traces/openssl/handler.h" + +struct test_context { + struct trace_event_context event_ctx; + struct flb_input_instance *ins; +}; + +static struct test_context *init_test_context(void) +{ + struct test_context *ctx; + + ctx = flb_calloc(1, sizeof(struct test_context)); + if (!ctx) { + return NULL; + } + + ctx->ins = flb_calloc(1, sizeof(struct flb_input_instance)); + if (!ctx->ins) { + flb_free(ctx); + return NULL; + } + + ctx->event_ctx.log_encoder = flb_log_event_encoder_create(FLB_LOG_EVENT_FORMAT_DEFAULT); + if (!ctx->event_ctx.log_encoder) { + flb_free(ctx->ins); + flb_free(ctx); + return NULL; + } + + ctx->ins->context = &ctx->event_ctx; + ctx->event_ctx.ins = ctx->ins; + + return ctx; +} + +static void cleanup_test_context(struct test_context *ctx) +{ + if (!ctx) { + return; + } + + if (ctx->event_ctx.log_encoder) { + flb_log_event_encoder_destroy(ctx->event_ctx.log_encoder); + } + + if (ctx->ins) { + flb_free(ctx->ins); + } + + flb_free(ctx); +} + +void test_openssl_event_encoding(void) +{ + struct test_context *ctx; + struct event ev = {0}; + int ret; + int i; + int types[] = { + EVENT_TYPE_TLS_HANDSHAKE, + EVENT_TYPE_TLS_READ, + EVENT_TYPE_TLS_WRITE, + EVENT_TYPE_TLS_SHUTDOWN + }; + + ctx = init_test_context(); + TEST_CHECK(ctx != NULL); + + for (i = 0; i < (int) (sizeof(types) / sizeof(types[0])); i++) { + memset(&ev, 0, sizeof(ev)); + ev.type = types[i]; + ev.common.pid = 101; + ev.common.tid = 202; + strncpy(ev.common.comm, "openssl", sizeof(ev.common.comm)); + ev.details.tls_io.ssl_ptr = 0x1234; + ev.details.tls_io.latency_ns = 5000; + ev.details.tls_io.ret = 1; + + ret = encode_openssl_event(ctx->event_ctx.log_encoder, &ev); + TEST_CHECK(ret == 0); + } + + cleanup_test_context(ctx); +} + +void test_openssl_event_encoding_rejects_unknown_type(void) +{ + struct test_context *ctx; + struct event ev = {0}; + int ret; + + ctx = init_test_context(); + TEST_CHECK(ctx != NULL); + + ev.type = EVENT_TYPE_SCHED; + ev.common.pid = 101; + ev.common.tid = 202; + strncpy(ev.common.comm, "openssl", sizeof(ev.common.comm)); + + ret = encode_openssl_event(ctx->event_ctx.log_encoder, &ev); + TEST_CHECK(ret == -1); + TEST_CHECK(ctx->event_ctx.log_encoder->output_length == 0); + + cleanup_test_context(ctx); +} + +TEST_LIST = { + {"openssl_event_encoding", test_openssl_event_encoding}, + {"openssl_event_encoding_rejects_unknown_type", + test_openssl_event_encoding_rejects_unknown_type}, + {NULL, NULL} +};