diff --git a/driver/SCHEMA_VERSION b/driver/SCHEMA_VERSION index 9b6c271987..cc24ff36d7 100644 --- a/driver/SCHEMA_VERSION +++ b/driver/SCHEMA_VERSION @@ -1 +1 @@ -3.64.0 +3.65.0 diff --git a/driver/bpf/fillers.h b/driver/bpf/fillers.h index 65a057fdb5..9a226fbdb7 100644 --- a/driver/bpf/fillers.h +++ b/driver/bpf/fillers.h @@ -1436,57 +1436,60 @@ FILLER(sys_connect_x, true) { int res = bpf_push_s64_to_ring(data, retval); CHECK_RES(res); + /* Get socket file descriptor, sockaddr pointer and length. */ int64_t fd = (int64_t)(int32_t)bpf_syscall_get_argument(data, 0); - - if(retval != 0 && retval != -EINPROGRESS) { - /* Parameter 2: tuple (type: PT_SOCKTUPLE) */ - res = bpf_push_empty_param(data); - CHECK_RES(res); - - /* Parameter 3: fd (type: PT_FD) */ - return bpf_push_s64_to_ring(data, fd); - } - - /* Get the sockaddr pointer and length. */ struct sockaddr __user *usrsockaddr = (struct sockaddr __user *)bpf_syscall_get_argument(data, 1); unsigned long usrsockaddr_len = bpf_syscall_get_argument(data, 2); - /* Evaluate socktuple, leveraging the user-provided sockaddr if possible */ + /* Copy the user-provided sockaddr into kernel memory, if possible. */ struct sockaddr *ksockaddr = (struct sockaddr *)data->tmp_scratch; - bool use_sockaddr_user_data = false; + bool can_use_sockaddr_data = false; bool push_socktuple = true; if(usrsockaddr != NULL && usrsockaddr_len != 0) { - /* Copy the address into kernel memory. */ res = bpf_addr_to_kernel(usrsockaddr, usrsockaddr_len, ksockaddr); if(likely(res >= 0)) { - /* Convert the fd into socket endpoint information. */ - use_sockaddr_user_data = true; + can_use_sockaddr_data = true; } else { - /* Do not send any socket endpoint information. */ push_socktuple = false; } } - uint32_t tuple_size = 0; - if(push_socktuple) { - /* Convert the fd into socket endpoint information */ - tuple_size = bpf_fd_to_socktuple(data, - fd, - ksockaddr, - usrsockaddr_len, - use_sockaddr_user_data, - false, - data->tmp_scratch + sizeof(struct sockaddr_storage)); - } - /* Parameter 2: tuple (type: PT_SOCKTUPLE) */ - data->curarg_already_on_frame = true; - res = bpf_val_to_ring_len(data, 0, tuple_size); + if(retval != 0 && retval != -EINPROGRESS) { + res = bpf_push_empty_param(data); + } else { + uint32_t tuple_size = 0; + if(push_socktuple) { + /* Use the file descriptor (and possibly the sockaddr) to obtain the socket tuple. + * The socket tuple is stored into the provided temp area. */ + tuple_size = bpf_fd_to_socktuple(data, + fd, + ksockaddr, + usrsockaddr_len, + can_use_sockaddr_data, + false, + data->tmp_scratch + sizeof(struct sockaddr_storage)); + } + + data->curarg_already_on_frame = true; + res = bpf_val_to_ring_len(data, 0, tuple_size); + } CHECK_RES(res); /* Parameter 3: fd (type: PT_FD) */ - return bpf_push_s64_to_ring(data, fd); + res = bpf_push_s64_to_ring(data, fd); + CHECK_RES(res); + + long addr_size = 0; + if(can_use_sockaddr_data) { + /* Convert the fd into socket endpoint information. */ + addr_size = bpf_pack_addr(data, ksockaddr, usrsockaddr_len); + } + + /* Parameter 4: addr (type: PT_SOCKADDR) */ + data->curarg_already_on_frame = true; + return bpf_val_to_ring_len(data, 0, addr_size); } FILLER(sys_socketpair_x, true) { diff --git a/driver/event_table.c b/driver/event_table.c index a955abec79..87719d366c 100644 --- a/driver/event_table.c +++ b/driver/event_table.c @@ -184,16 +184,17 @@ const struct ppm_event_info g_event_info[] = { {"fd", PT_FD, PF_DEC}}}, [PPME_SOCKET_CONNECT_E] = {"connect", EC_NET | EC_SYSCALL, - EF_USES_FD | EF_MODIFIES_STATE, + EF_USES_FD | EF_MODIFIES_STATE | EF_TMP_CONVERTER_MANAGED, 2, {{"fd", PT_FD, PF_DEC}, {"addr", PT_SOCKADDR, PF_NA}}}, [PPME_SOCKET_CONNECT_X] = {"connect", EC_NET | EC_SYSCALL, - EF_USES_FD | EF_MODIFIES_STATE, - 3, + EF_USES_FD | EF_MODIFIES_STATE | EF_TMP_CONVERTER_MANAGED, + 4, {{"res", PT_ERRNO, PF_DEC}, {"tuple", PT_SOCKTUPLE, PF_NA}, - {"fd", PT_FD, PF_DEC}}}, + {"fd", PT_FD, PF_DEC}, + {"addr", PT_SOCKADDR, PF_NA}}}, [PPME_SOCKET_LISTEN_E] = {"listen", EC_NET | EC_SYSCALL, EF_USES_FD | EF_TMP_CONVERTER_MANAGED, diff --git a/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/connect.bpf.c b/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/connect.bpf.c index 3529280c93..25cfdd24cc 100644 --- a/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/connect.bpf.c +++ b/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/connect.bpf.c @@ -29,9 +29,9 @@ int BPF_PROG(connect_e, struct pt_regs *regs, long id) { auxmap__store_s64_param(auxmap, socket_fd); /* Parameter 2: addr (type: PT_SOCKADDR) */ - unsigned long sockaddr_ptr = args[1]; - uint16_t addrlen = (uint16_t)args[2]; - auxmap__store_sockaddr_param(auxmap, sockaddr_ptr, addrlen); + unsigned long usrsockaddr = args[1]; + uint16_t usrsockaddr_len = (uint16_t)args[2]; + auxmap__store_sockaddr_param(auxmap, usrsockaddr, usrsockaddr_len); /*=============================== COLLECT PARAMETERS ===========================*/ @@ -57,16 +57,17 @@ int BPF_PROG(connect_x, struct pt_regs *regs, long ret) { /*=============================== COLLECT PARAMETERS ===========================*/ - unsigned long args[2] = {0}; - extract__network_args(args, 2, regs); + unsigned long args[3] = {0}; + extract__network_args(args, 3, regs); int64_t socket_fd = (int64_t)(int32_t)args[0]; /* Parameter 1: res (type: PT_ERRNO) */ auxmap__store_s64_param(auxmap, ret); + struct sockaddr *usrsockaddr = (struct sockaddr *)args[1]; + /* Parameter 2: tuple (type: PT_SOCKTUPLE) */ if(ret == 0 || ret == -EINPROGRESS) { - struct sockaddr *usrsockaddr = (struct sockaddr *)args[1]; /* Notice: the following will push an empty parameter if * something goes wrong (e.g.: fd not valid). */ auxmap__store_socktuple_param(auxmap, (int32_t)socket_fd, OUTBOUND, usrsockaddr); @@ -77,6 +78,10 @@ int BPF_PROG(connect_x, struct pt_regs *regs, long ret) { /* Parameter 3: fd (type: PT_FD) */ auxmap__store_s64_param(auxmap, socket_fd); + /* Parameter 4: addr (type: PT_SOCKADDR) */ + uint16_t usrsockaddr_len = (uint16_t)args[2]; + auxmap__store_sockaddr_param(auxmap, (unsigned long)usrsockaddr, usrsockaddr_len); + /*=============================== COLLECT PARAMETERS ===========================*/ auxmap__finalize_event_header(auxmap); diff --git a/driver/ppm_fillers.c b/driver/ppm_fillers.c index 2398fed775..1182ab3120 100644 --- a/driver/ppm_fillers.c +++ b/driver/ppm_fillers.c @@ -1726,10 +1726,13 @@ int f_sys_connect_e(struct event_filler_arguments *args) { if(usrsockaddr != NULL && usrsockaddr_len != 0) { /* Copy the address into kernel memory. */ - res = addr_to_kernel(usrsockaddr, val, (struct sockaddr *)&address); + res = addr_to_kernel(usrsockaddr, usrsockaddr_len, (struct sockaddr *)&address); if(likely(res >= 0)) { /* Convert the fd into socket endpoint information. */ - addr_size = pack_addr((struct sockaddr *)&address, val, targetbuf, STR_STORAGE_SIZE); + addr_size = pack_addr((struct sockaddr *)&address, + usrsockaddr_len, + targetbuf, + STR_STORAGE_SIZE); } } @@ -1750,63 +1753,63 @@ int f_sys_connect_x(struct event_filler_arguments *args) { struct sockaddr_storage address; struct sockaddr *ksockaddr = NULL; unsigned long sockaddr_len = 0; - bool use_sockaddr = false; + bool can_use_sockaddr_data = false; char *targetbuf = args->str_storage; - uint16_t tuple_size = 0; + uint16_t tuple_size = 0, addr_size = 0; /* 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); + CHECK_RES(res); + /* Get socket file descriptor, sockaddr pointer and length. */ syscall_get_arguments_deprecated(args, 0, 1, &val); fd = (int64_t)(int32_t)val; - - if(retval != 0 && retval != -EINPROGRESS) { - /* Parameter 2: tuple (type: PT_SOCKTUPLE) */ - res = push_empty_param(args); - CHECK_RES(res); - - /* Parameter 3: fd (type: PT_FD) */ - res = val_to_ring(args, fd, 0, false, 0); - CHECK_RES(res); - - return add_sentinel(args); - } - - /* Get the address */ syscall_get_arguments_deprecated(args, 1, 1, &val); usrsockaddr = (struct sockaddr __user *)val; - - /* Get the address len */ syscall_get_arguments_deprecated(args, 2, 1, &usrsockaddr_len); + /* Copy the user-provided sockaddr into kernel memory, if possible. */ if(usrsockaddr != NULL && usrsockaddr_len != 0) { - /* Copy the address into kernel memory */ res = addr_to_kernel(usrsockaddr, usrsockaddr_len, (struct sockaddr *)&address); if(likely(res >= 0)) { ksockaddr = (struct sockaddr *)&address; sockaddr_len = usrsockaddr_len; - use_sockaddr = true; + can_use_sockaddr_data = true; } } - /* Convert the fd into socket endpoint information */ - tuple_size = fd_to_socktuple((int)fd, - ksockaddr, - sockaddr_len, - use_sockaddr, - false, - targetbuf, - STR_STORAGE_SIZE); - /* Parameter 2: tuple (type: PT_SOCKTUPLE) */ - res = val_to_ring(args, (uint64_t)(unsigned long)targetbuf, tuple_size, false, 0); + if(retval != 0 && retval != -EINPROGRESS) { + res = push_empty_param(args); + } else { + /* Use the file descriptor (and possibly the sockaddr) to obtain the socket tuple. + * The socket tuple is stored into the provided target buffer. */ + tuple_size = fd_to_socktuple((int)fd, + ksockaddr, + sockaddr_len, + can_use_sockaddr_data, + false, + targetbuf, + STR_STORAGE_SIZE); + + res = val_to_ring(args, (uint64_t)(unsigned long)targetbuf, tuple_size, false, 0); + } CHECK_RES(res); /* Parameter 3: fd (type: PT_FD) */ res = val_to_ring(args, fd, 0, false, 0); CHECK_RES(res); + if(can_use_sockaddr_data) { + /* Encode the address and store it into the target buffer. */ + addr_size = pack_addr(ksockaddr, sockaddr_len, targetbuf, STR_STORAGE_SIZE); + } + + /* Parameter 2: addr (type: PT_SOCKADDR) */ + res = val_to_ring(args, (uint64_t)targetbuf, addr_size, false, 0); + CHECK_RES(res); + return add_sentinel(args); } diff --git a/test/drivers/test_suites/syscall_exit_suite/connect_x.cpp b/test/drivers/test_suites/syscall_exit_suite/connect_x.cpp index 82bb92d9bf..6e99788404 100644 --- a/test/drivers/test_suites/syscall_exit_suite/connect_x.cpp +++ b/test/drivers/test_suites/syscall_exit_suite/connect_x.cpp @@ -74,9 +74,12 @@ TEST(SyscallExit, connectX_INET) { /* Parameter 3: fd (type: PT_FD) */ evt_test->assert_numeric_param(3, (int64_t)client_socket_fd); + /* Parameter 4: addr (type: PT_SOCKADDR) */ + evt_test->assert_addr_info_inet_param(4, PPM_AF_INET, IPV4_SERVER, IPV4_PORT_SERVER_STRING); + /*=============================== ASSERT PARAMETERS ===========================*/ - evt_test->assert_num_params_pushed(3); + evt_test->assert_num_params_pushed(4); } TEST(SyscallExit, connectX_INET6) { @@ -146,9 +149,12 @@ TEST(SyscallExit, connectX_INET6) { /* Parameter 3: fd (type: PT_FD) */ evt_test->assert_numeric_param(3, (int64_t)client_socket_fd); + /* Parameter 4: addr (type: PT_SOCKADDR) */ + evt_test->assert_addr_info_inet6_param(4, PPM_AF_INET6, IPV6_SERVER, IPV6_PORT_SERVER_STRING); + /*=============================== ASSERT PARAMETERS ===========================*/ - evt_test->assert_num_params_pushed(3); + evt_test->assert_num_params_pushed(4); } #ifdef __NR_unlinkat @@ -235,9 +241,12 @@ TEST(SyscallExit, connectX_UNIX) { /* Parameter 3: fd (type: PT_FD) */ evt_test->assert_numeric_param(3, (int64_t)client_socket_fd); + /* Parameter 4: addr (type: PT_SOCKADDR) */ + evt_test->assert_addr_info_unix_param(4, PPM_AF_UNIX, server_symlink); + /*=============================== ASSERT PARAMETERS ===========================*/ - evt_test->assert_num_params_pushed(3); + evt_test->assert_num_params_pushed(4); } #endif /* __NR_unlinkat */ @@ -279,9 +288,12 @@ TEST(SyscallExit, connectX_failure) { /* Parameter 3: fd (type: PT_FD) */ evt_test->assert_numeric_param(3, (int64_t)mock_fd); + /* Parameter 4: addr (type: PT_SOCKADDR) */ + evt_test->assert_empty_param(4); + /*=============================== ASSERT PARAMETERS ===========================*/ - evt_test->assert_num_params_pushed(3); + evt_test->assert_num_params_pushed(4); } TEST(SyscallExit, connectX_failure_ECONNREFUSED) { @@ -340,9 +352,12 @@ TEST(SyscallExit, connectX_failure_ECONNREFUSED) { /* Parameter 3: fd (type: PT_FD) */ evt_test->assert_numeric_param(3, (int64_t)client_socket_fd); + /* Parameter 4: addr (type: PT_SOCKADDR) */ + evt_test->assert_addr_info_inet_param(4, PPM_AF_INET, IPV4_SERVER, IPV4_PORT_SERVER_STRING); + /*=============================== ASSERT PARAMETERS ===========================*/ - evt_test->assert_num_params_pushed(3); + evt_test->assert_num_params_pushed(4); } TEST(SyscallExit, connectX_failure_EINPROGRESS) { @@ -422,8 +437,11 @@ TEST(SyscallExit, connectX_failure_EINPROGRESS) { /* Parameter 3: fd (type: PT_FD) */ evt_test->assert_numeric_param(3, (int64_t)client_socket_fd); + /* Parameter 4: addr (type: PT_SOCKADDR) */ + evt_test->assert_addr_info_inet_param(4, PPM_AF_INET, IPV4_SERVER, IPV4_PORT_SERVER_STRING); + /*=============================== ASSERT PARAMETERS ===========================*/ - evt_test->assert_num_params_pushed(3); + evt_test->assert_num_params_pushed(4); } #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 4b2e00d3b1..0ce8727bc8 100644 --- a/test/drivers/test_suites/syscall_exit_suite/socketcall_x.cpp +++ b/test/drivers/test_suites/syscall_exit_suite/socketcall_x.cpp @@ -220,9 +220,12 @@ TEST(SyscallExit, socketcall_connectX) { /* Parameter 3: fd (type: PT_FD) */ evt_test->assert_numeric_param(3, (int64_t)client_socket_fd); + /* Parameter 4: addr (type: PT_SOCKADDR) */ + evt_test->assert_addr_info_inet_param(4, PPM_AF_INET, IPV4_SERVER, IPV4_PORT_SERVER_STRING); + /*=============================== ASSERT PARAMETERS ===========================*/ - evt_test->assert_num_params_pushed(3); + evt_test->assert_num_params_pushed(4); } #endif diff --git a/test/e2e/tests/test_event_generator/test_network_activity.py b/test/e2e/tests/test_event_generator/test_network_activity.py index e76b7eb99e..893b64d22b 100644 --- a/test/e2e/tests/test_event_generator/test_network_activity.py +++ b/test/e2e/tests/test_event_generator/test_network_activity.py @@ -43,7 +43,8 @@ def test_network_activity(sinsp, run_containers: dict): }, { "container.id": generator_id, - "evt.args": SinspField.regex_field(fr'^res=0 tuple={ipv4_regex}->10\.2\.3\.4:8192 fd=3\(<4u>{ipv4_regex}->10\.2\.3\.4:8192\)$'), + "evt.args": SinspField.regex_field( + fr'^res=0 tuple={ipv4_regex}->10\.2\.3\.4:8192 fd=3\(<4u>{ipv4_regex}->10\.2\.3\.4:8192\) addr=10.2.3.4:8192$'), "evt.category": "net", "evt.num": SinspField.numeric_field(), "evt.time": SinspField.numeric_field(), diff --git a/test/libscap/test_suites/engines/savefile/converter.cpp b/test/libscap/test_suites/engines/savefile/converter.cpp index e04362e244..c21abfa261 100644 --- a/test/libscap/test_suites/engines/savefile/converter.cpp +++ b/test/libscap/test_suites/engines/savefile/converter.cpp @@ -907,6 +907,101 @@ TEST_F(convert_event_test, PPME_SOCKET_BIND_X_to_3_params_with_enter) { fd)); } +//////////////////////////// +// CONNECT +//////////////////////////// + +TEST_F(convert_event_test, PPME_SOCKET_CONNECT_E_store) { + constexpr uint64_t ts = 12; + constexpr int64_t tid = 25; + + constexpr int64_t fd = 25; + struct sockaddr_in sockaddr = {}; + sockaddr.sin_family = AF_INET; + sockaddr.sin_port = htons(1234); + sockaddr.sin_addr.s_addr = htonl(INADDR_ANY); + + const auto evt = create_safe_scap_event(ts, + tid, + PPME_SOCKET_CONNECT_E, + 2, + fd, + scap_const_sized_buffer{&sockaddr, sizeof(sockaddr)}); + assert_single_conversion_skip(evt); + assert_event_storage_presence(evt); +} + +TEST_F(convert_event_test, PPME_SOCKET_CONNECT_X_3_to_4_params_no_enter) { + constexpr uint64_t ts = 12; + constexpr int64_t tid = 25; + + constexpr int64_t res = 89; + constexpr char tuple[] = "tuple"; + constexpr int64_t fd = 25; + + // Defaulted + constexpr uint8_t addr = PPM_AF_UNSPEC; + + assert_single_conversion_success( + conversion_result::CONVERSION_COMPLETED, + create_safe_scap_event(ts, + tid, + PPME_SOCKET_CONNECT_X, + 3, + res, + scap_const_sized_buffer{tuple, sizeof(tuple)}, + fd), + create_safe_scap_event(ts, + tid, + PPME_SOCKET_CONNECT_X, + 4, + res, + scap_const_sized_buffer{tuple, sizeof(tuple)}, + fd, + scap_const_sized_buffer{&addr, sizeof(addr)})); +} + +TEST_F(convert_event_test, PPME_SOCKET_CONNECT_X_3_to_4_params_with_enter) { + constexpr uint64_t ts = 12; + constexpr int64_t tid = 25; + + constexpr int64_t fd = 25; + struct sockaddr_in sockaddr = {}; + sockaddr.sin_family = AF_INET; + sockaddr.sin_port = htons(1234); + sockaddr.sin_addr.s_addr = htonl(INADDR_ANY); + constexpr int64_t res = 89; + constexpr char tuple[] = "tuple"; + + // After the first conversion we should have the storage + const auto evt = create_safe_scap_event(ts, + tid, + PPME_SOCKET_CONNECT_E, + 2, + fd, + scap_const_sized_buffer{&sockaddr, sizeof(sockaddr)}); + 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_CONNECT_X, + 3, + res, + scap_const_sized_buffer{tuple, sizeof(tuple)}, + fd), + create_safe_scap_event(ts, + tid, + PPME_SOCKET_CONNECT_X, + 4, + res, + scap_const_sized_buffer{tuple, sizeof(tuple)}, + fd, + scap_const_sized_buffer{&sockaddr, sizeof(sockaddr)})); +} + //////////////////////////// // SOCKET //////////////////////////// diff --git a/userspace/libscap/engine/gvisor/fillers.cpp b/userspace/libscap/engine/gvisor/fillers.cpp index db66899fdf..eca028670c 100644 --- a/userspace/libscap/engine/gvisor/fillers.cpp +++ b/userspace/libscap/engine/gvisor/fillers.cpp @@ -757,15 +757,17 @@ int32_t fill_event_connect_x(scap_sized_buffer scap_buf, char* scap_err, int64_t res, scap_const_sized_buffer tuple, - int64_t fd) { + int64_t fd, + scap_const_sized_buffer addr) { return scap_event_encode_params(scap_buf, event_size, scap_err, PPME_SOCKET_CONNECT_X, - 3, + 4, res, tuple, // local addr hardcoded 0 -- INVALID - fd); + fd, + addr); } // PPME_SYSCALL_SOCKET_E diff --git a/userspace/libscap/engine/gvisor/fillers.h b/userspace/libscap/engine/gvisor/fillers.h index 64699d8bc1..425cd6d67d 100644 --- a/userspace/libscap/engine/gvisor/fillers.h +++ b/userspace/libscap/engine/gvisor/fillers.h @@ -251,7 +251,8 @@ int32_t fill_event_connect_x(scap_sized_buffer scap_buf, char* scap_err, int64_t res, scap_const_sized_buffer tuple, - int64_t fd); + int64_t fd, + scap_const_sized_buffer addr); int32_t fill_event_socket_e(scap_sized_buffer scap_buf, size_t* event_size, diff --git a/userspace/libscap/engine/gvisor/parsers.cpp b/userspace/libscap/engine/gvisor/parsers.cpp index 1e504cc16c..689e99824c 100644 --- a/userspace/libscap/engine/gvisor/parsers.cpp +++ b/userspace/libscap/engine/gvisor/parsers.cpp @@ -697,13 +697,14 @@ static parse_result parse_connect(uint32_t id, return ret; } - ret.status = - scap_gvisor::fillers::fill_event_connect_x(scap_buf, - &ret.size, - scap_err, - gvisor_evt.exit().result(), - scap_const_sized_buffer{targetbuf, size}, - gvisor_evt.fd()); + ret.status = scap_gvisor::fillers::fill_event_connect_x( + scap_buf, + &ret.size, + scap_err, + gvisor_evt.exit().result(), + scap_const_sized_buffer{targetbuf, size}, + gvisor_evt.fd(), + scap_const_sized_buffer{targetbuf, size}); } else { char targetbuf[socktuple_buffer_size]; diff --git a/userspace/libscap/engine/savefile/converter/converter.cpp b/userspace/libscap/engine/savefile/converter/converter.cpp index 288dedc854..35f187752e 100644 --- a/userspace/libscap/engine/savefile/converter/converter.cpp +++ b/userspace/libscap/engine/savefile/converter/converter.cpp @@ -127,6 +127,7 @@ static inline uint8_t get_size_bytes_from_type(enum ppm_param_type t) { case PT_FLAGS8: case PT_ENUMFLAGS8: case PT_SIGTYPE: + case PT_SOCKADDR: // Sockaddr default parameter is a single-byte PPM_AF_UNSPEC family value. return 1; case PT_INT16: @@ -157,7 +158,6 @@ static inline uint8_t get_size_bytes_from_type(enum ppm_param_type t) { case PT_BYTEBUF: case PT_CHARBUF: - case PT_SOCKADDR: case PT_SOCKTUPLE: case PT_FDLIST: case PT_FSPATH: @@ -179,24 +179,38 @@ static inline uint8_t get_size_bytes_from_type(enum ppm_param_type t) { // This writes len + the param static void push_default_parameter(scap_evt *evt, uint16_t *params_offset, uint8_t param_num) { // Please ensure that `new_evt->type` is already the final type you want to obtain. - // Otherwise we will access the wrong entry in the event table. - const struct ppm_event_info *event_info = &(g_event_info[evt->type]); - uint16_t len = get_size_bytes_from_type(event_info->params[param_num].type); - uint16_t lens_offset = sizeof(scap_evt) + param_num * sizeof(uint16_t); + // Otherwise, we will access the wrong entry in the event table. + const struct ppm_event_info *event_info = &g_event_info[evt->type]; + const auto param_type = event_info->params[param_num].type; + const uint16_t len = get_size_bytes_from_type(param_type); + const uint16_t lens_offset = sizeof(scap_evt) + param_num * sizeof(uint16_t); PRINT_MESSAGE( "push default param (%d, type: %d) with len (%d) at {params_offest (%d), " "lens_offset (%d)}\n", param_num, - event_info->params[param_num].type, + param_type, len, *params_offset, lens_offset); - // The default param will be always 0 so we just need to copy the right number of 0 bytes. + // The default param will be always 0 (apart from some exception accounted below), so we just + // need to copy the right number of 0 bytes. // `uint64_t` should be enough for all the types considering that types like CHARBUF, BYTEBUF - // have `len==0` + // have `len==0`. uint64_t val = 0; + + // Account for some specific params having custom default values. + switch(param_type) { + case PT_SOCKADDR: { + val = PPM_AF_UNSPEC; + break; + } + default: { + break; + } + } + memcpy((char *)evt + *params_offset, (char *)&val, len); *params_offset += len; memcpy((char *)evt + lens_offset, &len, sizeof(uint16_t)); diff --git a/userspace/libscap/engine/savefile/converter/table.cpp b/userspace/libscap/engine/savefile/converter/table.cpp index ed26106395..e62eda02d3 100644 --- a/userspace/libscap/engine/savefile/converter/table.cpp +++ b/userspace/libscap/engine/savefile/converter/table.cpp @@ -105,6 +105,14 @@ const std::unordered_map g_conversion_table = { {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}})}, + /*====================== CONNECT ======================*/ + {conversion_key{PPME_SOCKET_CONNECT_E, 1}, + conversion_info().action(C_ACTION_ADD_PARAMS).instrs({{C_INSTR_FROM_DEFAULT, 0}})}, + {conversion_key{PPME_SOCKET_CONNECT_E, 2}, conversion_info().action(C_ACTION_STORE)}, + {conversion_key{PPME_SOCKET_CONNECT_X, 2}, + conversion_info().action(C_ACTION_ADD_PARAMS).instrs({{C_INSTR_FROM_ENTER, 0}})}, + {conversion_key{PPME_SOCKET_CONNECT_X, 3}, + conversion_info().action(C_ACTION_ADD_PARAMS).instrs({{C_INSTR_FROM_ENTER, 1}})}, /*====================== SOCKET ======================*/ {conversion_key{PPME_SOCKET_SOCKET_E, 3}, conversion_info().action(C_ACTION_STORE)}, {conversion_key{PPME_SOCKET_SOCKET_X, 1}, diff --git a/userspace/libscap/scap.h b/userspace/libscap/scap.h index d9f7bae719..7330256903 100644 --- a/userspace/libscap/scap.h +++ b/userspace/libscap/scap.h @@ -102,7 +102,7 @@ struct scap_vtable; // and handle the result // #define SCAP_MINIMUM_DRIVER_API_VERSION PPM_API_VERSION(8, 0, 0) -#define SCAP_MINIMUM_DRIVER_SCHEMA_VERSION PPM_API_VERSION(3, 64, 0) +#define SCAP_MINIMUM_DRIVER_SCHEMA_VERSION PPM_API_VERSION(3, 65, 0) // // This is the dimension we used before introducing the variable buffer size. diff --git a/userspace/libscap/scap_event.c b/userspace/libscap/scap_event.c index 6e753daabc..03859c0b53 100644 --- a/userspace/libscap/scap_event.c +++ b/userspace/libscap/scap_event.c @@ -568,6 +568,7 @@ int get_exit_event_fd_location(ppm_event_code etype) { case PPME_SYSCALL_SPLICE_X: case PPME_SYSCALL_WRITEV_X: case PPME_SYSCALL_PWRITEV_X: + case PPME_SOCKET_CONNECT_X: location = 2; break; case PPME_SOCKET_RECVFROM_X: diff --git a/userspace/libscap/scap_print_event.c b/userspace/libscap/scap_print_event.c index df5543e76e..cd3053dc86 100644 --- a/userspace/libscap/scap_print_event.c +++ b/userspace/libscap/scap_print_event.c @@ -156,7 +156,7 @@ static void print_parameter(int16_t num_param, scap_evt *ev, uint16_t offset) { break; default: - printf("- error\n"); + printf("- error\n"); break; } break; diff --git a/userspace/libsinsp/parsers.cpp b/userspace/libsinsp/parsers.cpp index 2fc3236cfb..b4909866c9 100644 --- a/userspace/libsinsp/parsers.cpp +++ b/userspace/libsinsp/parsers.cpp @@ -2697,91 +2697,82 @@ void sinsp_parser::parse_bind_exit(sinsp_evt &evt, sinsp_parser_verdict &verdict * Register a socket in pending state */ void sinsp_parser::parse_connect_enter(sinsp_evt &evt) const { - const sinsp_evt_param *parinfo; - const char *parstr; - uint8_t *packed_data; - - if(evt.get_fd_info() == nullptr) { + const auto fdinfo = evt.get_fd_info(); + if(fdinfo == nullptr) { return; } if(m_track_connection_status) { - evt.get_fd_info()->set_socket_pending(); + fdinfo->set_socket_pending(); } - if(evt.get_num_params() < 2) { - switch(evt.get_fd_info()->m_type) { - case SCAP_FD_IPV4_SOCK: - evt.get_fd_info()->m_sockinfo.m_ipv4info.m_fields.m_dip = 0; - evt.get_fd_info()->m_sockinfo.m_ipv4info.m_fields.m_dport = 0; - break; - case SCAP_FD_IPV6_SOCK: - evt.get_fd_info()->m_sockinfo.m_ipv6info.m_fields.m_dip = ipv6addr::empty_address; - evt.get_fd_info()->m_sockinfo.m_ipv6info.m_fields.m_dport = 0; - break; - default: - break; - } - sinsp_utils::sockinfo_to_str(&evt.get_fd_info()->m_sockinfo, - evt.get_fd_info()->m_type, - &evt.get_paramstr_storage()[0], - (uint32_t)evt.get_paramstr_storage().size(), - m_hostname_and_port_resolution_enabled); - - evt.get_fd_info()->m_name = &evt.get_paramstr_storage()[0]; - return; - } + auto &sockinfo = fdinfo->m_sockinfo; - parinfo = evt.get_param(1); - if(parinfo->m_len == 0) { - // + const sinsp_evt_param *addr_param = evt.get_param(1); + if(addr_param->m_len == 0) { // Address can be nullptr: // sk is a TCP fastopen active socket and // TCP_FASTOPEN_CONNECT sockopt is set and // we already have a valid cookie for this socket. - // return; } - packed_data = (uint8_t *)parinfo->m_val; + // TODO(ekoops): remove const_cast once we adapt used APIs to accept const pointers/references. + auto packed_data = const_cast(reinterpret_cast(addr_param->m_val)); - uint8_t family = *packed_data; - - if(family == PPM_AF_INET) { - evt.get_fd_info()->m_type = SCAP_FD_IPV4_SOCK; - memcpy(&evt.get_fd_info()->m_sockinfo.m_ipv4info.m_fields.m_dip, - packed_data + 1, - sizeof(uint32_t)); - memcpy(&evt.get_fd_info()->m_sockinfo.m_ipv4info.m_fields.m_dport, - packed_data + 5, - sizeof(uint16_t)); - } else if(family == PPM_AF_INET6) { + switch(const uint8_t family = *packed_data; family) { + case PPM_AF_INET: { + fdinfo->m_type = SCAP_FD_IPV4_SOCK; + memcpy(&sockinfo.m_ipv4info.m_fields.m_dip, packed_data + 1, sizeof(uint32_t)); + memcpy(&sockinfo.m_ipv4info.m_fields.m_dport, packed_data + 5, sizeof(uint16_t)); + break; + } + case PPM_AF_INET6: { uint16_t port; memcpy(&port, packed_data + 17, sizeof(uint16_t)); uint8_t *ip = packed_data + 1; if(sinsp_utils::is_ipv4_mapped_ipv6(ip)) { - evt.get_fd_info()->m_type = SCAP_FD_IPV4_SOCK; - memcpy(&evt.get_fd_info()->m_sockinfo.m_ipv4info.m_fields.m_dip, - packed_data + 13, - sizeof(uint32_t)); - evt.get_fd_info()->m_sockinfo.m_ipv4info.m_fields.m_dport = port; + fdinfo->m_type = SCAP_FD_IPV4_SOCK; + memcpy(&sockinfo.m_ipv4info.m_fields.m_dip, packed_data + 13, sizeof(uint32_t)); + sockinfo.m_ipv4info.m_fields.m_dport = port; } else { - evt.get_fd_info()->m_type = SCAP_FD_IPV6_SOCK; - evt.get_fd_info()->m_sockinfo.m_ipv6info.m_fields.m_dport = port; - memcpy(evt.get_fd_info()->m_sockinfo.m_ipv6info.m_fields.m_dip.m_b, - ip, - sizeof(ipv6addr)); + fdinfo->m_type = SCAP_FD_IPV6_SOCK; + sockinfo.m_ipv6info.m_fields.m_dport = port; + memcpy(sockinfo.m_ipv6info.m_fields.m_dip.m_b, ip, sizeof(ipv6addr)); } - } else { - // - // Add the friendly name to the fd info - // - evt.get_fd_info()->m_name = evt.get_param_as_str(1, &parstr, sinsp_evt::PF_SIMPLE); + break; + } + case PPM_AF_UNSPEC: { + switch(fdinfo->m_type) { + case SCAP_FD_IPV4_SOCK: + sockinfo.m_ipv4info.m_fields.m_dip = 0; + sockinfo.m_ipv4info.m_fields.m_dport = 0; + break; + case SCAP_FD_IPV6_SOCK: + sockinfo.m_ipv6info.m_fields.m_dip = ipv6addr::empty_address; + sockinfo.m_ipv6info.m_fields.m_dport = 0; + break; + default: + break; + } + sinsp_utils::sockinfo_to_str(&sockinfo, + fdinfo->m_type, + &evt.get_paramstr_storage()[0], + (uint32_t)evt.get_paramstr_storage().size(), + m_hostname_and_port_resolution_enabled); + + fdinfo->m_name = &evt.get_paramstr_storage()[0]; + return; + } + default: { + // Add the friendly name to the fd info. + const char *parstr; + fdinfo->m_name = evt.get_param_as_str(1, &parstr, sinsp_evt::PF_SIMPLE); + break; + } } - // - // If there's a listener callback and we're tracking connection status, invoke it - // + // If there's a listener callback, and we're tracking connection status, invoke it. if(m_track_connection_status && m_observer) { m_observer->on_connect(&evt, packed_data); } @@ -2878,44 +2869,33 @@ inline void sinsp_parser::fill_client_socket_info(sinsp_evt &evt, } void sinsp_parser::parse_connect_exit(sinsp_evt &evt, sinsp_parser_verdict &verdict) const { - const sinsp_evt_param *parinfo; - int64_t retval; - int64_t fd; - bool force_overwrite_stale_data = false; - if(evt.get_tinfo() == nullptr) { return; } + bool force_overwrite_stale_data = false; + if(evt.get_fd_info() == nullptr) { // Perhaps we dropped the connect enter event. // try harder to be resilient. - if(evt.get_num_params() > 2) { - fd = evt.get_param(2)->as(); - if(fd < 0) { - // - // Accept failure. - // Do nothing. - // - return; - } - evt.get_tinfo()->m_lastevent_fd = fd; - evt.set_fd_info(evt.get_tinfo()->get_fd(evt.get_tinfo()->m_lastevent_fd)); - if(evt.get_fd_info() == nullptr) { - // Ok this is a completely new fd; - // we probably lost too many events. - // Bye. - return; - } - // ok we got stale data; we probably missed the connect enter event on this thread. - // Force overwrite existing fdinfo socket data - force_overwrite_stale_data = true; - } else { + const int64_t fd = evt.get_param(2)->as(); + if(fd < 0) { + // Accept failure. Do nothing. + return; + } + evt.get_tinfo()->m_lastevent_fd = fd; + evt.set_fd_info(evt.get_tinfo()->get_fd(evt.get_tinfo()->m_lastevent_fd)); + if(evt.get_fd_info() == nullptr) { + // Ok this is a completely new fd; we probably lost too many events. + // Bye. return; } + // ok we got stale data; we probably missed the connect enter event on this thread. + // Force overwrite existing fdinfo socket data + force_overwrite_stale_data = true; } - retval = evt.get_syscall_return_value(); + const int64_t retval = evt.get_syscall_return_value(); if(m_track_connection_status) { if(retval == -SE_EINPROGRESS) { @@ -2928,32 +2908,28 @@ void sinsp_parser::parse_connect_exit(sinsp_evt &evt, sinsp_parser_verdict &verd } else { if(retval < 0 && retval != -SE_EINPROGRESS) { return; - } else { - evt.get_fd_info()->set_socket_connected(); } + evt.get_fd_info()->set_socket_connected(); } - parinfo = evt.get_param(1); - if(parinfo->m_len == 0) { - // + const sinsp_evt_param *tuple_param = evt.get_param(1); + if(tuple_param->m_len == 0) { // Address can be nullptr: // sk is a TCP fastopen active socket and // TCP_FASTOPEN_CONNECT sockopt is set and // we already have a valid cookie for this socket. - // return; } - uint8_t *packed_data = (uint8_t *)parinfo->m_val; + // TODO(ekoops): remove const_cast once we adapt used APIs to accept const pointers/references. + auto packed_data = const_cast(reinterpret_cast(tuple_param->m_val)); fill_client_socket_info(evt, packed_data, force_overwrite_stale_data, m_hostname_and_port_resolution_enabled); - // // If there's a listener, add a callback to later invoke it. - // if(m_observer) { verdict.add_post_process_cbs([packed_data](sinsp_observer *observer, sinsp_evt *evt) { observer->on_connect(evt, packed_data); diff --git a/userspace/libsinsp/test/events_net.ut.cpp b/userspace/libsinsp/test/events_net.ut.cpp index bdcc75207b..0456844348 100644 --- a/userspace/libsinsp/test/events_net.ut.cpp +++ b/userspace/libsinsp/test/events_net.ut.cpp @@ -121,13 +121,15 @@ TEST_F(sinsp_with_test_input, net_ipv4_connect) { std::vector socktuple = test_utils::pack_socktuple(reinterpret_cast(&client), reinterpret_cast(&server)); - evt = add_event_advance_ts(increasing_ts(), - 1, - PPME_SOCKET_CONNECT_X, - 3, - (int64_t)0, - scap_const_sized_buffer{socktuple.data(), socktuple.size()}, - sinsp_test_input::socket_params::default_fd); + evt = add_event_advance_ts( + increasing_ts(), + 1, + PPME_SOCKET_CONNECT_X, + 4, + (int64_t)0, + scap_const_sized_buffer{socktuple.data(), socktuple.size()}, + sinsp_test_input::socket_params::default_fd, + scap_const_sized_buffer{server_sockaddr.data(), server_sockaddr.size()}); fdinfo = evt->get_fd_info(); ASSERT_NE(fdinfo, nullptr); @@ -195,13 +197,15 @@ TEST_F(sinsp_with_test_input, net_ipv4_connect_with_intermediate_event) { sinsp_test_input::socket_params::default_fd, (uint32_t)102, scap_const_sized_buffer{socktuple.data(), socktuple.size()}); - evt = add_event_advance_ts(increasing_ts(), - 1, - PPME_SOCKET_CONNECT_X, - 3, - return_value, - scap_const_sized_buffer{socktuple.data(), socktuple.size()}, - sinsp_test_input::socket_params::default_fd); + evt = add_event_advance_ts( + increasing_ts(), + 1, + PPME_SOCKET_CONNECT_X, + 4, + return_value, + scap_const_sized_buffer{socktuple.data(), socktuple.size()}, + sinsp_test_input::socket_params::default_fd, + scap_const_sized_buffer{server_sockaddr.data(), server_sockaddr.size()}); /* We are able to recover the fdinfo in the connect exit event even when interleaved */ auto fdinfo = evt->get_fd_info(); @@ -239,13 +243,15 @@ TEST_F(sinsp_with_test_input, net_ipv6_multiple_connects) { std::vector socktuple = test_utils::pack_socktuple(reinterpret_cast(&client), reinterpret_cast(&server1)); - evt = add_event_advance_ts(increasing_ts(), - 1, - PPME_SOCKET_CONNECT_X, - 3, - (int64_t)0, - scap_const_sized_buffer{socktuple.data(), socktuple.size()}, - sinsp_test_input::socket_params::default_fd); + evt = add_event_advance_ts( + increasing_ts(), + 1, + PPME_SOCKET_CONNECT_X, + 4, + (int64_t)0, + scap_const_sized_buffer{socktuple.data(), socktuple.size()}, + sinsp_test_input::socket_params::default_fd, + scap_const_sized_buffer{server1_sockaddr.data(), server1_sockaddr.size()}); ASSERT_EQ(get_field_as_string(evt, "fd.name"), DEFAULT_IPV6_FDNAME); ASSERT_EQ(get_field_as_string(evt, "fd.connected"), "true"); @@ -290,13 +296,15 @@ TEST_F(sinsp_with_test_input, net_ipv6_multiple_connects) { socktuple = test_utils::pack_socktuple(reinterpret_cast(&client), reinterpret_cast(&server2)); - evt = add_event_advance_ts(increasing_ts(), - 1, - PPME_SOCKET_CONNECT_X, - 3, - (int64_t)0, - scap_const_sized_buffer{socktuple.data(), socktuple.size()}, - sinsp_test_input::socket_params::default_fd); + evt = add_event_advance_ts( + increasing_ts(), + 1, + PPME_SOCKET_CONNECT_X, + 4, + (int64_t)0, + scap_const_sized_buffer{socktuple.data(), socktuple.size()}, + sinsp_test_input::socket_params::default_fd, + scap_const_sized_buffer{server2_sockaddr.data(), server2_sockaddr.size()}); ASSERT_EQ(get_field_as_string(evt, "fd.name_changed"), "true"); std::string new_fd_name = std::string(DEFAULT_IPV6_CLIENT_STRING) + ":" + std::string(DEFAULT_CLIENT_PORT_STRING) + "->" + ipv6_server2 + ":" + @@ -508,13 +516,15 @@ TEST_F(sinsp_with_test_input, net_connect_exit_event_fails) { std::vector socktuple = test_utils::pack_socktuple(reinterpret_cast(&client), reinterpret_cast(&server)); - evt = add_event_advance_ts(increasing_ts(), - 1, - PPME_SOCKET_CONNECT_X, - 3, - (int64_t)0, - scap_const_sized_buffer{socktuple.data(), socktuple.size()}, - sinsp_test_input::socket_params::default_fd); + evt = add_event_advance_ts( + increasing_ts(), + 1, + PPME_SOCKET_CONNECT_X, + 4, + (int64_t)0, + scap_const_sized_buffer{socktuple.data(), socktuple.size()}, + sinsp_test_input::socket_params::default_fd, + scap_const_sized_buffer{server_sockaddr.data(), server_sockaddr.size()}); fdinfo = evt->get_fd_info(); ASSERT_NE(fdinfo, nullptr); @@ -537,13 +547,15 @@ TEST_F(sinsp_with_test_input, net_connect_exit_event_fails) { socktuple = test_utils::pack_socktuple(reinterpret_cast(&client), reinterpret_cast(&server2)); - evt = add_event_advance_ts(increasing_ts(), - 1, - PPME_SOCKET_CONNECT_X, - 3, - (int64_t)-2, - scap_const_sized_buffer{socktuple.data(), socktuple.size()}, - sinsp_test_input::socket_params::default_fd); + evt = add_event_advance_ts( + increasing_ts(), + 1, + PPME_SOCKET_CONNECT_X, + 4, + (int64_t)-2, + scap_const_sized_buffer{socktuple.data(), socktuple.size()}, + sinsp_test_input::socket_params::default_fd, + scap_const_sized_buffer{server_sockaddr.data(), server_sockaddr.size()}); /* Filterchecks will get an updated fdname since the extraction happens directly on the params, * while the fdinfo fdname is not updated. Ip and port of the new server are updated by the @@ -615,10 +627,11 @@ TEST_F(sinsp_with_test_input, net_connect_enter_event_is_empty) { add_event_advance_ts(increasing_ts(), 1, PPME_SOCKET_CONNECT_X, - 3, + 4, (int64_t)0, scap_const_sized_buffer{socktuple.data(), socktuple.size()}, - sinsp_test_input::socket_params::default_fd); + sinsp_test_input::socket_params::default_fd, + scap_const_sized_buffer{server_sockaddr.data(), server_sockaddr.size()}); /* Second connection with an empty sockaddr in the PPME_SOCKET_CONNECT_E event, new client and * new server */ @@ -646,10 +659,11 @@ TEST_F(sinsp_with_test_input, net_connect_enter_event_is_empty) { evt = add_event_advance_ts(increasing_ts(), 1, PPME_SOCKET_CONNECT_X, - 3, + 4, (int64_t)-2, scap_const_sized_buffer{socktuple.data(), socktuple.size()}, - sinsp_test_input::socket_params::default_fd); + sinsp_test_input::socket_params::default_fd, + null_buf); /* Only filterchecks will see the new tuple in the fdname all the rest is not updated */ std::string fdname = ipv4_client2 + ":" + port_client2_string + "->" + ipv4_server2 + ":" + @@ -699,19 +713,23 @@ TEST_F(sinsp_with_test_input, net_connect_enter_event_is_missing) { std::string ipv4_server = "152.40.111.222"; std::string port_server_string = "25632"; sockaddr_in server = test_utils::fill_sockaddr_in(port_server, ipv4_server.c_str()); + std::vector server_sockaddr = + test_utils::pack_sockaddr(reinterpret_cast(&server)); /* We dropped connect enter! */ std::vector socktuple = test_utils::pack_socktuple(reinterpret_cast(&client), reinterpret_cast(&server)); - evt = add_event_advance_ts(increasing_ts(), - 1, - PPME_SOCKET_CONNECT_X, - 3, - (int64_t)0, - scap_const_sized_buffer{socktuple.data(), socktuple.size()}, - sinsp_test_input::socket_params::default_fd); + evt = add_event_advance_ts( + increasing_ts(), + 1, + PPME_SOCKET_CONNECT_X, + 4, + (int64_t)0, + scap_const_sized_buffer{socktuple.data(), socktuple.size()}, + sinsp_test_input::socket_params::default_fd, + scap_const_sized_buffer{server_sockaddr.data(), server_sockaddr.size()}); /* Check that everything is updated anyway, even if we lost connect enter */ std::string fdname = @@ -740,56 +758,3 @@ TEST_F(sinsp_with_test_input, net_connect_enter_event_is_missing) { ASSERT_EQ(fdinfo->m_sockinfo.m_ipv4info.m_fields.m_dport, std::stoi(port_server_string)); ASSERT_EQ(fdinfo->m_sockinfo.m_ipv4info.m_fields.m_sport, std::stoi(port_client_string)); } - -/* - * Test that old connect exit event without the third `fd` argument - * were not able to load fd related data if connect enter was dropped. - */ -TEST_F(sinsp_with_test_input, net_connect_enter_event_is_missing_wo_fd_param_exit) { - add_default_init_thread(); - open_inspector(); - sinsp_evt* evt = NULL; - - generate_socket_events(sinsp_test_input::socket_params(PPM_AF_INET, SOCK_DGRAM)); - - int port_client = 12; - std::string ipv4_client = "80.9.11.45"; - std::string port_client_string = "12"; - sockaddr_in client = test_utils::fill_sockaddr_in(port_client, ipv4_client.c_str()); - - int port_server = 25632; - std::string ipv4_server = "152.40.111.222"; - std::string port_server_string = "25632"; - sockaddr_in server = test_utils::fill_sockaddr_in(port_server, ipv4_server.c_str()); - - /* We dropped connect enter! */ - - /* todo!: revisit this when we will manage CONNECT_X in scap files. - * We simulate an event from an old scap file, a connect exit event with just 2 params (no fd!) - */ - std::vector socktuple = - test_utils::pack_socktuple(reinterpret_cast(&client), - reinterpret_cast(&server)); - evt = add_event_advance_ts(increasing_ts(), - 1, - PPME_SOCKET_CONNECT_X, - 2, - (int64_t)0, - scap_const_sized_buffer{socktuple.data(), socktuple.size()}); - - /* We cannot recover the file descriptor from the enter event neither from the exit event */ - ASSERT_EQ(evt->get_fd_info(), nullptr); - - /* We recover this from the tuple */ - ASSERT_EQ(get_field_as_string(evt, "fd.name"), "80.9.11.45:12->152.40.111.222:25632"); - - /* Check that we are not able to load any info */ - ASSERT_FALSE(field_has_value(evt, "fd.sip")); - ASSERT_FALSE(field_has_value(evt, "fd.cip")); - ASSERT_FALSE(field_has_value(evt, "fd.rip")); - ASSERT_FALSE(field_has_value(evt, "fd.lip")); - ASSERT_FALSE(field_has_value(evt, "fd.cport")); - ASSERT_FALSE(field_has_value(evt, "fd.sport")); - ASSERT_FALSE(field_has_value(evt, "fd.lport")); - ASSERT_FALSE(field_has_value(evt, "fd.rport")); -} diff --git a/userspace/libsinsp/test/events_param.ut.cpp b/userspace/libsinsp/test/events_param.ut.cpp index 64e3d79fba..2f0f5af100 100644 --- a/userspace/libsinsp/test/events_param.ut.cpp +++ b/userspace/libsinsp/test/events_param.ut.cpp @@ -143,7 +143,8 @@ TEST_F(sinsp_with_test_input, sockaddr_empty_param) { sinsp_evt* evt = NULL; const sinsp_evt_param* param = NULL; - int64_t fd = 0; + constexpr int64_t res = 0; + constexpr int64_t fd = 3; /* `PPME_SOCKET_CONNECT_E` is a simple event that uses a `PT_SOCKADDR` */ scap_const_sized_buffer sockaddr_param; @@ -160,10 +161,11 @@ TEST_F(sinsp_with_test_input, sockaddr_empty_param) { evt = add_event_advance_ts(increasing_ts(), 1, PPME_SOCKET_CONNECT_X, - 3, - fd, + 4, + res, socktuple_param, - fd); + fd, + sockaddr_param); param = evt->get_param(1); ASSERT_EQ(param->m_len, 0); @@ -171,7 +173,7 @@ TEST_F(sinsp_with_test_input, sockaddr_empty_param) { scap_const_sized_buffer fdlist_param; fdlist_param.buf = NULL; fdlist_param.size = 0; - evt = add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_POLL_X, 2, fd, fdlist_param); + evt = add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_POLL_X, 2, res, fdlist_param); param = evt->get_param(1); ASSERT_EQ(param->m_len, 0); } diff --git a/userspace/libsinsp/test/filter_op_net_compare.ut.cpp b/userspace/libsinsp/test/filter_op_net_compare.ut.cpp index 8c6f6ed40a..9cc81a51bc 100644 --- a/userspace/libsinsp/test/filter_op_net_compare.ut.cpp +++ b/userspace/libsinsp/test/filter_op_net_compare.ut.cpp @@ -45,13 +45,15 @@ TEST_F(sinsp_with_test_input, net_ipv4_compare) { std::vector socktuple = test_utils::pack_socktuple(reinterpret_cast(&client), reinterpret_cast(&server)); - evt = add_event_advance_ts(increasing_ts(), - 1, - PPME_SOCKET_CONNECT_X, - 3, - return_value, - scap_const_sized_buffer{socktuple.data(), socktuple.size()}, - sinsp_test_input::socket_params::default_fd); + evt = add_event_advance_ts( + increasing_ts(), + 1, + PPME_SOCKET_CONNECT_X, + 4, + return_value, + scap_const_sized_buffer{socktuple.data(), socktuple.size()}, + sinsp_test_input::socket_params::default_fd, + scap_const_sized_buffer{server_sockaddr.data(), server_sockaddr.size()}); EXPECT_TRUE(eval_filter(evt, "fd.ip == 142.251.111.147")); EXPECT_TRUE(eval_filter(evt, "fd.sip == 142.251.111.147")); @@ -100,13 +102,15 @@ TEST_F(sinsp_with_test_input, net_ipv6_compare) { std::vector socktuple = test_utils::pack_socktuple(reinterpret_cast(&client), reinterpret_cast(&server1)); - evt = add_event_advance_ts(increasing_ts(), - 1, - PPME_SOCKET_CONNECT_X, - 3, - return_value, - scap_const_sized_buffer{socktuple.data(), socktuple.size()}, - sinsp_test_input::socket_params::default_fd); + evt = add_event_advance_ts( + increasing_ts(), + 1, + PPME_SOCKET_CONNECT_X, + 4, + return_value, + scap_const_sized_buffer{socktuple.data(), socktuple.size()}, + sinsp_test_input::socket_params::default_fd, + scap_const_sized_buffer{server1_sockaddr.data(), server1_sockaddr.size()}); EXPECT_TRUE(eval_filter(evt, "fd.ip == 2001:4860:4860::8888")); EXPECT_TRUE(eval_filter(evt, "fd.sip == 2001:4860:4860::8888")); diff --git a/userspace/libsinsp/test/filterchecks/mock.cpp b/userspace/libsinsp/test/filterchecks/mock.cpp index 937cabc663..fc8be1c2c2 100644 --- a/userspace/libsinsp/test/filterchecks/mock.cpp +++ b/userspace/libsinsp/test/filterchecks/mock.cpp @@ -364,13 +364,15 @@ TEST_F(sinsp_with_test_input, check_some_fd_fields) { std::vector socktuple = test_utils::pack_socktuple(reinterpret_cast(&client), reinterpret_cast(&server)); - auto evt = add_event_advance_ts(increasing_ts(), - 1, - PPME_SOCKET_CONNECT_X, - 3, - (int64_t)0, - scap_const_sized_buffer{socktuple.data(), socktuple.size()}, - sinsp_test_input::socket_params::default_fd); + auto evt = add_event_advance_ts( + increasing_ts(), + 1, + PPME_SOCKET_CONNECT_X, + 4, + (int64_t)0, + scap_const_sized_buffer{socktuple.data(), socktuple.size()}, + sinsp_test_input::socket_params::default_fd, + scap_const_sized_buffer{server_sockaddr.data(), server_sockaddr.size()}); { // fd.cip will extract an ipv6 we cannot compare it with an ipv4, so we expect false diff --git a/userspace/libsinsp/test/filterchecks/proc.cpp b/userspace/libsinsp/test/filterchecks/proc.cpp index dd343e8f45..3d016fd1c5 100644 --- a/userspace/libsinsp/test/filterchecks/proc.cpp +++ b/userspace/libsinsp/test/filterchecks/proc.cpp @@ -260,13 +260,15 @@ TEST_F(sinsp_with_test_input, PROC_FILTER_stdin_stdout_stderr) { std::vector socktuple = test_utils::pack_socktuple(reinterpret_cast(&client), reinterpret_cast(&server)); - evt = add_event_advance_ts(increasing_ts(), - 1, - PPME_SOCKET_CONNECT_X, - 3, - (int64_t)0, - scap_const_sized_buffer{socktuple.data(), socktuple.size()}, - sinsp_test_input::socket_params::default_fd); + evt = add_event_advance_ts( + increasing_ts(), + 1, + PPME_SOCKET_CONNECT_X, + 4, + (int64_t)0, + scap_const_sized_buffer{socktuple.data(), socktuple.size()}, + sinsp_test_input::socket_params::default_fd, + scap_const_sized_buffer{server_sockaddr.data(), server_sockaddr.size()}); // The socket is duped to stdin, stdout, stderr evt = add_event_advance_ts(increasing_ts(), diff --git a/userspace/libsinsp/test/parsers/parse_connect.cpp b/userspace/libsinsp/test/parsers/parse_connect.cpp index 14b624bc72..402de7f5f9 100644 --- a/userspace/libsinsp/test/parsers/parse_connect.cpp +++ b/userspace/libsinsp/test/parsers/parse_connect.cpp @@ -51,15 +51,21 @@ TEST_F(sinsp_with_test_input, CONNECT_parse_unix_socket) { ASSERT_EQ(fdinfo->m_name, ""); // We don't need the enter event! + const std::string sun_path{"/tmp/stream.sock"}; + sockaddr_un server = test_utils::fill_sockaddr_un(sun_path.c_str()); + std::vector server_sockaddr = + test_utils::pack_sockaddr(reinterpret_cast(&server)); std::vector socktuple = - test_utils::pack_unix_socktuple(0x9c758d0f, 0x9c758d0a, "/tmp/stream.sock"); - evt = add_event_advance_ts(increasing_ts(), - INIT_TID, - PPME_SOCKET_CONNECT_X, - 3, - (int64_t)0, - scap_const_sized_buffer{socktuple.data(), socktuple.size()}, - sinsp_test_input::socket_params::default_fd); + test_utils::pack_unix_socktuple(0x9c758d0f, 0x9c758d0a, sun_path.c_str()); + evt = add_event_advance_ts( + increasing_ts(), + INIT_TID, + PPME_SOCKET_CONNECT_X, + 4, + (int64_t)0, + scap_const_sized_buffer{socktuple.data(), socktuple.size()}, + sinsp_test_input::socket_params::default_fd, + scap_const_sized_buffer{server_sockaddr.data(), server_sockaddr.size()}); /* FDINFO associated with the event */ fdinfo = evt->get_fd_info(); diff --git a/userspace/libsinsp/test/scap_files/converter_tests.cpp b/userspace/libsinsp/test/scap_files/converter_tests.cpp index 2f0c2942be..6b3a6cfd00 100644 --- a/userspace/libsinsp/test/scap_files/converter_tests.cpp +++ b/userspace/libsinsp/test/scap_files/converter_tests.cpp @@ -64,6 +64,7 @@ TEST_F(scap_file_test, same_number_of_events) { {PPME_SYSCALL_LSEEK_E, 329}, {PPME_SYSCALL_LSEEK_X, 329}, {PPME_SYSCALL_WRITEV_E, 5}, {PPME_SYSCALL_WRITEV_X, 5}, {PPME_SYSCALL_FCNTL_E, 9817}, {PPME_SYSCALL_FCNTL_X, 9817}, + {PPME_SOCKET_CONNECT_E, 238}, {PPME_SOCKET_CONNECT_X, 238}, // Add further checks regarding the expected number of events in this scap file here. }); @@ -509,28 +510,73 @@ TEST_F(scap_file_test, socket_x_check_final_converted_event) { open_filename("scap_2013.scap"); // Inside the scap-file the event `515881` is the following: - // - type=PPME_SOCKET_SOCKET_E - // - ts=1380933088295478275 - // - tid=44106 - // - args=domain=2(AF_INET) type=524289 proto=0 - // - // And its corresponding enter event `511520` is the following: // - type=PPME_SOCKET_SOCKET_X // - ts=1380933088295552884 // - tid=44106, // - args=fd=19(<4>) // - uint64_t ts = 1380933088295552884; - int64_t tid = 44106; - int64_t fd = 19; - uint32_t domain = 2; - uint32_t type = 524289; - uint32_t proto = 0; + // And its corresponding enter event `511520` is the following: + // - type=PPME_SOCKET_SOCKET_E + // - ts=1380933088295478275 + // - tid=44106 + // - args=domain=2(AF_INET) type=524289 proto=0 + // + constexpr uint64_t ts = 1380933088295552884; + constexpr int64_t tid = 44106; + constexpr int64_t fd = 19; + constexpr uint32_t domain = 2; + constexpr uint32_t type = 524289; + constexpr uint32_t proto = 0; assert_event_presence( create_safe_scap_event(ts, tid, PPME_SOCKET_SOCKET_X, 4, fd, domain, type, proto)); } +//////////////////////////// +// CONNECT +//////////////////////////// + +// Compile out this test if test_utils helpers are not defined. +#if !defined(_WIN32) && !defined(__EMSCRIPTEN__) && !defined(__APPLE__) +TEST_F(scap_file_test, connect_x_check_final_converted_event) { + open_filename("kexec_arm64.scap"); + + // Inside the scap-file the event `907953` is the following: + // - type=PPME_SOCKET_CONNECT_X + // - ts=1687966734290916318 + // - tid=115186 + // - args=res=-101(ENETUNREACH) tuple=:::47437->2001:4860:4860::8888:53 fd=13(<6>) + // + // And its corresponding enter event `907952` is the following: + // - type=PPME_SOCKET_CONNECT_E + // - ts=1687966734290903534 + // - tid=115186 + // - args=fd=13(<6>) addr=2001:4860:4860::8888:53 + // + constexpr uint64_t ts = 1687966734290916318; + constexpr int64_t tid = 115186; + constexpr int64_t res = -101; + constexpr int64_t fd = 13; + sockaddr_in6 client_sockaddr = test_utils::fill_sockaddr_in6(47437, "::"); + sockaddr_in6 server_sockaddr = test_utils::fill_sockaddr_in6(53, "2001:4860:4860::8888"); + const std::vector tuple = + test_utils::pack_socktuple(reinterpret_cast(&client_sockaddr), + reinterpret_cast(&server_sockaddr)); + const std::vector packed_server_sockaddr = + test_utils::pack_sockaddr(reinterpret_cast(&server_sockaddr)); + + assert_event_presence(create_safe_scap_event( + ts, + tid, + PPME_SOCKET_CONNECT_X, + 4, + res, + scap_const_sized_buffer{tuple.data(), tuple.size()}, + fd, + scap_const_sized_buffer{packed_server_sockaddr.data(), packed_server_sockaddr.size()})); +} +#endif + //////////////////////////// // LISTEN ////////////////////////////