From 71124d3a9cc5c3efc595b5e2a845b703a88dc9be Mon Sep 17 00:00:00 2001 From: Leonardo Di Giovanna Date: Tue, 17 Dec 2024 15:34:04 +0100 Subject: [PATCH] new: extend BIND_X Signed-off-by: Leonardo Di Giovanna --- driver/SCHEMA_VERSION | 2 +- driver/bpf/fillers.h | 14 ++-- driver/event_table.c | 10 ++- .../syscall_dispatched_events/bind.bpf.c | 3 + driver/ppm_fillers.c | 15 ++-- .../test_suites/syscall_exit_suite/bind_x.cpp | 20 ++++- .../engines/savefile/converter.cpp | 79 +++++++++++++++++++ userspace/libscap/engine/gvisor/fillers.cpp | 8 +- userspace/libscap/engine/gvisor/fillers.h | 3 +- userspace/libscap/engine/gvisor/parsers.cpp | 3 +- .../engine/savefile/converter/table.cpp | 3 + userspace/libscap/scap_event.c | 1 + userspace/libsinsp/test/events_net.ut.cpp | 15 ++-- .../libsinsp/test/parsers/parse_connect.cpp | 9 ++- 14 files changed, 147 insertions(+), 38 deletions(-) diff --git a/driver/SCHEMA_VERSION b/driver/SCHEMA_VERSION index fd2a01863f..944880fa15 100644 --- a/driver/SCHEMA_VERSION +++ b/driver/SCHEMA_VERSION @@ -1 +1 @@ -3.1.0 +3.2.0 diff --git a/driver/bpf/fillers.h b/driver/bpf/fillers.h index 64bf7480ff..d3d12d4506 100644 --- a/driver/bpf/fillers.h +++ b/driver/bpf/fillers.h @@ -3941,18 +3941,15 @@ FILLER(sys_socket_bind_x, true) { uint16_t size = 0; int err = 0; long retval; + int32_t fd; int res; - /* - * res - */ + /* Parameter 1: res (type: PT_ERRNO) */ retval = bpf_syscall_get_retval(data->ctx); res = bpf_push_s64_to_ring(data, retval); CHECK_RES(res); - /* - * addr - */ + /* Parameter 2: addr (type: PT_SOCKADDR) */ usrsockaddr = (struct sockaddr __user *)bpf_syscall_get_argument(data, 1); val = bpf_syscall_get_argument(data, 2); @@ -3974,8 +3971,11 @@ FILLER(sys_socket_bind_x, true) { */ data->curarg_already_on_frame = true; res = bpf_val_to_ring_len(data, 0, size); + CHECK_RES(res); - return res; + /* Parameter 3: fd (type: PT_FD) */ + fd = bpf_syscall_get_argument(data, 0); + return bpf_push_s64_to_ring(data, (int64_t)fd); } static __always_inline int f_sys_recv_x_common(struct filler_data *data, long retval) { diff --git a/driver/event_table.c b/driver/event_table.c index d8160f5369..26305f7a29 100644 --- a/driver/event_table.c +++ b/driver/event_table.c @@ -164,14 +164,16 @@ const struct ppm_event_info g_event_info[] = { {{"fd", PT_FD, PF_DEC}}}, [PPME_SOCKET_BIND_E] = {"bind", EC_NET | EC_SYSCALL, - EF_USES_FD | EF_MODIFIES_STATE, + EF_USES_FD | EF_MODIFIES_STATE | EF_TMP_CONVERTER_MANAGED, 1, {{"fd", PT_FD, PF_DEC}}}, [PPME_SOCKET_BIND_X] = {"bind", EC_NET | EC_SYSCALL, - EF_USES_FD | EF_MODIFIES_STATE, - 2, - {{"res", PT_ERRNO, PF_DEC}, {"addr", PT_SOCKADDR, PF_NA}}}, + EF_USES_FD | EF_MODIFIES_STATE | EF_TMP_CONVERTER_MANAGED, + 3, + {{"res", PT_ERRNO, PF_DEC}, + {"addr", PT_SOCKADDR, PF_NA}, + {"fd", PT_FD, PF_DEC}}}, [PPME_SOCKET_CONNECT_E] = {"connect", EC_NET | EC_SYSCALL, EF_USES_FD | EF_MODIFIES_STATE, diff --git a/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/bind.bpf.c b/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/bind.bpf.c index 0d106c1eff..43a8c3f996 100644 --- a/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/bind.bpf.c +++ b/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/bind.bpf.c @@ -66,6 +66,9 @@ int BPF_PROG(bind_x, struct pt_regs *regs, long ret) { uint16_t addrlen = (uint16_t)args[2]; auxmap__store_sockaddr_param(auxmap, sockaddr_ptr, addrlen); + /* Parameter 3: fd (type: PT_FD) */ + auxmap__store_s64_param(auxmap, (int64_t)(int32_t)args[0]); + /*=============================== COLLECT PARAMETERS ===========================*/ auxmap__finalize_event_header(auxmap); diff --git a/driver/ppm_fillers.c b/driver/ppm_fillers.c index 1fe3366ac9..6e2a1746b8 100644 --- a/driver/ppm_fillers.c +++ b/driver/ppm_fillers.c @@ -1630,16 +1630,13 @@ int f_sys_socket_bind_x(struct event_filler_arguments *args) { unsigned long val; struct sockaddr_storage address; char *targetbuf = args->str_storage; + int32_t fd = 0; - /* - * res - */ + /* Parameter 1: res (type: PT_ERRNO) */ retval = (int64_t)syscall_get_return_value(current, args->regs); res = val_to_ring(args, retval, 0, false, 0); - /* - * addr - */ + /* Parameter 2: addr (type: PT_SOCKADDR) */ syscall_get_arguments_deprecated(args, 1, 1, &val); usrsockaddr = (struct sockaddr __user *)val; @@ -1668,6 +1665,12 @@ int f_sys_socket_bind_x(struct event_filler_arguments *args) { res = val_to_ring(args, (uint64_t)targetbuf, size, false, 0); CHECK_RES(res); + /* Parameter 3: fd (type: PT_FD) */ + syscall_get_arguments_deprecated(args, 0, 1, &val); + fd = (int32_t)val; + res = val_to_ring(args, (int64_t)fd, 0, false, 0); + CHECK_RES(res); + return add_sentinel(args); } diff --git a/test/drivers/test_suites/syscall_exit_suite/bind_x.cpp b/test/drivers/test_suites/syscall_exit_suite/bind_x.cpp index 1c11e23ac0..d882c0a18a 100644 --- a/test/drivers/test_suites/syscall_exit_suite/bind_x.cpp +++ b/test/drivers/test_suites/syscall_exit_suite/bind_x.cpp @@ -50,9 +50,12 @@ TEST(SyscallExit, bindX_INET) { /* Parameter 2: addr (type: PT_SOCKADDR) */ evt_test->assert_addr_info_inet_param(2, PPM_AF_INET, IPV4_SERVER, IPV4_PORT_SERVER_STRING); + /* Parameter 3: fd (type: PT_FD) */ + evt_test->assert_numeric_param(3, (int64_t)server_socket_fd); + /*=============================== ASSERT PARAMETERS ===========================*/ - evt_test->assert_num_params_pushed(2); + evt_test->assert_num_params_pushed(3); } TEST(SyscallExit, bindX_INET6) { @@ -101,9 +104,12 @@ TEST(SyscallExit, bindX_INET6) { /* Parameter 2: addr (type: PT_SOCKADDR) */ evt_test->assert_addr_info_inet6_param(2, PPM_AF_INET6, IPV6_SERVER, IPV6_PORT_SERVER_STRING); + /* Parameter 3: fd (type: PT_FD) */ + evt_test->assert_numeric_param(3, (int64_t)server_socket_fd); + /*=============================== ASSERT PARAMETERS ===========================*/ - evt_test->assert_num_params_pushed(2); + evt_test->assert_num_params_pushed(3); } #ifdef __NR_unlinkat @@ -153,9 +159,12 @@ TEST(SyscallExit, bindX_UNIX) { /* Parameter 2: addr (type: PT_SOCKADDR) */ evt_test->assert_addr_info_unix_param(2, PPM_AF_UNIX, UNIX_SERVER); + /* Parameter 3: fd (type: PT_FD) */ + evt_test->assert_numeric_param(3, (int64_t)server_socket_fd); + /*=============================== ASSERT PARAMETERS ===========================*/ - evt_test->assert_num_params_pushed(2); + evt_test->assert_num_params_pushed(3); } #endif /* __NR_unlinkat */ @@ -195,9 +204,12 @@ TEST(SyscallExit, bindX_failure) { /* Since the pointer to the `sockaddr` is `NULL` we expect an empty param here. */ evt_test->assert_empty_param(2); + /* Parameter 3: fd (type: PT_FD) */ + evt_test->assert_numeric_param(3, (int64_t)mock_fd); + /*=============================== ASSERT PARAMETERS ===========================*/ - evt_test->assert_num_params_pushed(2); + evt_test->assert_num_params_pushed(3); } #endif diff --git a/test/libscap/test_suites/engines/savefile/converter.cpp b/test/libscap/test_suites/engines/savefile/converter.cpp index 8a0d822988..ee24440e8e 100644 --- a/test/libscap/test_suites/engines/savefile/converter.cpp +++ b/test/libscap/test_suites/engines/savefile/converter.cpp @@ -12,6 +12,8 @@ See the License for the specific language governing permissions and limitations under the License. */ #include "convert_event_test.h" +#include +#include TEST_F(convert_event_test, conversion_not_needed) { uint64_t ts = 12; @@ -184,3 +186,80 @@ TEST_F(convert_event_test, PPME_SYSCALL_PREAD_X__to_4_params_with_enter) { size, pos)); } + +//////////////////////////// +// BIND +//////////////////////////// + +TEST_F(convert_event_test, PPME_SOCKET_BIND_E_store) { + uint64_t ts = 12; + int64_t tid = 25; + + int64_t fd = 25; + auto evt = create_safe_scap_event(ts, tid, PPME_SOCKET_BIND_E, 1, fd); + assert_single_conversion_skip(evt); + assert_event_storage_presence(evt); +} + +TEST_F(convert_event_test, PPME_SOCKET_BIND_X_to_3_params_no_enter) { + uint64_t ts = 12; + int64_t tid = 25; + + int64_t res = 89; + struct sockaddr_in sockaddr = {}; + sockaddr.sin_family = AF_INET; + sockaddr.sin_port = htons(1234); + sockaddr.sin_addr.s_addr = htonl(INADDR_ANY); + + // Defaulted to 0 + int64_t fd = 0; + + assert_single_conversion_success( + conversion_result::CONVERSION_COMPLETED, + create_safe_scap_event(ts, + tid, + PPME_SOCKET_BIND_X, + 2, + res, + scap_const_sized_buffer{&sockaddr, sizeof(sockaddr)}), + create_safe_scap_event(ts, + tid, + PPME_SOCKET_BIND_X, + 3, + res, + scap_const_sized_buffer{&sockaddr, sizeof(sockaddr)}, + fd)); +} + +TEST_F(convert_event_test, PPME_SOCKET_BIND_X_to_3_params_with_enter) { + uint64_t ts = 12; + int64_t tid = 25; + + int64_t res = 89; + struct sockaddr_in sockaddr = {}; + sockaddr.sin_family = AF_INET; + sockaddr.sin_port = htons(1234); + sockaddr.sin_addr.s_addr = htonl(INADDR_ANY); + int64_t fd = 100; + + // After the first conversion we should have the storage + auto evt = create_safe_scap_event(ts, tid, PPME_SOCKET_BIND_E, 1, fd); + assert_single_conversion_skip(evt); + assert_event_storage_presence(evt); + + assert_single_conversion_success( + conversion_result::CONVERSION_COMPLETED, + create_safe_scap_event(ts, + tid, + PPME_SOCKET_BIND_X, + 2, + res, + scap_const_sized_buffer{&sockaddr, sizeof(sockaddr)}), + create_safe_scap_event(ts, + tid, + PPME_SOCKET_BIND_X, + 3, + res, + scap_const_sized_buffer{&sockaddr, sizeof(sockaddr)}, + fd)); +} diff --git a/userspace/libscap/engine/gvisor/fillers.cpp b/userspace/libscap/engine/gvisor/fillers.cpp index 48de12dfae..71c48dec71 100644 --- a/userspace/libscap/engine/gvisor/fillers.cpp +++ b/userspace/libscap/engine/gvisor/fillers.cpp @@ -1202,14 +1202,16 @@ int32_t fill_event_bind_x(scap_sized_buffer scap_buf, size_t* event_size, char* scap_err, int64_t res, - scap_const_sized_buffer addr) { + scap_const_sized_buffer addr, + int64_t fd) { return scap_event_encode_params(scap_buf, event_size, scap_err, PPME_SOCKET_BIND_X, - 2, + 3, res, - addr); + addr, + fd); } // PPME_SYSCALL_ACCEPT_5_E diff --git a/userspace/libscap/engine/gvisor/fillers.h b/userspace/libscap/engine/gvisor/fillers.h index d7b7b8bd9a..fb93e8a93f 100644 --- a/userspace/libscap/engine/gvisor/fillers.h +++ b/userspace/libscap/engine/gvisor/fillers.h @@ -441,7 +441,8 @@ int32_t fill_event_bind_x(scap_sized_buffer scap_buf, size_t* event_size, char* scap_err, int64_t res, - scap_const_sized_buffer addr); + scap_const_sized_buffer addr, + int64_t fd); int32_t fill_event_accept_5_e(scap_sized_buffer scap_buf, size_t* event_size, char* scap_err); diff --git a/userspace/libscap/engine/gvisor/parsers.cpp b/userspace/libscap/engine/gvisor/parsers.cpp index 73cdaedeca..0d78fbf333 100644 --- a/userspace/libscap/engine/gvisor/parsers.cpp +++ b/userspace/libscap/engine/gvisor/parsers.cpp @@ -994,7 +994,8 @@ static parse_result parse_bind(uint32_t id, &ret.size, scap_err, gvisor_evt.exit().result(), - scap_const_sized_buffer{targetbuf, size}); + scap_const_sized_buffer{targetbuf, size}, + gvisor_evt.fd()); } else { ret.status = scap_gvisor::fillers::fill_event_bind_e(scap_buf, &ret.size, diff --git a/userspace/libscap/engine/savefile/converter/table.cpp b/userspace/libscap/engine/savefile/converter/table.cpp index e00f683e7d..aa326a8779 100644 --- a/userspace/libscap/engine/savefile/converter/table.cpp +++ b/userspace/libscap/engine/savefile/converter/table.cpp @@ -36,4 +36,7 @@ const std::unordered_map g_conversion_table = { .instrs({{C_INSTR_FROM_ENTER, 0}, {C_INSTR_FROM_ENTER, 1}, {C_INSTR_FROM_ENTER, 2}})}, + {conversion_key{PPME_SOCKET_BIND_E, 1}, conversion_info().action(C_ACTION_STORE)}, + {conversion_key{PPME_SOCKET_BIND_X, 2}, + conversion_info().action(C_ACTION_ADD_PARAMS).instrs({{C_INSTR_FROM_ENTER, 0}})}, }; diff --git a/userspace/libscap/scap_event.c b/userspace/libscap/scap_event.c index c13a55efb5..6ba2cfef4c 100644 --- a/userspace/libscap/scap_event.c +++ b/userspace/libscap/scap_event.c @@ -531,6 +531,7 @@ int get_exit_event_fd_location(ppm_event_code etype) { switch(etype) { case PPME_SYSCALL_READ_X: case PPME_SYSCALL_PREAD_X: + case PPME_SOCKET_BIND_X: location = 2; break; default: diff --git a/userspace/libsinsp/test/events_net.ut.cpp b/userspace/libsinsp/test/events_net.ut.cpp index faedbcf878..efc846b0b9 100644 --- a/userspace/libsinsp/test/events_net.ut.cpp +++ b/userspace/libsinsp/test/events_net.ut.cpp @@ -368,10 +368,6 @@ TEST_F(sinsp_with_test_input, net_bind_listen_accept_ipv4) { (uint32_t)0); add_event_advance_ts(increasing_ts(), 1, PPME_SOCKET_SOCKET_X, 1, server_fd); - /* We have no parsers for bind enter event */ - evt = add_event_advance_ts(increasing_ts(), 1, PPME_SOCKET_BIND_E, 1, server_fd); - ASSERT_EQ(get_field_as_string(evt, "fd.name"), ""); - sockaddr_in server = test_utils::fill_sockaddr_in(DEFAULT_SERVER_PORT, DEFAULT_IPV4_SERVER_STRING); std::vector server_sockaddr = @@ -381,9 +377,10 @@ TEST_F(sinsp_with_test_input, net_bind_listen_accept_ipv4) { increasing_ts(), 1, PPME_SOCKET_BIND_X, - 2, + 3, return_value, - scap_const_sized_buffer{server_sockaddr.data(), server_sockaddr.size()}); + scap_const_sized_buffer{server_sockaddr.data(), server_sockaddr.size()}, + server_fd); fdinfo = evt->get_fd_info(); ASSERT_NE(fdinfo, nullptr); ASSERT_FALSE(fdinfo->is_ipv4_socket()); @@ -464,7 +461,6 @@ TEST_F(sinsp_with_test_input, net_bind_listen_accept_ipv6) { (uint32_t)SOCK_STREAM, 0); add_event_advance_ts(increasing_ts(), 1, PPME_SOCKET_SOCKET_X, 1, server_fd); - add_event_advance_ts(increasing_ts(), 1, PPME_SOCKET_BIND_E, 1, server_fd); sockaddr_in6 server = test_utils::fill_sockaddr_in6(DEFAULT_SERVER_PORT, DEFAULT_IPV6_SERVER_STRING); @@ -475,9 +471,10 @@ TEST_F(sinsp_with_test_input, net_bind_listen_accept_ipv6) { increasing_ts(), 1, PPME_SOCKET_BIND_X, - 2, + 3, return_value, - scap_const_sized_buffer{server_sockaddr.data(), server_sockaddr.size()}); + scap_const_sized_buffer{server_sockaddr.data(), server_sockaddr.size()}, + server_fd); std::string fdname = std::string(DEFAULT_IPV6_SERVER_STRING) + ":" + std::string(DEFAULT_SERVER_PORT_STRING); ASSERT_EQ(get_field_as_string(evt, "fd.name"), fdname); diff --git a/userspace/libsinsp/test/parsers/parse_connect.cpp b/userspace/libsinsp/test/parsers/parse_connect.cpp index 43bdf49525..25ac9dc340 100644 --- a/userspace/libsinsp/test/parsers/parse_connect.cpp +++ b/userspace/libsinsp/test/parsers/parse_connect.cpp @@ -121,14 +121,19 @@ TEST_F(sinsp_with_test_input, BIND_parse_unix_socket) { sockaddr_un u_sockaddr = test_utils::fill_sockaddr_un(unix_path.c_str()); std::vector server_sockaddr = test_utils::pack_sockaddr(reinterpret_cast(&u_sockaddr)); + uint64_t socket_fd = 77; auto evt = add_event_advance_ts( increasing_ts(), INIT_TID, PPME_SOCKET_BIND_X, - 2, + 3, return_value, - scap_const_sized_buffer{server_sockaddr.data(), server_sockaddr.size()}); + scap_const_sized_buffer{server_sockaddr.data(), server_sockaddr.size()}, + socket_fd); // we want to check that `get_param_value_str` returns the correct unix socket path ASSERT_EQ(evt->get_param_value_str("addr"), unix_path); + + // we want to check that `get_fd_info()->m_fd` returns the correct socket fd. + ASSERT_EQ(evt->get_param_by_name("fd")->as(), socket_fd); }