diff --git a/driver/bpf/fillers.h b/driver/bpf/fillers.h index 139c91e6d27..1cd36451cc5 100644 --- a/driver/bpf/fillers.h +++ b/driver/bpf/fillers.h @@ -3387,54 +3387,37 @@ FILLER(sys_io_uring_setup_x, true) FILLER(sys_io_uring_enter_x, true) { - long retval; - int res; - unsigned long val; - - retval = bpf_syscall_get_retval(data->ctx); - res = bpf_val_to_ring(data, retval); - if (res != PPM_SUCCESS) - return res; + /* Parameter 1: res (type: PT_ERRNO) */ + long retval = bpf_syscall_get_retval(data->ctx); + int res = bpf_val_to_ring(data, retval); + CHECK_RES(res); - /* - * fd - */ - val = bpf_syscall_get_argument(data, 0); - res = bpf_val_to_ring(data, val); - if (res != PPM_SUCCESS) - return res; + /* Parameter 2: fd (type: PT_FD) */ + s32 fd = (s32)bpf_syscall_get_argument(data, 0); + res = bpf_val_to_ring(data, (s64)fd); + CHECK_RES(res); - /* - * to_submit - */ - val = bpf_syscall_get_argument(data, 1); - res = bpf_val_to_ring(data, val); - if (res != PPM_SUCCESS) - return res; + /* Parameter 3: to_submit (type: PT_UINT32) */ + u32 to_submit = (u32)bpf_syscall_get_argument(data, 1); + res = bpf_val_to_ring(data, to_submit); + CHECK_RES(res); - /* - * min_complete - */ - val = bpf_syscall_get_argument(data, 2); - res = bpf_val_to_ring(data, val); - if (res != PPM_SUCCESS) - return res; + /* Parameter 4: min_complete (type: PT_UINT32) */ + u32 min_complete = (u32)bpf_syscall_get_argument(data, 2); + res = bpf_val_to_ring(data, min_complete); + CHECK_RES(res); - /* - * flags - */ - val = bpf_syscall_get_argument(data, 3); - res = bpf_val_to_ring(data, io_uring_enter_flags_to_scap(val)); - if (res != PPM_SUCCESS) - return res; + /* Parameter 5: flags (type: PT_FLAGS32) */ + u32 flags = (u32)bpf_syscall_get_argument(data, 3); + res = bpf_val_to_ring(data, io_uring_enter_flags_to_scap(flags)); + CHECK_RES(res); - /* - * min_complete - */ - val = bpf_syscall_get_argument(data, 4); - res = bpf_val_to_ring(data, val); + /* Parameter 6: sig (type: PT_SIGSET) */ + u32 sig = (u32)bpf_syscall_get_argument(data, 4); + return bpf_val_to_ring(data, sig); - return res; + /// TODO: We miss the last parameter `size_t argsz` + /// we need to implement it in all our drivers } FILLER(sys_io_uring_register_x, true) diff --git a/driver/modern_bpf/definitions/events_dimensions.h b/driver/modern_bpf/definitions/events_dimensions.h index 30244635240..29ad7b11fab 100644 --- a/driver/modern_bpf/definitions/events_dimensions.h +++ b/driver/modern_bpf/definitions/events_dimensions.h @@ -152,6 +152,8 @@ #define MLOCKALL_X_SIZE HEADER_LEN + sizeof(int64_t) + sizeof(uint32_t) + PARAM_LEN * 2 #define MUNLOCKALL_E_SIZE HEADER_LEN #define MUNLOCKALL_X_SIZE HEADER_LEN + sizeof(int64_t) + PARAM_LEN +#define IO_URING_ENTER_E_SIZE HEADER_LEN +#define IO_URING_ENTER_X_SIZE HEADER_LEN + sizeof(int64_t) * 2 + sizeof(uint32_t) * 4 + PARAM_LEN * 6 /* Generic tracepoints events. */ #define PROC_EXIT_SIZE HEADER_LEN + sizeof(int64_t) * 2 + sizeof(uint8_t) * 2 + PARAM_LEN * 4 diff --git a/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/io_uring_enter.bpf.c b/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/io_uring_enter.bpf.c new file mode 100644 index 00000000000..b2eaa9e7f05 --- /dev/null +++ b/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/io_uring_enter.bpf.c @@ -0,0 +1,91 @@ +/* + * 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 + +/*=============================== ENTER EVENT ===========================*/ + +SEC("tp_btf/sys_enter") +int BPF_PROG(io_uring_enter_e, + struct pt_regs *regs, + long id) +{ + struct ringbuf_struct ringbuf; + if(!ringbuf__reserve_space(&ringbuf, IO_URING_ENTER_E_SIZE)) + { + return 0; + } + + ringbuf__store_event_header(&ringbuf, PPME_SYSCALL_IO_URING_ENTER_E); + + /*=============================== COLLECT PARAMETERS ===========================*/ + + // Here we have no parameters to collect. + + /*=============================== COLLECT PARAMETERS ===========================*/ + + ringbuf__submit_event(&ringbuf); + + return 0; +} + +/*=============================== ENTER EVENT ===========================*/ + +/*=============================== EXIT EVENT ===========================*/ + +SEC("tp_btf/sys_exit") +int BPF_PROG(io_uring_enter_x, + struct pt_regs *regs, + long ret) +{ + struct ringbuf_struct ringbuf; + if(!ringbuf__reserve_space(&ringbuf, IO_URING_ENTER_X_SIZE)) + { + return 0; + } + + ringbuf__store_event_header(&ringbuf, PPME_SYSCALL_IO_URING_ENTER_X); + + /*=============================== COLLECT PARAMETERS ===========================*/ + + /* Parameter 1: res (type: PT_ERRNO) */ + ringbuf__store_s64(&ringbuf, ret); + + /* Parameter 2: fd (type: PT_FD) */ + s32 fd = (s32)extract__syscall_argument(regs, 0); + ringbuf__store_s64(&ringbuf, (s64)fd); + + /* Parameter 3: to_submit (type: PT_UINT32) */ + u32 to_submit = (u32)extract__syscall_argument(regs, 1); + ringbuf__store_u32(&ringbuf, to_submit); + + /* Parameter 4: min_complete (type: PT_UINT32) */ + u32 min_complete = (u32)extract__syscall_argument(regs, 2); + ringbuf__store_u32(&ringbuf, min_complete); + + /* Parameter 5: flags (type: PT_FLAGS32) */ + u32 flags = (u32)extract__syscall_argument(regs, 3); + ringbuf__store_u32(&ringbuf, io_uring_enter_flags_to_scap(flags)); + + /* Parameter 6: sig (type: PT_SIGSET) */ + /* This is unclear, why we store only the first 32 bit? this is a pointer! + * It could be also a pointer to a `struct io_uring_getevents_args`. + */ + u32 sig = (u32)extract__syscall_argument(regs, 4); + ringbuf__store_u32(&ringbuf, sig); + + /// TODO: We miss the last parameter `size_t argsz` + /// we need to implement it in all our drivers + + /*=============================== COLLECT PARAMETERS ===========================*/ + + ringbuf__submit_event(&ringbuf); + + return 0; +} + +/*=============================== EXIT EVENT ===========================*/ diff --git a/driver/ppm_fillers.c b/driver/ppm_fillers.c index a8ecea3af0d..7aac57e7491 100644 --- a/driver/ppm_fillers.c +++ b/driver/ppm_fillers.c @@ -5175,45 +5175,45 @@ int f_sys_io_uring_setup_x (struct event_filler_arguments *args) return add_sentinel(args); } -int f_sys_io_uring_enter_x (struct event_filler_arguments *args) +int f_sys_io_uring_enter_x(struct event_filler_arguments *args) { - int res; - unsigned long val; + int res = 0; + int32_t fd = 0; + unsigned long val = 0; - int64_t retval = (int64_t)syscall_get_return_value(current, args->regs); + /* Parameter 1: res (type: PT_ERRNO) */ + long retval = (long)syscall_get_return_value(current, args->regs); res = val_to_ring(args, retval, 0, false, 0); - if (unlikely(res != PPM_SUCCESS)) - return res; + CHECK_RES(res); - /* fd */ + /* Parameter 2: fd (type: PT_FD) */ syscall_get_arguments_deprecated(current, args->regs, 0, 1, &val); - res = val_to_ring(args, val, 0, true, 0); - if (unlikely(res != PPM_SUCCESS)) - return res; + fd = (s32)val; + res = val_to_ring(args, (s64)fd, 0, true, 0); + CHECK_RES(res); - /* to_submit */ + /* Parameter 3: to_submit (type: PT_UINT32) */ syscall_get_arguments_deprecated(current, args->regs, 1, 1, &val); res = val_to_ring(args, val, 0, true, 0); - if (unlikely(res != PPM_SUCCESS)) - return res; + CHECK_RES(res); - /* min_complete */ + /* Parameter 4: min_complete (type: PT_UINT32) */ syscall_get_arguments_deprecated(current, args->regs, 2, 1, &val); res = val_to_ring(args, val, 0, true, 0); - if (unlikely(res != PPM_SUCCESS)) - return res; + CHECK_RES(res); - /* flags */ + /* Parameter 5: flags (type: PT_FLAGS32) */ syscall_get_arguments_deprecated(current, args->regs, 3, 1, &val); res = val_to_ring(args, io_uring_enter_flags_to_scap(val), 0, true, 0); - if (unlikely(res != PPM_SUCCESS)) - return res; + CHECK_RES(res); - /* sig */ + /* Parameter 6: sig (type: PT_SIGSET) */ syscall_get_arguments_deprecated(current, args->regs, 4, 1, &val); res = val_to_ring(args, val, 0, true, 0); - if (unlikely(res != PPM_SUCCESS)) - return res; + CHECK_RES(res); + + /// TODO: We miss the last parameter `size_t argsz` + /// we need to implement it in all our drivers return add_sentinel(args); } diff --git a/test/drivers/test_suites/syscall_enter_suite/io_uring_enter_e.cpp b/test/drivers/test_suites/syscall_enter_suite/io_uring_enter_e.cpp new file mode 100644 index 00000000000..374d8eaa0bf --- /dev/null +++ b/test/drivers/test_suites/syscall_enter_suite/io_uring_enter_e.cpp @@ -0,0 +1,46 @@ +#include "../../event_class/event_class.h" + +#if defined(__NR_io_uring_enter) + +#include + +TEST(SyscallEnter, io_uring_enterE) +{ + auto evt_test = get_syscall_event_test(__NR_io_uring_enter, ENTER_EVENT); + + evt_test->enable_capture(); + + /*=============================== TRIGGER SYSCALL ===========================*/ + + int32_t fd = -1; + uint32_t to_submit = 10; + uint32_t min_complete = 20; + uint32_t flags = IORING_ENTER_EXT_ARG; + const void* argp = NULL; + size_t argsz = 7; + assert_syscall_state(SYSCALL_FAILURE, "io_uring_enter", syscall(__NR_io_uring_enter, fd, to_submit, min_complete, flags, argp, argsz)); + + /*=============================== TRIGGER SYSCALL ===========================*/ + + evt_test->disable_capture(); + + evt_test->assert_event_presence(); + + if(HasFatalFailure()) + { + return; + } + + evt_test->parse_event(); + + evt_test->assert_header(); + + /*=============================== ASSERT PARAMETERS ===========================*/ + + // Here we have no parameters to assert. + + /*=============================== ASSERT PARAMETERS ===========================*/ + + evt_test->assert_num_params_pushed(0); +} +#endif diff --git a/test/drivers/test_suites/syscall_exit_suite/io_uring_enter_x.cpp b/test/drivers/test_suites/syscall_exit_suite/io_uring_enter_x.cpp new file mode 100644 index 00000000000..117e85c4e3f --- /dev/null +++ b/test/drivers/test_suites/syscall_exit_suite/io_uring_enter_x.cpp @@ -0,0 +1,64 @@ +#include "../../event_class/event_class.h" + +#if defined(__NR_io_uring_enter) && defined(__NR_close) + +#include + +TEST(SyscallExit, io_uring_enterX) +{ + auto evt_test = get_syscall_event_test(__NR_io_uring_enter, EXIT_EVENT); + + evt_test->enable_capture(); + + /*=============================== TRIGGER SYSCALL ===========================*/ + + int32_t fd = -1; + uint32_t to_submit = 10; + uint32_t min_complete = 20; + uint32_t flags = IORING_ENTER_EXT_ARG; + const void* argp = NULL; + size_t argsz = 7; + assert_syscall_state(SYSCALL_FAILURE, "io_uring_enter", syscall(__NR_io_uring_enter, fd, to_submit, min_complete, flags, argp, argsz)); + int64_t errno_value = -errno; + + /*=============================== TRIGGER SYSCALL ===========================*/ + + evt_test->disable_capture(); + + evt_test->assert_event_presence(); + + if(HasFatalFailure()) + { + return; + } + + evt_test->parse_event(); + + evt_test->assert_header(); + + /*=============================== ASSERT PARAMETERS ===========================*/ + + /* Parameter 1: res (type: PT_ERRNO) */ + evt_test->assert_numeric_param(1, (int64_t)errno_value); + + /* Parameter 2: fd (type: PT_FD) */ + evt_test->assert_numeric_param(2, (int64_t)fd); + + /* Parameter 3: to_submit (type: PT_UINT32) */ + evt_test->assert_numeric_param(3, (uint32_t)to_submit); + + /* Parameter 4: min_complete (type: PT_UINT32) */ + evt_test->assert_numeric_param(4, (uint32_t)min_complete); + + /* Parameter 5: flags (type: PT_FLAGS32) */ + evt_test->assert_numeric_param(5, (uint32_t)PPM_IORING_ENTER_EXT_ARG); + + /* Parameter 6: sig (type: PT_SIGSET) */ + /* These are the first 32 bit of a pointer so in this case all zeros */ + evt_test->assert_numeric_param(6, (uint32_t)0); + + /*=============================== ASSERT PARAMETERS ===========================*/ + + evt_test->assert_num_params_pushed(6); +} +#endif diff --git a/userspace/libpman/src/events_prog_names.h b/userspace/libpman/src/events_prog_names.h index 5225f4f7b5d..39b1a56d5c6 100644 --- a/userspace/libpman/src/events_prog_names.h +++ b/userspace/libpman/src/events_prog_names.h @@ -207,6 +207,8 @@ static const char* event_prog_names[PPM_EVENT_MAX] = { [PPME_SYSCALL_MLOCKALL_X] = "mlockall_x", [PPME_SYSCALL_MUNLOCKALL_E] = "munlockall_e", [PPME_SYSCALL_MUNLOCKALL_X] = "munlockall_x", + [PPME_SYSCALL_IO_URING_ENTER_E] = "io_uring_enter_e", + [PPME_SYSCALL_IO_URING_ENTER_X] = "io_uring_enter_x", }; /* Some events can require more than one bpf program to collect all the data. */