From f286ecb5999df44f517a2cd4e0175597049d9ab3 Mon Sep 17 00:00:00 2001 From: Andrea Terzolo Date: Mon, 24 Jun 2024 09:13:42 +0200 Subject: [PATCH] fix(libpman): avoid truncated verifier logs 4096 bytes are not enough for long verifier logs, we need to use the same dimension provided by libbpf (UINT32_MAX >> 8) Signed-off-by: Andrea Terzolo --- userspace/libpman/src/configuration.c | 27 ++++++++++++++++++++++++--- userspace/libpman/src/lifecycle.c | 7 +++++++ userspace/libpman/src/state.h | 6 +++++- 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/userspace/libpman/src/configuration.c b/userspace/libpman/src/configuration.c index 223618bcb2..5fae1505d1 100644 --- a/userspace/libpman/src/configuration.c +++ b/userspace/libpman/src/configuration.c @@ -44,13 +44,23 @@ static int libbpf_print(enum libbpf_print_level level, const char* format, va_li if(g_state.log_fn == NULL) return vfprintf(stderr, format, args); - char buf[4096]; - int rc = vsnprintf(buf, sizeof(buf), format, args); + // This should be already allocated by the caller, but if for some reason libbpf wants to log again after initialization we create a smaller buffer. + // We need a big buffer only for verifier logs at initialization time. + if(g_state.log_buf == NULL) + { + g_state.log_buf_size = 0; + // this will be freed when the global state is destroyed. + g_state.log_buf = calloc(1, BPF_LOG_SMALL_BUF_SIZE); + if(g_state.log_buf == NULL) + return -ENOMEM; + g_state.log_buf_size = BPF_LOG_SMALL_BUF_SIZE; + } + int rc = vsnprintf(g_state.log_buf, g_state.log_buf_size, format, args); if(rc < 0) return rc; // don't need a component name for libbpf, it will prepend "libbpf: " to logs for us - g_state.log_fn(NULL, buf, sev); + g_state.log_fn(NULL, g_state.log_buf, sev); return rc; } @@ -73,6 +83,12 @@ void pman_clear_state() g_state.n_attached_progs = 0; g_state.stats = NULL; g_state.log_fn = NULL; + if(g_state.log_buf) + { + free(g_state.log_buf); + } + g_state.log_buf = NULL; + g_state.log_buf_size = 0; } int pman_init_state(falcosecurity_log_fn log_fn, unsigned long buf_bytes_dim, uint16_t cpus_for_each_buffer, @@ -88,6 +104,11 @@ int pman_init_state(falcosecurity_log_fn log_fn, unsigned long buf_bytes_dim, ui /* Set libbpf logging. */ g_state.log_fn = log_fn; + // we allocate a big buffer for verifier logs we will free it after initialization. + g_state.log_buf = calloc(1, BPF_LOG_BIG_BUF_SIZE); + if(g_state.log_buf == NULL) + return -ENOMEM; + g_state.log_buf_size = BPF_LOG_BIG_BUF_SIZE; libbpf_set_print(libbpf_print); /* Bump rlimit in any case. We need to do that because some kernels backport diff --git a/userspace/libpman/src/lifecycle.c b/userspace/libpman/src/lifecycle.c index f08d2fc400..f811612deb 100644 --- a/userspace/libpman/src/lifecycle.c +++ b/userspace/libpman/src/lifecycle.c @@ -70,6 +70,13 @@ int pman_load_probe() return errno; } pman_save_attached_progs(); + // Programs are loaded so we passed the verifier we can free the 16 MB + if(g_state.log_buf) + { + free(g_state.log_buf); + g_state.log_buf = NULL; + g_state.log_buf_size = 0; + } return 0; } diff --git a/userspace/libpman/src/state.h b/userspace/libpman/src/state.h index 15c8da58a2..ffd116e8bd 100644 --- a/userspace/libpman/src/state.h +++ b/userspace/libpman/src/state.h @@ -32,6 +32,9 @@ limitations under the License. /* Pay attention this need to be bumped every time we add a new bpf program that is directly attached into the kernel */ #define MODERN_BPF_PROG_ATTACHED_MAX 9 +#define BPF_LOG_BIG_BUF_SIZE (UINT32_MAX >> 8) /* Recommended log buffer size, taken from libbpf. Used for verifier logs */ +#define BPF_LOG_SMALL_BUF_SIZE 8192 /* Used for libbpf non-verifier logs */ + struct metrics_v2; struct internal_state @@ -58,7 +61,8 @@ struct internal_state collect stats */ uint16_t n_attached_progs; /* number of attached progs */ struct metrics_v2* stats; /* array of stats collected by libpman */ - + char* log_buf; /* buffer used to store logs before sending them to the log_fn */ + size_t log_buf_size; /* size of the log buffer */ falcosecurity_log_fn log_fn; };