From 7c0d3fe9e7a09e01cb33fea61ff45632971a0f27 Mon Sep 17 00:00:00 2001 From: Andrea Terzolo Date: Tue, 26 Nov 2024 11:49:36 +0100 Subject: [PATCH 1/5] fix: split sampling logic between enter and exit Signed-off-by: Andrea Terzolo --- .../attached/dispatchers/syscall_enter.bpf.c | 35 ++++++++++++-- .../attached/dispatchers/syscall_exit.bpf.c | 48 ++++++++++++++++++- .../events/custom_logic/drop.bpf.c | 10 +--- 3 files changed, 79 insertions(+), 14 deletions(-) diff --git a/driver/modern_bpf/programs/attached/dispatchers/syscall_enter.bpf.c b/driver/modern_bpf/programs/attached/dispatchers/syscall_enter.bpf.c index 0bc17f1702..d60dafd8be 100644 --- a/driver/modern_bpf/programs/attached/dispatchers/syscall_enter.bpf.c +++ b/driver/modern_bpf/programs/attached/dispatchers/syscall_enter.bpf.c @@ -7,13 +7,42 @@ */ #include -#include + +// We don't want to send DROP_E/DROP_X events from the enter tracepoint because it would requires us +// to create a dedicated tail table for the enter. It is enough to send DROP_E/DROP_X events from +// the exit tracepoint. +static __always_inline bool sampling_logic_enter(void* ctx, uint32_t id) { + /* If dropping mode is not enabled we don't perform any sampling + * false: means don't drop the syscall + * true: means drop the syscall + */ + if(!maps__get_dropping_mode()) { + return false; + } + + uint8_t sampling_flag = maps__64bit_sampling_syscall_table(id); + + if(sampling_flag == UF_NEVER_DROP) { + return false; + } + + if(sampling_flag == UF_ALWAYS_DROP) { + return true; + } + + // If we are in the sampling period we drop the event + if((bpf_ktime_get_boot_ns() % SECOND_TO_NS) >= (SECOND_TO_NS / maps__get_sampling_ratio())) { + return true; + } + + return false; +} /* From linux tree: /include/trace/events/syscall.h * TP_PROTO(struct pt_regs *regs, long id), */ SEC("tp_btf/sys_enter") -int BPF_PROG(sys_enter, struct pt_regs *regs, long syscall_id) { +int BPF_PROG(sys_enter, struct pt_regs* regs, long syscall_id) { int socketcall_syscall_id = -1; if(bpf_in_ia32_syscall()) { @@ -49,7 +78,7 @@ int BPF_PROG(sys_enter, struct pt_regs *regs, long syscall_id) { return 0; } - if(sampling_logic(ctx, syscall_id)) { + if(sampling_logic_enter(ctx, syscall_id)) { return 0; } diff --git a/driver/modern_bpf/programs/attached/dispatchers/syscall_exit.bpf.c b/driver/modern_bpf/programs/attached/dispatchers/syscall_exit.bpf.c index 9355466f7e..e84042687b 100644 --- a/driver/modern_bpf/programs/attached/dispatchers/syscall_exit.bpf.c +++ b/driver/modern_bpf/programs/attached/dispatchers/syscall_exit.bpf.c @@ -7,9 +7,53 @@ */ #include -#include #include +static __always_inline bool sampling_logic_exit(void *ctx, uint32_t id) { + /* If dropping mode is not enabled we don't perform any sampling + * false: means don't drop the syscall + * true: means drop the syscall + */ + if(!maps__get_dropping_mode()) { + return false; + } + + uint8_t sampling_flag = maps__64bit_sampling_syscall_table(id); + + if(sampling_flag == UF_NEVER_DROP) { + return false; + } + + if(sampling_flag == UF_ALWAYS_DROP) { + return true; + } + + if((bpf_ktime_get_boot_ns() % SECOND_TO_NS) >= (SECOND_TO_NS / maps__get_sampling_ratio())) { + /* If we are starting the dropping phase we need to notify the userspace, otherwise, we + * simply drop our event. + * PLEASE NOTE: this logic is not per-CPU so it is best effort! + */ + if(!maps__get_is_dropping()) { + /* Here we are not sure we can send the drop_e event to userspace + * if the buffer is full, but this is not essential even if we lose + * an iteration we will synchronize again the next time the logic is enabled. + */ + maps__set_is_dropping(true); + bpf_tail_call(ctx, &extra_syscall_calls, T1_DROP_E); + bpf_printk("unable to tail call into 'drop_e' prog"); + } + return true; + } + + if(maps__get_is_dropping()) { + maps__set_is_dropping(false); + bpf_tail_call(ctx, &extra_syscall_calls, T1_DROP_X); + bpf_printk("unable to tail call into 'drop_x' prog"); + } + + return false; +} + #define X86_64_NR_EXECVE 59 #define X86_64_NR_EXECVEAT 322 @@ -63,7 +107,7 @@ int BPF_PROG(sys_exit, struct pt_regs *regs, long ret) { return 0; } - if(sampling_logic(ctx, syscall_id)) { + if(sampling_logic_exit(ctx, syscall_id)) { return 0; } diff --git a/driver/modern_bpf/programs/tail_called/events/custom_logic/drop.bpf.c b/driver/modern_bpf/programs/tail_called/events/custom_logic/drop.bpf.c index ca725ad1be..c15cbe6d90 100644 --- a/driver/modern_bpf/programs/tail_called/events/custom_logic/drop.bpf.c +++ b/driver/modern_bpf/programs/tail_called/events/custom_logic/drop.bpf.c @@ -8,9 +8,7 @@ #include -/*=============================== ENTER EVENT ===========================*/ - -SEC("tp_btf/sys_enter") +SEC("tp_btf/sys_exit") int BPF_PROG(t1_drop_e) { struct ringbuf_struct ringbuf; if(!ringbuf__reserve_space(&ringbuf, DROP_E_SIZE, PPME_DROP_E)) { @@ -29,10 +27,6 @@ int BPF_PROG(t1_drop_e) { return 0; } -/*=============================== ENTER EVENT ===========================*/ - -/*=============================== EXIT EVENT ===========================*/ - SEC("tp_btf/sys_exit") int BPF_PROG(t1_drop_x) { struct ringbuf_struct ringbuf; @@ -51,5 +45,3 @@ int BPF_PROG(t1_drop_x) { ringbuf__submit_event(&ringbuf); return 0; } - -/*=============================== EXIT EVENT ===========================*/ From 40b1fe38ae0ae5aec9b711648e3e4e890f9d17c8 Mon Sep 17 00:00:00 2001 From: Andrea Terzolo Date: Tue, 26 Nov 2024 11:50:27 +0100 Subject: [PATCH 2/5] cleanup: remove an unused header Signed-off-by: Andrea Terzolo --- .../helpers/interfaces/attached_programs.h | 60 ------------------- .../attached/events/page_fault_kernel.bpf.c | 1 - .../attached/events/page_fault_user.bpf.c | 1 - .../attached/events/sched_process_exit.bpf.c | 1 - .../attached/events/sched_switch.bpf.c | 1 - .../attached/events/signal_deliver.bpf.c | 1 - 6 files changed, 65 deletions(-) delete mode 100644 driver/modern_bpf/helpers/interfaces/attached_programs.h diff --git a/driver/modern_bpf/helpers/interfaces/attached_programs.h b/driver/modern_bpf/helpers/interfaces/attached_programs.h deleted file mode 100644 index 77299e1c03..0000000000 --- a/driver/modern_bpf/helpers/interfaces/attached_programs.h +++ /dev/null @@ -1,60 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only OR MIT -/* - * Copyright (C) 2023 The Falco Authors. - * - * This file is dual licensed under either the MIT or GPL 2. See MIT.txt - * or GPL2.txt for full copies of the license. - */ - -#pragma once - -#include - -/* The sampling logic is used by all BPF programs attached to the kernel. - * We treat the syscalls tracepoints in a dedicated way because they could generate - * more than one event (1 for each syscall) for this reason we need a dedicated table. - */ -static __always_inline bool sampling_logic(void* ctx, uint32_t id) { - /* If dropping mode is not enabled we don't perform any sampling - * false: means don't drop the syscall - * true: means drop the syscall - */ - if(!maps__get_dropping_mode()) { - return false; - } - - uint8_t sampling_flag = maps__64bit_sampling_syscall_table(id); - - if(sampling_flag == UF_NEVER_DROP) { - return false; - } - - if(sampling_flag == UF_ALWAYS_DROP) { - return true; - } - - if((bpf_ktime_get_boot_ns() % SECOND_TO_NS) >= (SECOND_TO_NS / maps__get_sampling_ratio())) { - /* If we are starting the dropping phase we need to notify the userspace, otherwise, we - * simply drop our event. - * PLEASE NOTE: this logic is not per-CPU so it is best effort! - */ - if(!maps__get_is_dropping()) { - /* Here we are not sure we can send the drop_e event to userspace - * if the buffer is full, but this is not essential even if we lose - * an iteration we will synchronize again the next time the logic is enabled. - */ - maps__set_is_dropping(true); - bpf_tail_call(ctx, &extra_syscall_calls, T1_DROP_E); - bpf_printk("unable to tail call into 'drop_e' prog"); - } - return true; - } - - if(maps__get_is_dropping()) { - maps__set_is_dropping(false); - bpf_tail_call(ctx, &extra_syscall_calls, T1_DROP_X); - bpf_printk("unable to tail call into 'drop_x' prog"); - } - - return false; -} diff --git a/driver/modern_bpf/programs/attached/events/page_fault_kernel.bpf.c b/driver/modern_bpf/programs/attached/events/page_fault_kernel.bpf.c index 3ce886d22a..5b26d69e22 100644 --- a/driver/modern_bpf/programs/attached/events/page_fault_kernel.bpf.c +++ b/driver/modern_bpf/programs/attached/events/page_fault_kernel.bpf.c @@ -7,7 +7,6 @@ */ #include -#include /* From linux tree: `/arch/x86/include/asm/trace/exceptions.h` * TP_PROTO(unsigned long address, struct pt_regs *regs, diff --git a/driver/modern_bpf/programs/attached/events/page_fault_user.bpf.c b/driver/modern_bpf/programs/attached/events/page_fault_user.bpf.c index 98a3416142..5819b1f2ca 100644 --- a/driver/modern_bpf/programs/attached/events/page_fault_user.bpf.c +++ b/driver/modern_bpf/programs/attached/events/page_fault_user.bpf.c @@ -7,7 +7,6 @@ */ #include -#include /* From linux tree: `/arch/x86/include/asm/trace/exceptions.h` * TP_PROTO(unsigned long address, struct pt_regs *regs, diff --git a/driver/modern_bpf/programs/attached/events/sched_process_exit.bpf.c b/driver/modern_bpf/programs/attached/events/sched_process_exit.bpf.c index 42d6d2f701..6e0728a262 100644 --- a/driver/modern_bpf/programs/attached/events/sched_process_exit.bpf.c +++ b/driver/modern_bpf/programs/attached/events/sched_process_exit.bpf.c @@ -8,7 +8,6 @@ #include #include -#include /* The instruction limit is 1000000, so we shouldn't have issues */ #define MAX_THREADS_GROUPS 30 diff --git a/driver/modern_bpf/programs/attached/events/sched_switch.bpf.c b/driver/modern_bpf/programs/attached/events/sched_switch.bpf.c index a273d7d5ff..a060f4e945 100644 --- a/driver/modern_bpf/programs/attached/events/sched_switch.bpf.c +++ b/driver/modern_bpf/programs/attached/events/sched_switch.bpf.c @@ -7,7 +7,6 @@ */ #include -#include /* From linux tree: /include/linux/events/sched.h * TP_PROTO(bool preempt, struct task_struct *prev, diff --git a/driver/modern_bpf/programs/attached/events/signal_deliver.bpf.c b/driver/modern_bpf/programs/attached/events/signal_deliver.bpf.c index 65c2be8dee..9057d4f054 100644 --- a/driver/modern_bpf/programs/attached/events/signal_deliver.bpf.c +++ b/driver/modern_bpf/programs/attached/events/signal_deliver.bpf.c @@ -7,7 +7,6 @@ */ #include -#include /* From linux tree: `/include/trace/events/signal.h` * TP_PROTO(int sig, struct kernel_siginfo *info, struct k_sigaction *ka) From 07e5ada1ce1703a3e3ec602593cea0011bc90c8b Mon Sep 17 00:00:00 2001 From: Andrea Terzolo Date: Tue, 26 Nov 2024 13:24:13 +0100 Subject: [PATCH 3/5] cleanup: move custom tail calls in sys_exit Signed-off-by: Andrea Terzolo --- .../attached/dispatchers/syscall_exit.bpf.c | 119 +++++++++++++++++- .../events/custom_logic/drop.bpf.c | 47 ------- .../events/custom_logic/hotplug.bpf.c | 61 --------- driver/ppm_events_public.h | 3 - userspace/libpman/src/events_prog_names.h | 3 - 5 files changed, 116 insertions(+), 117 deletions(-) delete mode 100644 driver/modern_bpf/programs/tail_called/events/custom_logic/drop.bpf.c delete mode 100644 driver/modern_bpf/programs/tail_called/events/custom_logic/hotplug.bpf.c diff --git a/driver/modern_bpf/programs/attached/dispatchers/syscall_exit.bpf.c b/driver/modern_bpf/programs/attached/dispatchers/syscall_exit.bpf.c index e84042687b..22356436f5 100644 --- a/driver/modern_bpf/programs/attached/dispatchers/syscall_exit.bpf.c +++ b/driver/modern_bpf/programs/attached/dispatchers/syscall_exit.bpf.c @@ -8,6 +8,119 @@ #include #include +#include + +SEC("tp_btf/sys_exit") +int BPF_PROG(t_hotplug) { + /* We assume that the ring buffer for CPU 0 is always there so we send the + * HOT-PLUG event through this buffer. + */ + uint32_t cpu_0 = 0; + struct ringbuf_map *rb = bpf_map_lookup_elem(&ringbuf_maps, &cpu_0); + if(!rb) { + bpf_printk("unable to obtain the ring buffer for CPU 0"); + return 0; + } + + struct counter_map *counter = bpf_map_lookup_elem(&counter_maps, &cpu_0); + if(!counter) { + bpf_printk("unable to obtain the counter map for CPU 0"); + return 0; + } + + /* This counts the event seen by the drivers even if they are dropped because the buffer is + * full. */ + counter->n_evts++; + + /* If we are not able to reserve space we stop here + * the event collection. + */ + struct ringbuf_struct ringbuf; + ringbuf.reserved_event_size = HOTPLUG_E_SIZE; + ringbuf.event_type = PPME_CPU_HOTPLUG_E; + ringbuf.data = bpf_ringbuf_reserve(rb, HOTPLUG_E_SIZE, 0); + if(!ringbuf.data) { + counter->n_drops_buffer++; + return 0; + } + + ringbuf__store_event_header(&ringbuf); + + /*=============================== COLLECT PARAMETERS ===========================*/ + + /* Parameter 1: cpu (type: PT_UINT32) */ + uint32_t current_cpu_id = (uint32_t)bpf_get_smp_processor_id(); + ringbuf__store_u32(&ringbuf, current_cpu_id); + + /* Parameter 2: action (type: PT_UINT32) */ + /* Right now we don't have actions we always send 0 */ + ringbuf__store_u32(&ringbuf, 0); + + /*=============================== COLLECT PARAMETERS ===========================*/ + + ringbuf__submit_event(&ringbuf); + return 0; +} + +SEC("tp_btf/sys_exit") +int BPF_PROG(t_drop_e) { + struct ringbuf_struct ringbuf; + if(!ringbuf__reserve_space(&ringbuf, DROP_E_SIZE, PPME_DROP_E)) { + return 0; + } + + ringbuf__store_event_header(&ringbuf); + + /*=============================== COLLECT PARAMETERS ===========================*/ + + ringbuf__store_u32(&ringbuf, maps__get_sampling_ratio()); + + /*=============================== COLLECT PARAMETERS ===========================*/ + + ringbuf__submit_event(&ringbuf); + return 0; +} + +SEC("tp_btf/sys_exit") +int BPF_PROG(t_drop_x) { + struct ringbuf_struct ringbuf; + if(!ringbuf__reserve_space(&ringbuf, DROP_X_SIZE, PPME_DROP_X)) { + return 0; + } + + ringbuf__store_event_header(&ringbuf); + + /*=============================== COLLECT PARAMETERS ===========================*/ + + ringbuf__store_u32(&ringbuf, maps__get_sampling_ratio()); + + /*=============================== COLLECT PARAMETERS ===========================*/ + + ringbuf__submit_event(&ringbuf); + return 0; +} + +enum custom_sys_exit_logic_codes { + T_HOTPLUG, + T_DROP_E, + T_DROP_X, + // add more codes here. + T_CUSTOM_MAX, +}; + +struct { + __uint(type, BPF_MAP_TYPE_PROG_ARRAY); + __uint(max_entries, T_CUSTOM_MAX); + __uint(key_size, sizeof(__u32)); + __array(values, int(void *)); +} custom_sys_exit_calls SEC(".maps") = { + .values = + { + [T_HOTPLUG] = (void *)&t_hotplug, + [T_DROP_E] = (void *)&t_drop_e, + [T_DROP_X] = (void *)&t_drop_x, + }, +}; static __always_inline bool sampling_logic_exit(void *ctx, uint32_t id) { /* If dropping mode is not enabled we don't perform any sampling @@ -39,7 +152,7 @@ static __always_inline bool sampling_logic_exit(void *ctx, uint32_t id) { * an iteration we will synchronize again the next time the logic is enabled. */ maps__set_is_dropping(true); - bpf_tail_call(ctx, &extra_syscall_calls, T1_DROP_E); + bpf_tail_call(ctx, &custom_sys_exit_calls, T_DROP_E); bpf_printk("unable to tail call into 'drop_e' prog"); } return true; @@ -47,7 +160,7 @@ static __always_inline bool sampling_logic_exit(void *ctx, uint32_t id) { if(maps__get_is_dropping()) { maps__set_is_dropping(false); - bpf_tail_call(ctx, &extra_syscall_calls, T1_DROP_X); + bpf_tail_call(ctx, &custom_sys_exit_calls, T_DROP_X); bpf_printk("unable to tail call into 'drop_x' prog"); } @@ -120,7 +233,7 @@ int BPF_PROG(sys_exit, struct pt_regs *regs, long ret) { // we change our architecture we may need to update this logic. struct ringbuf_map *rb = maps__get_ringbuf_map(); if(!rb) { - bpf_tail_call(ctx, &extra_syscall_calls, T1_HOTPLUG_E); + bpf_tail_call(ctx, &custom_sys_exit_calls, T_HOTPLUG); bpf_printk("failed to tail call into the 'hotplug' prog"); return 0; } diff --git a/driver/modern_bpf/programs/tail_called/events/custom_logic/drop.bpf.c b/driver/modern_bpf/programs/tail_called/events/custom_logic/drop.bpf.c deleted file mode 100644 index c15cbe6d90..0000000000 --- a/driver/modern_bpf/programs/tail_called/events/custom_logic/drop.bpf.c +++ /dev/null @@ -1,47 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only OR MIT -/* - * Copyright (C) 2023 The Falco Authors. - * - * This file is dual licensed under either the MIT or GPL 2. See MIT.txt - * or GPL2.txt for full copies of the license. - */ - -#include - -SEC("tp_btf/sys_exit") -int BPF_PROG(t1_drop_e) { - struct ringbuf_struct ringbuf; - if(!ringbuf__reserve_space(&ringbuf, DROP_E_SIZE, PPME_DROP_E)) { - return 0; - } - - ringbuf__store_event_header(&ringbuf); - - /*=============================== COLLECT PARAMETERS ===========================*/ - - ringbuf__store_u32(&ringbuf, maps__get_sampling_ratio()); - - /*=============================== COLLECT PARAMETERS ===========================*/ - - ringbuf__submit_event(&ringbuf); - return 0; -} - -SEC("tp_btf/sys_exit") -int BPF_PROG(t1_drop_x) { - struct ringbuf_struct ringbuf; - if(!ringbuf__reserve_space(&ringbuf, DROP_X_SIZE, PPME_DROP_X)) { - return 0; - } - - ringbuf__store_event_header(&ringbuf); - - /*=============================== COLLECT PARAMETERS ===========================*/ - - ringbuf__store_u32(&ringbuf, maps__get_sampling_ratio()); - - /*=============================== COLLECT PARAMETERS ===========================*/ - - ringbuf__submit_event(&ringbuf); - return 0; -} diff --git a/driver/modern_bpf/programs/tail_called/events/custom_logic/hotplug.bpf.c b/driver/modern_bpf/programs/tail_called/events/custom_logic/hotplug.bpf.c deleted file mode 100644 index ce969ed8e3..0000000000 --- a/driver/modern_bpf/programs/tail_called/events/custom_logic/hotplug.bpf.c +++ /dev/null @@ -1,61 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only OR MIT -/* - * Copyright (C) 2023 The Falco Authors. - * - * This file is dual licensed under either the MIT or GPL 2. See MIT.txt - * or GPL2.txt for full copies of the license. - */ - -#include - -SEC("tp_btf/sys_exit") -int BPF_PROG(t1_hotplug_e) { - /* We assume that the ring buffer for CPU 0 is always there so we send the - * HOT-PLUG event through this buffer. - */ - uint32_t cpu_0 = 0; - struct ringbuf_map *rb = bpf_map_lookup_elem(&ringbuf_maps, &cpu_0); - if(!rb) { - bpf_printk("unable to obtain the ring buffer for CPU 0"); - return 0; - } - - struct counter_map *counter = bpf_map_lookup_elem(&counter_maps, &cpu_0); - if(!counter) { - bpf_printk("unable to obtain the counter map for CPU 0"); - return 0; - } - - /* This counts the event seen by the drivers even if they are dropped because the buffer is - * full. */ - counter->n_evts++; - - /* If we are not able to reserve space we stop here - * the event collection. - */ - struct ringbuf_struct ringbuf; - ringbuf.reserved_event_size = HOTPLUG_E_SIZE; - ringbuf.event_type = PPME_CPU_HOTPLUG_E; - ringbuf.data = bpf_ringbuf_reserve(rb, HOTPLUG_E_SIZE, 0); - if(!ringbuf.data) { - counter->n_drops_buffer++; - return 0; - } - - ringbuf__store_event_header(&ringbuf); - - /*=============================== COLLECT PARAMETERS ===========================*/ - - /* Parameter 1: cpu (type: PT_UINT32) */ - uint32_t current_cpu_id = (uint32_t)bpf_get_smp_processor_id(); - ringbuf__store_u32(&ringbuf, current_cpu_id); - - /* Parameter 2: action (type: PT_UINT32) */ - /* Right now we don't have actions we always send 0 */ - ringbuf__store_u32(&ringbuf, 0); - - /*=============================== COLLECT PARAMETERS ===========================*/ - - ringbuf__submit_event(&ringbuf); - return 0; -} diff --git a/driver/ppm_events_public.h b/driver/ppm_events_public.h index 2a6d9fca43..86728d4196 100644 --- a/driver/ppm_events_public.h +++ b/driver/ppm_events_public.h @@ -1536,9 +1536,6 @@ enum extra_syscall_codes { T2_CLONE3_X, T2_FORK_X, T2_VFORK_X, - T1_DROP_E, - T1_DROP_X, - T1_HOTPLUG_E, T1_OPEN_BY_HANDLE_AT_X, T2_EXECVE_X, T2_EXECVEAT_X, diff --git a/userspace/libpman/src/events_prog_names.h b/userspace/libpman/src/events_prog_names.h index d896f606b9..688130ea41 100644 --- a/userspace/libpman/src/events_prog_names.h +++ b/userspace/libpman/src/events_prog_names.h @@ -353,9 +353,6 @@ static const char* extra_event_prog_names[TAIL_EXTRA_EVENT_PROG_MAX] = { [T2_CLONE3_X] = "t2_clone3_x", [T2_FORK_X] = "t2_fork_x", [T2_VFORK_X] = "t2_vfork_x", - [T1_DROP_E] = "t1_drop_e", - [T1_DROP_X] = "t1_drop_x", - [T1_HOTPLUG_E] = "t1_hotplug_e", [T1_OPEN_BY_HANDLE_AT_X] = "t1_open_by_handle_at_x", [T2_EXECVE_X] = "t2_execve_x", [T2_EXECVEAT_X] = "t2_execveat_x", From 2783b8ae5cf5ddd51c10a2bd494576320b06fc20 Mon Sep 17 00:00:00 2001 From: Andrea Terzolo Date: Tue, 26 Nov 2024 13:52:27 +0100 Subject: [PATCH 4/5] cleanup: rename some methods/maps Signed-off-by: Andrea Terzolo --- driver/modern_bpf/maps/maps.h | 13 +++++------- .../syscall_dispatched_events/clone.bpf.c | 4 ++-- .../syscall_dispatched_events/clone3.bpf.c | 4 ++-- .../syscall_dispatched_events/execve.bpf.c | 4 ++-- .../syscall_dispatched_events/execveat.bpf.c | 4 ++-- .../syscall_dispatched_events/fork.bpf.c | 4 ++-- .../open_by_handle_at.bpf.c | 2 +- .../syscall_dispatched_events/vfork.bpf.c | 4 ++-- driver/ppm_events_public.h | 8 +++---- userspace/libpman/include/libpman.h | 11 +++++----- userspace/libpman/src/events_prog_names.h | 4 ++-- userspace/libpman/src/maps.c | 21 ++++++++++--------- 12 files changed, 39 insertions(+), 44 deletions(-) diff --git a/driver/modern_bpf/maps/maps.h b/driver/modern_bpf/maps/maps.h index 59cdb3dd54..850133f41a 100644 --- a/driver/modern_bpf/maps/maps.h +++ b/driver/modern_bpf/maps/maps.h @@ -117,20 +117,17 @@ struct { } syscall_exit_tail_table __weak SEC(".maps"); /** - * @brief This tail table is used when a bpf program needs another program - * to complete its execution flow. This table could be used both by - * programs directly attached in the kernel (like page_faults, - * context_switch, ...) and by syscall_events (like - * ppme_syscall_execveat_x, ...). - * Given a predefined tail-code (`extra_syscall_codes`), it calls + * @brief This tail table is used when a sys exit bpf program needs another program + * to complete its execution flow. + * Given a predefined tail-code (`sys_exit_extra_code`), it calls * the right bpf program. */ struct { __uint(type, BPF_MAP_TYPE_PROG_ARRAY); - __uint(max_entries, TAIL_EXTRA_EVENT_PROG_MAX); + __uint(max_entries, SYS_EXIT_EXTRA_CODE_MAX); __type(key, uint32_t); __type(value, uint32_t); -} extra_syscall_calls __weak SEC(".maps"); +} syscall_exit_extra_tail_table __weak SEC(".maps"); /*=============================== BPF_MAP_TYPE_PROG_ARRAY ===============================*/ diff --git a/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/clone.bpf.c b/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/clone.bpf.c index c38c3f02c3..83b8ec85c2 100644 --- a/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/clone.bpf.c +++ b/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/clone.bpf.c @@ -150,7 +150,7 @@ int BPF_PROG(clone_x, struct pt_regs *regs, long ret) { /* We have to split here the bpf program, otherwise, it is too large * for the verifier (limit 1000000 instructions). */ - bpf_tail_call(ctx, &extra_syscall_calls, T1_CLONE_X); + bpf_tail_call(ctx, &syscall_exit_extra_tail_table, T1_CLONE_X); return 0; } @@ -206,7 +206,7 @@ int BPF_PROG(t1_clone_x, struct pt_regs *regs, long ret) { /* We have to split here the bpf program, otherwise, it is too large * for the verifier (limit 1000000 instructions). */ - bpf_tail_call(ctx, &extra_syscall_calls, T2_CLONE_X); + bpf_tail_call(ctx, &syscall_exit_extra_tail_table, T2_CLONE_X); return 0; } diff --git a/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/clone3.bpf.c b/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/clone3.bpf.c index ac8ba9e41a..fca6d958bd 100644 --- a/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/clone3.bpf.c +++ b/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/clone3.bpf.c @@ -150,7 +150,7 @@ int BPF_PROG(clone3_x, struct pt_regs *regs, long ret) { /* We have to split here the bpf program, otherwise, it is too large * for the verifier (limit 1000000 instructions). */ - bpf_tail_call(ctx, &extra_syscall_calls, T1_CLONE3_X); + bpf_tail_call(ctx, &syscall_exit_extra_tail_table, T1_CLONE3_X); return 0; } @@ -204,7 +204,7 @@ int BPF_PROG(t1_clone3_x, struct pt_regs *regs, long ret) { /* We have to split here the bpf program, otherwise, it is too large * for the verifier (limit 1000000 instructions). */ - bpf_tail_call(ctx, &extra_syscall_calls, T2_CLONE3_X); + bpf_tail_call(ctx, &syscall_exit_extra_tail_table, T2_CLONE3_X); return 0; } diff --git a/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/execve.bpf.c b/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/execve.bpf.c index 22d0ef76f9..870c99215d 100644 --- a/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/execve.bpf.c +++ b/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/execve.bpf.c @@ -155,7 +155,7 @@ int BPF_PROG(execve_x, struct pt_regs *regs, long ret) { /* We have to split here the bpf program, otherwise, it is too large * for the verifier (limit 1000000 instructions). */ - bpf_tail_call(ctx, &extra_syscall_calls, T1_EXECVE_X); + bpf_tail_call(ctx, &syscall_exit_extra_tail_table, T1_EXECVE_X); return 0; } @@ -284,7 +284,7 @@ int BPF_PROG(t1_execve_x, struct pt_regs *regs, long ret) { /*=============================== COLLECT PARAMETERS ===========================*/ - bpf_tail_call(ctx, &extra_syscall_calls, T2_EXECVE_X); + bpf_tail_call(ctx, &syscall_exit_extra_tail_table, T2_EXECVE_X); return 0; } diff --git a/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/execveat.bpf.c b/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/execveat.bpf.c index beed1e9c13..878d3f94f6 100644 --- a/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/execveat.bpf.c +++ b/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/execveat.bpf.c @@ -168,7 +168,7 @@ int BPF_PROG(execveat_x, struct pt_regs *regs, long ret) { /* We have to split here the bpf program, otherwise it is too large * for the verifier (limit 1000000 instructions). */ - bpf_tail_call(ctx, &extra_syscall_calls, T1_EXECVEAT_X); + bpf_tail_call(ctx, &syscall_exit_extra_tail_table, T1_EXECVEAT_X); return 0; } @@ -296,7 +296,7 @@ int BPF_PROG(t1_execveat_x, struct pt_regs *regs, long ret) { /*=============================== COLLECT PARAMETERS ===========================*/ - bpf_tail_call(ctx, &extra_syscall_calls, T2_EXECVEAT_X); + bpf_tail_call(ctx, &syscall_exit_extra_tail_table, T2_EXECVEAT_X); return 0; } diff --git a/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/fork.bpf.c b/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/fork.bpf.c index 983130d87f..a8b2026f0d 100644 --- a/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/fork.bpf.c +++ b/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/fork.bpf.c @@ -152,7 +152,7 @@ int BPF_PROG(fork_x, struct pt_regs *regs, long ret) { /* We have to split here the bpf program, otherwise, it is too large * for the verifier (limit 1000000 instructions). */ - bpf_tail_call(ctx, &extra_syscall_calls, T1_FORK_X); + bpf_tail_call(ctx, &syscall_exit_extra_tail_table, T1_FORK_X); return 0; } @@ -198,7 +198,7 @@ int BPF_PROG(t1_fork_x, struct pt_regs *regs, long ret) { /* We have to split here the bpf program, otherwise, it is too large * for the verifier (limit 1000000 instructions). */ - bpf_tail_call(ctx, &extra_syscall_calls, T2_FORK_X); + bpf_tail_call(ctx, &syscall_exit_extra_tail_table, T2_FORK_X); return 0; } diff --git a/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/open_by_handle_at.bpf.c b/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/open_by_handle_at.bpf.c index 274d84a03b..5bf799808a 100644 --- a/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/open_by_handle_at.bpf.c +++ b/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/open_by_handle_at.bpf.c @@ -60,7 +60,7 @@ int BPF_PROG(open_by_handle_at_x, struct pt_regs *regs, long ret) { /*=============================== COLLECT PARAMETERS ===========================*/ - bpf_tail_call(ctx, &extra_syscall_calls, T1_OPEN_BY_HANDLE_AT_X); + bpf_tail_call(ctx, &syscall_exit_extra_tail_table, T1_OPEN_BY_HANDLE_AT_X); return 0; } diff --git a/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/vfork.bpf.c b/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/vfork.bpf.c index 8ede844bc1..3c73d519b4 100644 --- a/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/vfork.bpf.c +++ b/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/vfork.bpf.c @@ -150,7 +150,7 @@ int BPF_PROG(vfork_x, struct pt_regs *regs, long ret) { /* We have to split here the bpf program, otherwise, it is too large * for the verifier (limit 1000000 instructions). */ - bpf_tail_call(ctx, &extra_syscall_calls, T1_VFORK_X); + bpf_tail_call(ctx, &syscall_exit_extra_tail_table, T1_VFORK_X); return 0; } @@ -196,7 +196,7 @@ int BPF_PROG(t1_vfork_x, struct pt_regs *regs, long ret) { /* We have to split here the bpf program, otherwise, it is too large * for the verifier (limit 1000000 instructions). */ - bpf_tail_call(ctx, &extra_syscall_calls, T2_VFORK_X); + bpf_tail_call(ctx, &syscall_exit_extra_tail_table, T2_VFORK_X); return 0; } diff --git a/driver/ppm_events_public.h b/driver/ppm_events_public.h index 86728d4196..83e06c9d71 100644 --- a/driver/ppm_events_public.h +++ b/driver/ppm_events_public.h @@ -1521,11 +1521,9 @@ typedef enum { * "Tx_" stands for "extra tail call number x for the event after '_'". * For example "T1_EXECVE_X" stands for: * - `T1` = extra tail call number 1. - * - `EXECVE` = name of the syscall for which we need an extra tail call. - * - `X` = means that we need this extra tail call for the exit event, `E` means enter the event. - * + * - `EXECVE_X` = name of the syscall for which we need an extra tail call. */ -enum extra_syscall_codes { +enum sys_exit_extra_code { T1_EXECVE_X, T1_EXECVEAT_X, T1_CLONE_X, @@ -1540,7 +1538,7 @@ enum extra_syscall_codes { T2_EXECVE_X, T2_EXECVEAT_X, // Add new codes here... - TAIL_EXTRA_EVENT_PROG_MAX, + SYS_EXIT_EXTRA_CODE_MAX, }; /* diff --git a/userspace/libpman/include/libpman.h b/userspace/libpman/include/libpman.h index b916bb6164..aa8cc827e8 100644 --- a/userspace/libpman/include/libpman.h +++ b/userspace/libpman/include/libpman.h @@ -396,19 +396,18 @@ uint64_t pman_get_probe_api_ver(void); uint64_t pman_get_probe_schema_ver(void); /** - * @brief Some bpf programs exceed the maximum complexity + * @brief Some sys exit bpf programs exceed the maximum complexity * so they have to tail-call other programs. To do that, they - * need a particular tail table that we call `extra_syscall_calls`. + * need a particular tail table that we call `syscall_exit_extra_tail_table`. * - * -> EXTRA EVENT PROG TAIL TABLE - * extra_syscall_calls(extra_syscall_codes, program_fd). + * syscall_exit_extra_tail_table(sys_exit_extra_code, program_fd). * - * `extra_syscall_codes` is an enum defined in + * `sys_exit_extra_code` is an enum defined in * `/driver/ppm_events_public.h` * * @return `0` on success, `errno` in case of error. */ -int pman_fill_extra_syscall_calls_table(void); +int pman_fill_syscall_exit_extra_tail_table(void); /** * @brief The syscall dispatchers will look into these tables diff --git a/userspace/libpman/src/events_prog_names.h b/userspace/libpman/src/events_prog_names.h index 688130ea41..2aba445b90 100644 --- a/userspace/libpman/src/events_prog_names.h +++ b/userspace/libpman/src/events_prog_names.h @@ -341,8 +341,8 @@ static const char* event_prog_names[PPM_EVENT_MAX] = { [PPME_SYSCALL_SETREGID_X] = "setregid_x", }; -/* Some events can require more than one bpf program to collect all the data. */ -static const char* extra_event_prog_names[TAIL_EXTRA_EVENT_PROG_MAX] = { +/* Some exit events can require more than one bpf program to collect all the data. */ +static const char* sys_exit_extra_event_names[SYS_EXIT_EXTRA_CODE_MAX] = { [T1_EXECVE_X] = "t1_execve_x", [T1_EXECVEAT_X] = "t1_execveat_x", [T1_CLONE_X] = "t1_clone_x", diff --git a/userspace/libpman/src/maps.c b/userspace/libpman/src/maps.c index 759e43cd8d..36cb2c0829 100644 --- a/userspace/libpman/src/maps.c +++ b/userspace/libpman/src/maps.c @@ -249,24 +249,25 @@ int pman_fill_syscalls_tail_table() { return errno; } -int pman_fill_extra_syscall_calls_table() { - int extra_syscall_call_table_fd = bpf_map__fd(g_state.skel->maps.extra_syscall_calls); - if(extra_syscall_call_table_fd <= 0) { - pman_print_error("unable to get the extra event programs tail table"); +int pman_fill_syscall_exit_extra_tail_table() { + int extra_sys_exit_tail_table_fd = + bpf_map__fd(g_state.skel->maps.syscall_exit_extra_tail_table); + if(extra_sys_exit_tail_table_fd <= 0) { + pman_print_error("unable to get the extra sys exit tail table"); return errno; } const char* tail_prog_name = NULL; - for(int j = 0; j < TAIL_EXTRA_EVENT_PROG_MAX; j++) { - tail_prog_name = extra_event_prog_names[j]; + for(int j = 0; j < SYS_EXIT_EXTRA_CODE_MAX; j++) { + tail_prog_name = sys_exit_extra_event_names[j]; if(!tail_prog_name) { - pman_print_error("unknown entry in the extra event programs tail table"); + pman_print_error("unknown entry in the extra sys exit tail table"); return -1; } - if(add_bpf_program_to_tail_table(extra_syscall_call_table_fd, tail_prog_name, j)) { - close(extra_syscall_call_table_fd); + if(add_bpf_program_to_tail_table(extra_sys_exit_tail_table_fd, tail_prog_name, j)) { + close(extra_sys_exit_tail_table_fd); return errno; } } @@ -331,6 +332,6 @@ int pman_finalize_maps_after_loading() { pman_fill_syscall_sampling_table(); pman_fill_ia32_to_64_table(); err = pman_fill_syscalls_tail_table(); - err = err ?: pman_fill_extra_syscall_calls_table(); + err = err ?: pman_fill_syscall_exit_extra_tail_table(); return err; } From fefd5137152556d1ad48c59756f02d7a772fdf8b Mon Sep 17 00:00:00 2001 From: Andrea Terzolo Date: Tue, 26 Nov 2024 15:11:03 +0100 Subject: [PATCH 5/5] chore: install bpftool manually Signed-off-by: Andrea Terzolo --- .github/workflows/ci.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0a6a66aa8c..19ae7c68b5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -95,7 +95,11 @@ jobs: steps: - name: Install deps ⛓️ run: | - apk add g++ gcc cmake make git bash perl linux-headers autoconf automake m4 libtool elfutils-dev libelf-static patch binutils bpftool clang + apk add g++ gcc cmake make git bash perl linux-headers autoconf automake m4 libtool elfutils-dev libelf-static patch binutils clang llvm + git clone https://github.com/libbpf/bpftool.git --branch v7.3.0 --single-branch + cd bpftool + git submodule update --init + cd src && make install - name: Checkout Libs ⤵️ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2