mirror of
https://github.com/kubeshark/kubeshark.git
synced 2025-07-31 16:25:22 +00:00
EBPF error handling
This commit is contained in:
parent
0a9be1884a
commit
590fa08c81
@ -259,9 +259,10 @@ func startPassiveTapper(streamsMap *tcpStreamMap, assembler *tcpAssembler) {
|
||||
|
||||
func startTlsTapper(extension *api.Extension, outputItems chan *api.OutputChannelItem, options *api.TrafficFilteringOptions) *tlstapper.TlsTapper {
|
||||
tls := tlstapper.TlsTapper{}
|
||||
tlsPerfBufferSize := os.Getpagesize() * 100
|
||||
chunksBufferSize := os.Getpagesize() * 100
|
||||
logBufferSize := os.Getpagesize()
|
||||
|
||||
if err := tls.Init(tlsPerfBufferSize, *procfs, extension); err != nil {
|
||||
if err := tls.Init(chunksBufferSize, logBufferSize, *procfs, extension); err != nil {
|
||||
tlstapper.LogError(err)
|
||||
return nil
|
||||
}
|
||||
@ -285,6 +286,7 @@ func startTlsTapper(extension *api.Extension, outputItems chan *api.OutputChanne
|
||||
OutputChannel: outputItems,
|
||||
}
|
||||
|
||||
go tls.PollForLogging()
|
||||
go tls.Poll(emitter, options)
|
||||
|
||||
return &tls
|
||||
|
@ -7,8 +7,12 @@ Copyright (C) UP9 Inc.
|
||||
#include "include/headers.h"
|
||||
#include "include/util.h"
|
||||
#include "include/maps.h"
|
||||
#include "include/log.h"
|
||||
#include "include/logger_messages.h"
|
||||
#include "include/pids.h"
|
||||
|
||||
#define IPV4_ADDR_LEN (16)
|
||||
|
||||
struct accept_info {
|
||||
__u64* sockaddr;
|
||||
__u32* addrlen;
|
||||
@ -41,9 +45,7 @@ void sys_enter_accept4(struct sys_enter_accept4_ctx *ctx) {
|
||||
long err = bpf_map_update_elem(&accept_syscall_context, &id, &info, BPF_ANY);
|
||||
|
||||
if (err != 0) {
|
||||
char msg[] = "Error putting accept info (id: %ld) (err: %ld)";
|
||||
bpf_trace_printk(msg, sizeof(msg), id, err);
|
||||
return;
|
||||
log_error(ctx, LOG_ERROR_PUTTING_ACCEPT_INFO, id, err, 0l);
|
||||
}
|
||||
}
|
||||
|
||||
@ -70,6 +72,7 @@ void sys_exit_accept4(struct sys_exit_accept4_ctx *ctx) {
|
||||
struct accept_info *infoPtr = bpf_map_lookup_elem(&accept_syscall_context, &id);
|
||||
|
||||
if (infoPtr == NULL) {
|
||||
log_error(ctx, LOG_ERROR_GETTING_ACCEPT_INFO, id, 0l, 0l);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -79,15 +82,14 @@ void sys_exit_accept4(struct sys_exit_accept4_ctx *ctx) {
|
||||
bpf_map_delete_elem(&accept_syscall_context, &id);
|
||||
|
||||
if (err != 0) {
|
||||
char msg[] = "Error reading accept info from accept syscall (id: %ld) (err: %ld)";
|
||||
bpf_trace_printk(msg, sizeof(msg), id, err);
|
||||
log_error(ctx, LOG_ERROR_READING_ACCEPT_INFO, id, err, 0l);
|
||||
return;
|
||||
}
|
||||
|
||||
__u32 addrlen;
|
||||
bpf_probe_read(&addrlen, sizeof(__u32), info.addrlen);
|
||||
|
||||
if (addrlen != 16) {
|
||||
if (addrlen != IPV4_ADDR_LEN) {
|
||||
// Currently only ipv4 is supported linux-src/include/linux/inet.h
|
||||
return;
|
||||
}
|
||||
@ -105,9 +107,7 @@ void sys_exit_accept4(struct sys_exit_accept4_ctx *ctx) {
|
||||
err = bpf_map_update_elem(&file_descriptor_to_ipv4, &key, &fdinfo, BPF_ANY);
|
||||
|
||||
if (err != 0) {
|
||||
char msg[] = "Error putting fd to address mapping from accept (key: %ld) (err: %ld)";
|
||||
bpf_trace_printk(msg, sizeof(msg), key, err);
|
||||
return;
|
||||
log_error(ctx, LOG_ERROR_PUTTING_FD_MAPPING, id, err, ORIGIN_SYS_EXIT_ACCEPT4_CODE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -145,9 +145,7 @@ void sys_enter_connect(struct sys_enter_connect_ctx *ctx) {
|
||||
long err = bpf_map_update_elem(&connect_syscall_info, &id, &info, BPF_ANY);
|
||||
|
||||
if (err != 0) {
|
||||
char msg[] = "Error putting connect info (id: %ld) (err: %ld)";
|
||||
bpf_trace_printk(msg, sizeof(msg), id, err);
|
||||
return;
|
||||
log_error(ctx, LOG_ERROR_PUTTING_CONNECT_INFO, id, err, 0l);
|
||||
}
|
||||
}
|
||||
|
||||
@ -176,6 +174,7 @@ void sys_exit_connect(struct sys_exit_connect_ctx *ctx) {
|
||||
struct connect_info *infoPtr = bpf_map_lookup_elem(&connect_syscall_info, &id);
|
||||
|
||||
if (infoPtr == NULL) {
|
||||
log_error(ctx, LOG_ERROR_GETTING_CONNECT_INFO, id, 0l, 0l);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -185,12 +184,11 @@ void sys_exit_connect(struct sys_exit_connect_ctx *ctx) {
|
||||
bpf_map_delete_elem(&connect_syscall_info, &id);
|
||||
|
||||
if (err != 0) {
|
||||
char msg[] = "Error reading connect info from connect syscall (id: %ld) (err: %ld)";
|
||||
bpf_trace_printk(msg, sizeof(msg), id, err);
|
||||
log_error(ctx, LOG_ERROR_READING_CONNECT_INFO, id, err, 0l);
|
||||
return;
|
||||
}
|
||||
|
||||
if (info.addrlen != 16) {
|
||||
if (info.addrlen != IPV4_ADDR_LEN) {
|
||||
// Currently only ipv4 is supported linux-src/include/linux/inet.h
|
||||
return;
|
||||
}
|
||||
@ -208,8 +206,6 @@ void sys_exit_connect(struct sys_exit_connect_ctx *ctx) {
|
||||
err = bpf_map_update_elem(&file_descriptor_to_ipv4, &key, &fdinfo, BPF_ANY);
|
||||
|
||||
if (err != 0) {
|
||||
char msg[] = "Error putting fd to address mapping from connect (key: %ld) (err: %ld)";
|
||||
bpf_trace_printk(msg, sizeof(msg), key, err);
|
||||
return;
|
||||
log_error(ctx, LOG_ERROR_PUTTING_FD_MAPPING, id, err, ORIGIN_SYS_EXIT_CONNECT_CODE);
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,8 @@ Copyright (C) UP9 Inc.
|
||||
#include "include/headers.h"
|
||||
#include "include/util.h"
|
||||
#include "include/maps.h"
|
||||
#include "include/log.h"
|
||||
#include "include/logger_messages.h"
|
||||
#include "include/pids.h"
|
||||
|
||||
struct sys_enter_read_ctx {
|
||||
@ -36,8 +38,7 @@ void sys_enter_read(struct sys_enter_read_ctx *ctx) {
|
||||
long err = bpf_probe_read(&info, sizeof(struct ssl_info), infoPtr);
|
||||
|
||||
if (err != 0) {
|
||||
char msg[] = "Error reading read info from read syscall (id: %ld) (err: %ld)";
|
||||
bpf_trace_printk(msg, sizeof(msg), id, err);
|
||||
log_error(ctx, LOG_ERROR_READING_SSL_CONTEXT, id, err, ORIGIN_SYS_ENTER_READ_CODE);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -46,9 +47,7 @@ void sys_enter_read(struct sys_enter_read_ctx *ctx) {
|
||||
err = bpf_map_update_elem(&ssl_read_context, &id, &info, BPF_ANY);
|
||||
|
||||
if (err != 0) {
|
||||
char msg[] = "Error putting file descriptor from read syscall (id: %ld) (err: %ld)";
|
||||
bpf_trace_printk(msg, sizeof(msg), id, err);
|
||||
return;
|
||||
log_error(ctx, LOG_ERROR_PUTTING_FILE_DESCRIPTOR, id, err, ORIGIN_SYS_ENTER_READ_CODE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,8 +78,7 @@ void sys_enter_write(struct sys_enter_write_ctx *ctx) {
|
||||
long err = bpf_probe_read(&info, sizeof(struct ssl_info), infoPtr);
|
||||
|
||||
if (err != 0) {
|
||||
char msg[] = "Error reading write context from write syscall (id: %ld) (err: %ld)";
|
||||
bpf_trace_printk(msg, sizeof(msg), id, err);
|
||||
log_error(ctx, LOG_ERROR_READING_SSL_CONTEXT, id, err, ORIGIN_SYS_ENTER_WRITE_CODE);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -89,8 +87,6 @@ void sys_enter_write(struct sys_enter_write_ctx *ctx) {
|
||||
err = bpf_map_update_elem(&ssl_write_context, &id, &info, BPF_ANY);
|
||||
|
||||
if (err != 0) {
|
||||
char msg[] = "Error putting file descriptor from write syscall (id: %ld) (err: %ld)";
|
||||
bpf_trace_printk(msg, sizeof(msg), id, err);
|
||||
return;
|
||||
log_error(ctx, LOG_ERROR_PUTTING_FILE_DESCRIPTOR, id, err, ORIGIN_SYS_ENTER_WRITE_CODE);
|
||||
}
|
||||
}
|
||||
|
79
tap/tlstapper/bpf/include/log.h
Normal file
79
tap/tlstapper/bpf/include/log.h
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
Note: This file is licenced differently from the rest of the project
|
||||
SPDX-License-Identifier: GPL-2.0
|
||||
Copyright (C) UP9 Inc.
|
||||
*/
|
||||
|
||||
#ifndef __LOG__
|
||||
#define __LOG__
|
||||
|
||||
// The same consts defined in bpf_logger.go
|
||||
//
|
||||
#define LOG_LEVEL_ERROR (0)
|
||||
#define LOG_LEVEL_INFO (1)
|
||||
#define LOG_LEVEL_DEBUG (2)
|
||||
|
||||
// The same struct can be found in bpf_logger.go
|
||||
//
|
||||
// Be careful when editing, alignment and padding should be exactly the same in go/c.
|
||||
//
|
||||
struct log_message {
|
||||
__u32 level;
|
||||
__u32 message_code;
|
||||
__u64 arg1;
|
||||
__u64 arg2;
|
||||
__u64 arg3;
|
||||
};
|
||||
|
||||
static __always_inline void log_error(void* ctx, __u16 message_code, __u64 arg1, __u64 arg2, __u64 arg3) {
|
||||
struct log_message entry = {};
|
||||
|
||||
entry.level = LOG_LEVEL_ERROR;
|
||||
entry.message_code = message_code;
|
||||
entry.arg1 = arg1;
|
||||
entry.arg2 = arg2;
|
||||
entry.arg3 = arg3;
|
||||
|
||||
long err = bpf_perf_event_output(ctx, &log_buffer, BPF_F_CURRENT_CPU, &entry, sizeof(struct log_message));
|
||||
|
||||
if (err != 0) {
|
||||
char msg[] = "Error writing log error to perf buffer - %ld";
|
||||
bpf_trace_printk(msg, sizeof(msg), err);
|
||||
}
|
||||
}
|
||||
|
||||
static __always_inline void log_info(void* ctx, __u16 message_code, __u64 arg1, __u64 arg2, __u64 arg3) {
|
||||
struct log_message entry = {};
|
||||
|
||||
entry.level = LOG_LEVEL_INFO;
|
||||
entry.message_code = message_code;
|
||||
entry.arg1 = arg1;
|
||||
entry.arg2 = arg2;
|
||||
entry.arg3 = arg3;
|
||||
|
||||
long err = bpf_perf_event_output(ctx, &log_buffer, BPF_F_CURRENT_CPU, &entry, sizeof(struct log_message));
|
||||
|
||||
if (err != 0) {
|
||||
char msg[] = "Error writing log info to perf buffer - %ld";
|
||||
bpf_trace_printk(msg, sizeof(msg), arg1, err);
|
||||
}
|
||||
}
|
||||
|
||||
static __always_inline void log_debug(void* ctx, __u16 message_code, __u64 arg1, __u64 arg2, __u64 arg3) {
|
||||
struct log_message entry = {};
|
||||
|
||||
entry.level = LOG_LEVEL_DEBUG;
|
||||
entry.message_code = message_code;
|
||||
entry.arg1 = arg1;
|
||||
entry.arg2 = arg2;
|
||||
entry.arg3 = arg3;
|
||||
|
||||
long err = bpf_perf_event_output(ctx, &log_buffer, BPF_F_CURRENT_CPU, &entry, sizeof(struct log_message));
|
||||
|
||||
if (err != 0) {
|
||||
char msg[] = "Error writing log debug to perf buffer - %ld";
|
||||
bpf_trace_printk(msg, sizeof(msg), arg1, err);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* __LOG__ */
|
42
tap/tlstapper/bpf/include/logger_messages.h
Normal file
42
tap/tlstapper/bpf/include/logger_messages.h
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
Note: This file is licenced differently from the rest of the project
|
||||
SPDX-License-Identifier: GPL-2.0
|
||||
Copyright (C) UP9 Inc.
|
||||
*/
|
||||
|
||||
#ifndef __LOG_MESSAGES__
|
||||
#define __LOG_MESSAGES__
|
||||
|
||||
// Must be synced with bpf_logger_messages.go
|
||||
//
|
||||
#define LOG_ERROR_READING_BYTES_COUNT (0)
|
||||
#define LOG_ERROR_READING_FD_ADDRESS (1)
|
||||
#define LOG_ERROR_READING_FROM_SSL_BUFFER (2)
|
||||
#define LOG_ERROR_BUFFER_TOO_BIG (3)
|
||||
#define LOG_ERROR_ALLOCATING_CHUNK (4)
|
||||
#define LOG_ERROR_READING_SSL_CONTEXT (5)
|
||||
#define LOG_ERROR_PUTTING_SSL_CONTEXT (6)
|
||||
#define LOG_ERROR_GETTING_SSL_CONTEXT (7)
|
||||
#define LOG_ERROR_MISSING_FILE_DESCRIPTOR (8)
|
||||
#define LOG_ERROR_PUTTING_FILE_DESCRIPTOR (9)
|
||||
#define LOG_ERROR_PUTTING_ACCEPT_INFO (10)
|
||||
#define LOG_ERROR_GETTING_ACCEPT_INFO (11)
|
||||
#define LOG_ERROR_READING_ACCEPT_INFO (12)
|
||||
#define LOG_ERROR_PUTTING_FD_MAPPING (13)
|
||||
#define LOG_ERROR_PUTTING_CONNECT_INFO (14)
|
||||
#define LOG_ERROR_GETTING_CONNECT_INFO (15)
|
||||
#define LOG_ERROR_READING_CONNECT_INFO (16)
|
||||
|
||||
// Sometimes we have the same error, happening from different locations.
|
||||
// in order to be able to distinct between them in the log, we add an
|
||||
// extra number that identify the location. The number can be anything,
|
||||
// but do not give the same number to different origins.
|
||||
//
|
||||
#define ORIGIN_SSL_UPROBE_CODE (0l)
|
||||
#define ORIGIN_SSL_URETPROBE_CODE (1l)
|
||||
#define ORIGIN_SYS_ENTER_READ_CODE (2l)
|
||||
#define ORIGIN_SYS_ENTER_WRITE_CODE (3l)
|
||||
#define ORIGIN_SYS_EXIT_ACCEPT4_CODE (4l)
|
||||
#define ORIGIN_SYS_EXIT_CONNECT_CODE (5l)
|
||||
|
||||
#endif /* __LOG_MESSAGES__ */
|
@ -70,5 +70,6 @@ BPF_LRU_HASH(ssl_write_context, __u64, struct ssl_info);
|
||||
BPF_LRU_HASH(ssl_read_context, __u64, struct ssl_info);
|
||||
BPF_HASH(file_descriptor_to_ipv4, __u64, struct fd_info);
|
||||
BPF_PERF_OUTPUT(chunks_buffer);
|
||||
BPF_PERF_OUTPUT(log_buffer);
|
||||
|
||||
#endif /* __MAPS__ */
|
||||
|
@ -7,6 +7,8 @@ Copyright (C) UP9 Inc.
|
||||
#include "include/headers.h"
|
||||
#include "include/util.h"
|
||||
#include "include/maps.h"
|
||||
#include "include/log.h"
|
||||
#include "include/logger_messages.h"
|
||||
#include "include/pids.h"
|
||||
|
||||
// Heap-like area for eBPF programs - stack size limited to 512 bytes, we must use maps for bigger (chunk) objects.
|
||||
@ -39,15 +41,14 @@ static __always_inline int get_count_bytes(struct pt_regs *ctx, struct ssl_info*
|
||||
long err = bpf_probe_read(&countBytes, sizeof(size_t), (void*) info->count_ptr);
|
||||
|
||||
if (err != 0) {
|
||||
char msg[] = "Error reading bytes count of _ex (id: %ld) (err: %ld)";
|
||||
bpf_trace_printk(msg, sizeof(msg), id, err);
|
||||
log_error(ctx, LOG_ERROR_READING_BYTES_COUNT, id, err, 0l);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return countBytes;
|
||||
}
|
||||
|
||||
static __always_inline void add_address_to_chunk(struct tlsChunk* chunk, __u64 id, __u32 fd) {
|
||||
static __always_inline void add_address_to_chunk(struct pt_regs *ctx, struct tlsChunk* chunk, __u64 id, __u32 fd) {
|
||||
__u32 pid = id >> 32;
|
||||
__u64 key = (__u64) pid << 32 | fd;
|
||||
|
||||
@ -61,8 +62,7 @@ static __always_inline void add_address_to_chunk(struct tlsChunk* chunk, __u64 i
|
||||
chunk->flags |= (fdinfo->flags & FLAGS_IS_CLIENT_BIT);
|
||||
|
||||
if (err != 0) {
|
||||
char msg[] = "Error reading from fd address %ld - %ld";
|
||||
bpf_trace_printk(msg, sizeof(msg), id, err);
|
||||
log_error(ctx, LOG_ERROR_READING_FD_ADDRESS, id, err, 0l);
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,8 +88,7 @@ static __always_inline void send_chunk_part(struct pt_regs *ctx, __u8* buffer, _
|
||||
}
|
||||
|
||||
if (err != 0) {
|
||||
char msg[] = "Error reading from ssl buffer %ld - %ld";
|
||||
bpf_trace_printk(msg, sizeof(msg), id, err);
|
||||
log_error(ctx, LOG_ERROR_READING_FROM_SSL_BUFFER, id, err, 0l);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -101,8 +100,9 @@ static __always_inline void send_chunk(struct pt_regs *ctx, __u8* buffer, __u64
|
||||
//
|
||||
// https://lwn.net/Articles/794934/
|
||||
//
|
||||
// If we want to compile in kernel older than 5.3, we should add "#pragma unroll" to this loop
|
||||
// However we want to run in kernel older than 5.3, hence we use "#pragma unroll" anyway
|
||||
//
|
||||
#pragma unroll
|
||||
for (int i = 0; i < MAX_CHUNKS_PER_OPERATION; i++) {
|
||||
if (chunk->len <= (CHUNK_SIZE * i)) {
|
||||
break;
|
||||
@ -120,8 +120,7 @@ static __always_inline void output_ssl_chunk(struct pt_regs *ctx, struct ssl_inf
|
||||
}
|
||||
|
||||
if (countBytes > (CHUNK_SIZE * MAX_CHUNKS_PER_OPERATION)) {
|
||||
char msg[] = "Buffer too big %d (id: %ld)";
|
||||
bpf_trace_printk(msg, sizeof(msg), countBytes, id);
|
||||
log_error(ctx, LOG_ERROR_BUFFER_TOO_BIG, id, countBytes, 0l);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -134,8 +133,7 @@ static __always_inline void output_ssl_chunk(struct pt_regs *ctx, struct ssl_inf
|
||||
chunk = bpf_map_lookup_elem(&heap, &zero);
|
||||
|
||||
if (!chunk) {
|
||||
char msg[] = "Unable to allocate chunk (id: %ld)";
|
||||
bpf_trace_printk(msg, sizeof(msg), id);
|
||||
log_error(ctx, LOG_ERROR_ALLOCATING_CHUNK, id, 0l, 0l);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -145,11 +143,11 @@ static __always_inline void output_ssl_chunk(struct pt_regs *ctx, struct ssl_inf
|
||||
chunk->len = countBytes;
|
||||
chunk->fd = info->fd;
|
||||
|
||||
add_address_to_chunk(chunk, id, chunk->fd);
|
||||
add_address_to_chunk(ctx, chunk, id, chunk->fd);
|
||||
send_chunk(ctx, info->buffer, id, chunk);
|
||||
}
|
||||
|
||||
static __always_inline void ssl_uprobe(void* ssl, void* buffer, int num, struct bpf_map_def* map_fd, size_t *count_ptr) {
|
||||
static __always_inline void ssl_uprobe(struct pt_regs *ctx, void* ssl, void* buffer, int num, struct bpf_map_def* map_fd, size_t *count_ptr) {
|
||||
__u64 id = bpf_get_current_pid_tgid();
|
||||
|
||||
if (!should_tap(id >> 32)) {
|
||||
@ -166,8 +164,7 @@ static __always_inline void ssl_uprobe(void* ssl, void* buffer, int num, struct
|
||||
long err = bpf_probe_read(&info, sizeof(struct ssl_info), infoPtr);
|
||||
|
||||
if (err != 0) {
|
||||
char msg[] = "Error reading old ssl context (id: %ld) (err: %ld)";
|
||||
bpf_trace_printk(msg, sizeof(msg), id, err);
|
||||
log_error(ctx, LOG_ERROR_READING_SSL_CONTEXT, id, err, ORIGIN_SSL_UPROBE_CODE);
|
||||
}
|
||||
|
||||
if ((bpf_ktime_get_ns() - info.created_at_nano) > SSL_INFO_MAX_TTL_NANO) {
|
||||
@ -184,8 +181,7 @@ static __always_inline void ssl_uprobe(void* ssl, void* buffer, int num, struct
|
||||
long err = bpf_map_update_elem(map_fd, &id, &info, BPF_ANY);
|
||||
|
||||
if (err != 0) {
|
||||
char msg[] = "Error putting ssl context (id: %ld) (err: %ld)";
|
||||
bpf_trace_printk(msg, sizeof(msg), id, err);
|
||||
log_error(ctx, LOG_ERROR_PUTTING_SSL_CONTEXT, id, err, 0l);
|
||||
}
|
||||
}
|
||||
|
||||
@ -199,8 +195,7 @@ static __always_inline void ssl_uretprobe(struct pt_regs *ctx, struct bpf_map_de
|
||||
struct ssl_info *infoPtr = bpf_map_lookup_elem(map_fd, &id);
|
||||
|
||||
if (infoPtr == NULL) {
|
||||
char msg[] = "Error getting ssl context info (id: %ld)";
|
||||
bpf_trace_printk(msg, sizeof(msg), id);
|
||||
log_error(ctx, LOG_ERROR_GETTING_SSL_CONTEXT, id, 0l, 0l);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -220,14 +215,12 @@ static __always_inline void ssl_uretprobe(struct pt_regs *ctx, struct bpf_map_de
|
||||
// bpf_map_delete_elem(map_fd, &id);
|
||||
|
||||
if (err != 0) {
|
||||
char msg[] = "Error reading ssl context (id: %ld) (err: %ld)";
|
||||
bpf_trace_printk(msg, sizeof(msg), id, err);
|
||||
log_error(ctx, LOG_ERROR_READING_SSL_CONTEXT, id, err, ORIGIN_SSL_URETPROBE_CODE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (info.fd == -1) {
|
||||
char msg[] = "File descriptor is missing from ssl info (id: %ld)";
|
||||
bpf_trace_printk(msg, sizeof(msg), id);
|
||||
log_error(ctx, LOG_ERROR_MISSING_FILE_DESCRIPTOR, id, 0l, 0l);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -236,7 +229,7 @@ static __always_inline void ssl_uretprobe(struct pt_regs *ctx, struct bpf_map_de
|
||||
|
||||
SEC("uprobe/ssl_write")
|
||||
void BPF_KPROBE(ssl_write, void* ssl, void* buffer, int num) {
|
||||
ssl_uprobe(ssl, buffer, num, &ssl_write_context, 0);
|
||||
ssl_uprobe(ctx, ssl, buffer, num, &ssl_write_context, 0);
|
||||
}
|
||||
|
||||
SEC("uretprobe/ssl_write")
|
||||
@ -246,7 +239,7 @@ void BPF_KPROBE(ssl_ret_write) {
|
||||
|
||||
SEC("uprobe/ssl_read")
|
||||
void BPF_KPROBE(ssl_read, void* ssl, void* buffer, int num) {
|
||||
ssl_uprobe(ssl, buffer, num, &ssl_read_context, 0);
|
||||
ssl_uprobe(ctx, ssl, buffer, num, &ssl_read_context, 0);
|
||||
}
|
||||
|
||||
SEC("uretprobe/ssl_read")
|
||||
@ -256,7 +249,7 @@ void BPF_KPROBE(ssl_ret_read) {
|
||||
|
||||
SEC("uprobe/ssl_write_ex")
|
||||
void BPF_KPROBE(ssl_write_ex, void* ssl, void* buffer, size_t num, size_t *written) {
|
||||
ssl_uprobe(ssl, buffer, num, &ssl_write_context, written);
|
||||
ssl_uprobe(ctx, ssl, buffer, num, &ssl_write_context, written);
|
||||
}
|
||||
|
||||
SEC("uretprobe/ssl_write_ex")
|
||||
@ -266,7 +259,7 @@ void BPF_KPROBE(ssl_ret_write_ex) {
|
||||
|
||||
SEC("uprobe/ssl_read_ex")
|
||||
void BPF_KPROBE(ssl_read_ex, void* ssl, void* buffer, size_t num, size_t *readbytes) {
|
||||
ssl_uprobe(ssl, buffer, num, &ssl_read_context, readbytes);
|
||||
ssl_uprobe(ctx, ssl, buffer, num, &ssl_read_context, readbytes);
|
||||
}
|
||||
|
||||
SEC("uretprobe/ssl_read_ex")
|
||||
|
@ -7,6 +7,8 @@ Copyright (C) UP9 Inc.
|
||||
#include "include/headers.h"
|
||||
#include "include/util.h"
|
||||
#include "include/maps.h"
|
||||
#include "include/log.h"
|
||||
#include "include/logger_messages.h"
|
||||
#include "include/pids.h"
|
||||
|
||||
// To avoid multiple .o files
|
||||
|
116
tap/tlstapper/bpf_logger.go
Normal file
116
tap/tlstapper/bpf_logger.go
Normal file
@ -0,0 +1,116 @@
|
||||
package tlstapper
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"strings"
|
||||
|
||||
"github.com/cilium/ebpf/perf"
|
||||
"github.com/go-errors/errors"
|
||||
"github.com/up9inc/mizu/shared/logger"
|
||||
)
|
||||
|
||||
const logPrefix = "[bpf] "
|
||||
|
||||
// The same consts defined in log.h
|
||||
//
|
||||
const logLevelError = 0
|
||||
const logLevelInfo = 1
|
||||
const logLevelDebug = 2
|
||||
|
||||
type logMessage struct {
|
||||
Level uint32
|
||||
MessageCode uint32
|
||||
Arg1 uint64
|
||||
Arg2 uint64
|
||||
Arg3 uint64
|
||||
}
|
||||
|
||||
type bpfLogger struct {
|
||||
logReader *perf.Reader
|
||||
}
|
||||
|
||||
func newBpfLogger() *bpfLogger {
|
||||
return &bpfLogger{
|
||||
logReader: nil,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *bpfLogger) init(bpfObjects *tlsTapperObjects, bufferSize int) error {
|
||||
var err error
|
||||
|
||||
p.logReader, err = perf.NewReader(bpfObjects.LogBuffer, bufferSize)
|
||||
|
||||
if err != nil {
|
||||
return errors.Wrap(err, 0)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *bpfLogger) close() error {
|
||||
return p.logReader.Close()
|
||||
}
|
||||
|
||||
func (p *bpfLogger) poll() {
|
||||
logger.Log.Infof("Start polling for bpf logs")
|
||||
|
||||
for {
|
||||
record, err := p.logReader.Read()
|
||||
|
||||
if err != nil {
|
||||
if errors.Is(err, perf.ErrClosed) {
|
||||
return
|
||||
}
|
||||
|
||||
LogError(errors.Errorf("Error reading from bpf logger perf buffer, aboring logger! %w", err))
|
||||
return
|
||||
}
|
||||
|
||||
if record.LostSamples != 0 {
|
||||
logger.Log.Infof("Log buffer is full, dropped %d logs", record.LostSamples)
|
||||
continue
|
||||
}
|
||||
|
||||
buffer := bytes.NewReader(record.RawSample)
|
||||
|
||||
var log logMessage
|
||||
|
||||
if err := binary.Read(buffer, binary.LittleEndian, &log); err != nil {
|
||||
LogError(errors.Errorf("Error parsing log %v", err))
|
||||
continue
|
||||
}
|
||||
|
||||
p.log(&log)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *bpfLogger) log(log *logMessage) {
|
||||
if int(log.MessageCode) >= len(bpfLogMessages) {
|
||||
logger.Log.Errorf("Unknown message code from bpf logger %d", log.MessageCode)
|
||||
return
|
||||
}
|
||||
|
||||
format := bpfLogMessages[log.MessageCode]
|
||||
tokensCount := strings.Count(format, "%")
|
||||
|
||||
if tokensCount == 0 {
|
||||
p.logLevel(log.Level, format)
|
||||
} else if tokensCount == 1 {
|
||||
p.logLevel(log.Level, format, log.Arg1)
|
||||
} else if tokensCount == 2 {
|
||||
p.logLevel(log.Level, format, log.Arg1, log.Arg2)
|
||||
} else if tokensCount == 3 {
|
||||
p.logLevel(log.Level, format, log.Arg1, log.Arg2, log.Arg3)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *bpfLogger) logLevel(level uint32, format string, args ...interface{}) {
|
||||
if level == logLevelError {
|
||||
logger.Log.Errorf(logPrefix+format, args...)
|
||||
} else if level == logLevelInfo {
|
||||
logger.Log.Infof(logPrefix+format, args...)
|
||||
} else if level == logLevelDebug {
|
||||
logger.Log.Debugf(logPrefix+format, args...)
|
||||
}
|
||||
}
|
25
tap/tlstapper/bpf_logger_messages.go
Normal file
25
tap/tlstapper/bpf_logger_messages.go
Normal file
@ -0,0 +1,25 @@
|
||||
package tlstapper
|
||||
|
||||
// Must be synced with logger_messages.h
|
||||
//
|
||||
var bpfLogMessages = []string {
|
||||
/*0000*/ "[%d] Unable to read bytes count from _ex methods [err: %d]",
|
||||
/*0001*/ "[%d] Unable to read ipv4 address [err: %d]",
|
||||
/*0002*/ "[%d] Unable to read ssl buffer [err: %d]",
|
||||
/*0003*/ "[%d] Buffer is too big [size: %d]",
|
||||
/*0004*/ "[%d] Unable to allocate chunk in bpf heap",
|
||||
/*0005*/ "[%d] Unable to read ssl context [err: %d] [origin: %d]",
|
||||
/*0006*/ "[%d] Unable to put ssl context [err: %d]",
|
||||
/*0007*/ "[%d] Unable to get ssl context",
|
||||
/*0008*/ "[%d] File descriptor is missing for tls chunk",
|
||||
/*0009*/ "[%d] Unable to put file descriptor [err: %d] [origin: %d]",
|
||||
/*0010*/ "[%d] Unable to put accept info [err: %d]",
|
||||
/*0011*/ "[%d] Unable to get accept info",
|
||||
/*0012*/ "[%d] Unable to read accept info [err: %d]",
|
||||
/*0013*/ "[%d] Unable to put file descriptor to address mapping [err: %d] [origin: %d]",
|
||||
/*0014*/ "[%d] Unable to put connect info [err: %d]",
|
||||
/*0015*/ "[%d] Unable to get connect info",
|
||||
/*0016*/ "[%d] Unable to read connect info [err: %d]",
|
||||
|
||||
}
|
||||
|
@ -8,6 +8,8 @@ import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
const GLOABL_TAP_PID = 0
|
||||
|
||||
//go:generate go run github.com/cilium/ebpf/cmd/bpf2go tlsTapper bpf/tls_tapper.c -- -O2 -g -D__TARGET_ARCH_x86
|
||||
|
||||
type TlsTapper struct {
|
||||
@ -15,11 +17,12 @@ type TlsTapper struct {
|
||||
syscallHooks syscallHooks
|
||||
sslHooksStructs []sslHooks
|
||||
poller *tlsPoller
|
||||
bpfLogger *bpfLogger
|
||||
registeredPids sync.Map
|
||||
}
|
||||
|
||||
func (t *TlsTapper) Init(bufferSize int, procfs string, extension *api.Extension) error {
|
||||
logger.Log.Infof("Initializing tls tapper (bufferSize: %v)", bufferSize)
|
||||
func (t *TlsTapper) Init(chunksBufferSize int, logBufferSize int, procfs string, extension *api.Extension) error {
|
||||
logger.Log.Infof("Initializing tls tapper (chunksSize: %d) (logSize: %d)", chunksBufferSize, logBufferSize)
|
||||
|
||||
if err := setupRLimit(); err != nil {
|
||||
return err
|
||||
@ -37,16 +40,25 @@ func (t *TlsTapper) Init(bufferSize int, procfs string, extension *api.Extension
|
||||
|
||||
t.sslHooksStructs = make([]sslHooks, 0)
|
||||
|
||||
t.bpfLogger = newBpfLogger()
|
||||
if err := t.bpfLogger.init(&t.bpfObjects, logBufferSize); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
t.poller = newTlsPoller(t, extension, procfs)
|
||||
return t.poller.init(&t.bpfObjects, bufferSize)
|
||||
return t.poller.init(&t.bpfObjects, chunksBufferSize)
|
||||
}
|
||||
|
||||
func (t *TlsTapper) Poll(emitter api.Emitter, options *api.TrafficFilteringOptions) {
|
||||
t.poller.poll(emitter, options)
|
||||
}
|
||||
|
||||
func (t *TlsTapper) PollForLogging() {
|
||||
t.bpfLogger.poll()
|
||||
}
|
||||
|
||||
func (t *TlsTapper) GlobalTap(sslLibrary string) error {
|
||||
return t.tapPid(0, sslLibrary)
|
||||
return t.tapPid(GLOABL_TAP_PID, sslLibrary)
|
||||
}
|
||||
|
||||
func (t *TlsTapper) AddPid(procfs string, pid uint32) error {
|
||||
@ -74,7 +86,12 @@ func (t *TlsTapper) RemovePid(pid uint32) error {
|
||||
|
||||
func (t *TlsTapper) ClearPids() {
|
||||
t.registeredPids.Range(func(key, v interface{}) bool {
|
||||
if err := t.RemovePid(key.(uint32)); err != nil {
|
||||
pid := key.(uint32)
|
||||
if pid == GLOABL_TAP_PID {
|
||||
return true
|
||||
}
|
||||
|
||||
if err := t.RemovePid(pid); err != nil {
|
||||
LogError(err)
|
||||
}
|
||||
t.registeredPids.Delete(key)
|
||||
@ -95,6 +112,10 @@ func (t *TlsTapper) Close() []error {
|
||||
errors = append(errors, sslHooks.close()...)
|
||||
}
|
||||
|
||||
if err := t.bpfLogger.close(); err != nil {
|
||||
errors = append(errors, err)
|
||||
}
|
||||
|
||||
if err := t.poller.close(); err != nil {
|
||||
errors = append(errors, err)
|
||||
}
|
||||
|
@ -78,6 +78,7 @@ type tlsTapperMapSpecs struct {
|
||||
ConnectSyscallInfo *ebpf.MapSpec `ebpf:"connect_syscall_info"`
|
||||
FileDescriptorToIpv4 *ebpf.MapSpec `ebpf:"file_descriptor_to_ipv4"`
|
||||
Heap *ebpf.MapSpec `ebpf:"heap"`
|
||||
LogBuffer *ebpf.MapSpec `ebpf:"log_buffer"`
|
||||
PidsMap *ebpf.MapSpec `ebpf:"pids_map"`
|
||||
SslReadContext *ebpf.MapSpec `ebpf:"ssl_read_context"`
|
||||
SslWriteContext *ebpf.MapSpec `ebpf:"ssl_write_context"`
|
||||
@ -107,6 +108,7 @@ type tlsTapperMaps struct {
|
||||
ConnectSyscallInfo *ebpf.Map `ebpf:"connect_syscall_info"`
|
||||
FileDescriptorToIpv4 *ebpf.Map `ebpf:"file_descriptor_to_ipv4"`
|
||||
Heap *ebpf.Map `ebpf:"heap"`
|
||||
LogBuffer *ebpf.Map `ebpf:"log_buffer"`
|
||||
PidsMap *ebpf.Map `ebpf:"pids_map"`
|
||||
SslReadContext *ebpf.Map `ebpf:"ssl_read_context"`
|
||||
SslWriteContext *ebpf.Map `ebpf:"ssl_write_context"`
|
||||
@ -119,6 +121,7 @@ func (m *tlsTapperMaps) Close() error {
|
||||
m.ConnectSyscallInfo,
|
||||
m.FileDescriptorToIpv4,
|
||||
m.Heap,
|
||||
m.LogBuffer,
|
||||
m.PidsMap,
|
||||
m.SslReadContext,
|
||||
m.SslWriteContext,
|
||||
|
Binary file not shown.
@ -78,6 +78,7 @@ type tlsTapperMapSpecs struct {
|
||||
ConnectSyscallInfo *ebpf.MapSpec `ebpf:"connect_syscall_info"`
|
||||
FileDescriptorToIpv4 *ebpf.MapSpec `ebpf:"file_descriptor_to_ipv4"`
|
||||
Heap *ebpf.MapSpec `ebpf:"heap"`
|
||||
LogBuffer *ebpf.MapSpec `ebpf:"log_buffer"`
|
||||
PidsMap *ebpf.MapSpec `ebpf:"pids_map"`
|
||||
SslReadContext *ebpf.MapSpec `ebpf:"ssl_read_context"`
|
||||
SslWriteContext *ebpf.MapSpec `ebpf:"ssl_write_context"`
|
||||
@ -107,6 +108,7 @@ type tlsTapperMaps struct {
|
||||
ConnectSyscallInfo *ebpf.Map `ebpf:"connect_syscall_info"`
|
||||
FileDescriptorToIpv4 *ebpf.Map `ebpf:"file_descriptor_to_ipv4"`
|
||||
Heap *ebpf.Map `ebpf:"heap"`
|
||||
LogBuffer *ebpf.Map `ebpf:"log_buffer"`
|
||||
PidsMap *ebpf.Map `ebpf:"pids_map"`
|
||||
SslReadContext *ebpf.Map `ebpf:"ssl_read_context"`
|
||||
SslWriteContext *ebpf.Map `ebpf:"ssl_write_context"`
|
||||
@ -119,6 +121,7 @@ func (m *tlsTapperMaps) Close() error {
|
||||
m.ConnectSyscallInfo,
|
||||
m.FileDescriptorToIpv4,
|
||||
m.Heap,
|
||||
m.LogBuffer,
|
||||
m.PidsMap,
|
||||
m.SslReadContext,
|
||||
m.SslWriteContext,
|
||||
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user