diff --git a/driver/modern_bpf/definitions/events_dimensions.h b/driver/modern_bpf/definitions/events_dimensions.h index 4d79ea0a69..4413724995 100644 --- a/driver/modern_bpf/definitions/events_dimensions.h +++ b/driver/modern_bpf/definitions/events_dimensions.h @@ -207,6 +207,7 @@ #define GETRLIMIT_E_SIZE HEADER_LEN + sizeof(uint8_t) + PARAM_LEN #define GETRLIMIT_X_SIZE HEADER_LEN + sizeof(int64_t) * 3 + PARAM_LEN * 3 #define SEND_E_SIZE HEADER_LEN + sizeof(int64_t) + sizeof(uint32_t) + PARAM_LEN * 2 +#define RECV_E_SIZE HEADER_LEN + sizeof(int64_t) + sizeof(uint32_t) + PARAM_LEN * 2 #define NANOSLEEP_E_SIZE HEADER_LEN + sizeof(uint64_t) + PARAM_LEN #define NANOSLEEP_X_SIZE HEADER_LEN + sizeof(int64_t) + PARAM_LEN diff --git a/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/recv.bpf.c b/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/recv.bpf.c new file mode 100644 index 0000000000..dbf27733e8 --- /dev/null +++ b/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/recv.bpf.c @@ -0,0 +1,100 @@ +/* + * 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 +#include + +/*=============================== ENTER EVENT ===========================*/ + +SEC("tp_btf/sys_enter") +int BPF_PROG(recv_e, + struct pt_regs *regs, + long id) +{ + struct ringbuf_struct ringbuf; + if(!ringbuf__reserve_space(&ringbuf, RECV_E_SIZE)) + { + return 0; + } + + ringbuf__store_event_header(&ringbuf, PPME_SOCKET_RECV_E); + + /*=============================== COLLECT PARAMETERS ===========================*/ + + /* Collect parameters at the beginning to manage socketcalls */ + unsigned long args[3]; + extract__network_args(args, 3, regs); + + /* Parameter 1: fd (type: PT_FD) */ + s32 fd = (s32)args[0]; + ringbuf__store_s64(&ringbuf, (s64)fd); + + /* Parameter 2: size (type: PT_UINT32) */ + u32 size = (u32)args[2]; + ringbuf__store_u32(&ringbuf, size); + + /*=============================== COLLECT PARAMETERS ===========================*/ + + ringbuf__submit_event(&ringbuf); + + return 0; +} + +/*=============================== ENTER EVENT ===========================*/ + +/*=============================== EXIT EVENT ===========================*/ + +SEC("tp_btf/sys_exit") +int BPF_PROG(recv_x, + struct pt_regs *regs, + long ret) +{ + struct auxiliary_map *auxmap = auxmap__get(); + if(!auxmap) + { + return 0; + } + + auxmap__preload_event_header(auxmap, PPME_SOCKET_RECV_X); + + /*=============================== COLLECT PARAMETERS ===========================*/ + + /* Parameter 1: res (type: PT_ERRNO) */ + auxmap__store_s64_param(auxmap, ret); + + if(ret > 0) + { + /* Collect parameters at the beginning to manage socketcalls */ + unsigned long args[2]; + extract__network_args(args, 2, regs); + + unsigned long bytes_to_read = maps__get_snaplen(); + if(bytes_to_read > ret) + { + bytes_to_read = ret; + } + + /* Parameter 2: data (type: PT_BYTEBUF) */ + unsigned long data_pointer = args[1]; + auxmap__store_bytebuf_param(auxmap, data_pointer, bytes_to_read, USER); + } + else + { + /* Parameter 2: data (type: PT_BYTEBUF) */ + auxmap__store_empty_param(auxmap); + } + + /*=============================== COLLECT PARAMETERS ===========================*/ + + auxmap__finalize_event_header(auxmap); + + auxmap__submit_event(auxmap); + + return 0; +} + +/*=============================== EXIT EVENT ===========================*/ diff --git a/test/drivers/test_suites/syscall_enter_suite/recv_e.cpp b/test/drivers/test_suites/syscall_enter_suite/recv_e.cpp new file mode 100644 index 0000000000..9c3b92f57e --- /dev/null +++ b/test/drivers/test_suites/syscall_enter_suite/recv_e.cpp @@ -0,0 +1,46 @@ +#include "../../event_class/event_class.h" + +#ifdef __NR_recv + +TEST(SyscallEnter, recvE) +{ + auto evt_test = get_syscall_event_test(__NR_recv, ENTER_EVENT); + + evt_test->enable_capture(); + + /*=============================== TRIGGER SYSCALL ===========================*/ + + int32_t mock_fd = -1; + char* mock_buf = NULL; + size_t mock_count = DEFAULT_SNAPLEN; + int flags = 0; + assert_syscall_state(SYSCALL_FAILURE, "recv", syscall(__NR_recv, mock_fd, (void*)(mock_buf), mock_count, flags)); + + /*=============================== 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: fd (type: PT_FD) */ + evt_test->assert_numeric_param(1, (int64_t)mock_fd); + + /* Parameter 2: size (type: PT_UINT32)*/ + evt_test->assert_numeric_param(2, (uint32_t)mock_count); + + /*=============================== ASSERT PARAMETERS ===========================*/ + + evt_test->assert_num_params_pushed(2); +} +#endif diff --git a/test/drivers/test_suites/syscall_enter_suite/socketcall_e.cpp b/test/drivers/test_suites/syscall_enter_suite/socketcall_e.cpp index 1afddd7228..e304fce481 100644 --- a/test/drivers/test_suites/syscall_enter_suite/socketcall_e.cpp +++ b/test/drivers/test_suites/syscall_enter_suite/socketcall_e.cpp @@ -940,4 +940,55 @@ TEST(SyscallEnter, socketcall_sendE) } #endif +#ifdef __NR_recv + +TEST(SyscallEnter, socketcall_recvE) +{ + auto evt_test = get_syscall_event_test(__NR_recv, ENTER_EVENT); + + evt_test->enable_capture(); + + /*=============================== TRIGGER SYSCALL ===========================*/ + + int32_t mock_fd = -1; + char *mock_buf = NULL; + size_t mock_count = DEFAULT_SNAPLEN; + int flags = 0; + + unsigned long args[4] = {0}; + args[0] = mock_fd; + args[1] = (unsigned long)mock_buf; + args[2] = mock_count; + args[3] = (unsigned long)flags; + assert_syscall_state(SYSCALL_FAILURE, "recv", syscall(__NR_socketcall, SYS_RECV, args)); + + /*=============================== 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: fd (type: PT_FD) */ + evt_test->assert_numeric_param(1, (int64_t)mock_fd); + + /* Parameter 2: size (type: PT_UINT32)*/ + evt_test->assert_numeric_param(2, (uint32_t)mock_count); + + /*=============================== ASSERT PARAMETERS ===========================*/ + + evt_test->assert_num_params_pushed(2); +} +#endif + #endif /* __NR_socketcall */ diff --git a/test/drivers/test_suites/syscall_exit_suite/recv_x.cpp b/test/drivers/test_suites/syscall_exit_suite/recv_x.cpp new file mode 100644 index 0000000000..670e5b9c82 --- /dev/null +++ b/test/drivers/test_suites/syscall_exit_suite/recv_x.cpp @@ -0,0 +1,46 @@ +#include "../../event_class/event_class.h" + +#ifdef __NR_recv +TEST(SyscallExit, recvX_fail) +{ + auto evt_test = get_syscall_event_test(__NR_recv, EXIT_EVENT); + + evt_test->enable_capture(); + + /*=============================== TRIGGER SYSCALL ===========================*/ + + int32_t mock_fd = -1; + char* mock_buf = NULL; + size_t mock_count = DEFAULT_SNAPLEN; + int flags = 0; + assert_syscall_state(SYSCALL_FAILURE, "recv", syscall(__NR_recv, mock_fd, (void*)(mock_buf), mock_count, flags)); + int 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: data (type: PT_BYTEBUF) */ + evt_test->assert_empty_param(2); + + /*=============================== ASSERT PARAMETERS ===========================*/ + + evt_test->assert_num_params_pushed(2); +} +#endif diff --git a/test/drivers/test_suites/syscall_exit_suite/socketcall_x.cpp b/test/drivers/test_suites/syscall_exit_suite/socketcall_x.cpp index b9e3aa4f28..8096e82968 100644 --- a/test/drivers/test_suites/syscall_exit_suite/socketcall_x.cpp +++ b/test/drivers/test_suites/syscall_exit_suite/socketcall_x.cpp @@ -2952,4 +2952,55 @@ TEST(SyscallExit, socketcall_sendX) } #endif +#ifdef __NR_recv +TEST(SyscallExit, socketcall_recvX_fail) +{ + auto evt_test = get_syscall_event_test(__NR_recv, EXIT_EVENT); + + evt_test->enable_capture(); + + /*=============================== TRIGGER SYSCALL ===========================*/ + + int32_t mock_fd = -1; + char *mock_buf = NULL; + size_t mock_count = DEFAULT_SNAPLEN; + int flags = 0; + + unsigned long args[4] = {0}; + args[0] = mock_fd; + args[1] = (unsigned long)mock_buf; + args[2] = mock_count; + args[3] = (unsigned long)flags; + assert_syscall_state(SYSCALL_FAILURE, "recv", syscall(__NR_socketcall, SYS_RECV, args)); + int 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: data (type: PT_BYTEBUF) */ + evt_test->assert_empty_param(2); + + /*=============================== ASSERT PARAMETERS ===========================*/ + + evt_test->assert_num_params_pushed(2); +} +#endif + #endif /* __NR_socketcall */ diff --git a/userspace/libpman/src/events_prog_names.h b/userspace/libpman/src/events_prog_names.h index 1d90cd5dc1..cd511d6f65 100644 --- a/userspace/libpman/src/events_prog_names.h +++ b/userspace/libpman/src/events_prog_names.h @@ -275,6 +275,8 @@ static const char* event_prog_names[PPM_EVENT_MAX] = { [PPME_SYSCALL_GETRLIMIT_X] = "getrlimit_x", [PPME_SOCKET_SEND_E] = "send_e", [PPME_SOCKET_SEND_X] = "send_x", + [PPME_SOCKET_RECV_E] = "recv_e", + [PPME_SOCKET_RECV_X] = "recv_x", [PPME_SYSCALL_NANOSLEEP_E] = "nanosleep_e", [PPME_SYSCALL_NANOSLEEP_X] = "nanosleep_x", [PPME_SYSCALL_UMOUNT_1_E] = "umount_e",