diff --git a/test/libsinsp_e2e/forking.cpp b/test/libsinsp_e2e/forking.cpp index 0035cd676a..4528713721 100644 --- a/test/libsinsp_e2e/forking.cpp +++ b/test/libsinsp_e2e/forking.cpp @@ -734,13 +734,13 @@ TEST_F(sys_call_test, forking_main_thread_exit) { if(param.m_evt->get_type() == PPME_SYSCALL_OPEN_X) { if(param.m_evt->get_param_value_str("name") == "/etc/passwd") { EXPECT_EQ("/etc/passwd", param.m_evt->get_param_value_str("fd")); - fd = param.m_evt->get_param(0)->as(); + fd = param.m_evt->get_syscall_return_value(); ++callnum; } } else if(param.m_evt->get_type() == PPME_SYSCALL_OPENAT_2_X) { if(param.m_evt->get_param_value_str("name") == "/etc/passwd") { EXPECT_EQ("/etc/passwd", param.m_evt->get_param_value_str("fd")); - fd = param.m_evt->get_param(0)->as(); + fd = param.m_evt->get_syscall_return_value(); ++callnum; } } else if(param.m_evt->get_type() == PPME_PROCEXIT_1_E && param.m_evt->get_tid() == cpid) { diff --git a/userspace/libscap/scap.h b/userspace/libscap/scap.h index d13f5e8875..119e209290 100644 --- a/userspace/libscap/scap.h +++ b/userspace/libscap/scap.h @@ -855,6 +855,7 @@ int32_t scap_event_encode_params_v(struct scap_sized_buffer event_buf, ppm_event_code event_type, uint32_t n, va_list args); +uint8_t scap_get_size_bytes_from_type(enum ppm_param_type t); /*@}*/ diff --git a/userspace/libscap/scap_event.c b/userspace/libscap/scap_event.c index 283bceda88..e039be173a 100644 --- a/userspace/libscap/scap_event.c +++ b/userspace/libscap/scap_event.c @@ -355,3 +355,57 @@ int32_t scap_event_encode_params_v(const struct scap_sized_buffer event_buf, return SCAP_SUCCESS; } + +uint8_t scap_get_size_bytes_from_type(enum ppm_param_type t) { + switch(t) { + case PT_INT8: + case PT_UINT8: + case PT_FLAGS8: + case PT_ENUMFLAGS8: + return 1; + + case PT_INT16: + case PT_UINT16: + case PT_FLAGS16: + case PT_ENUMFLAGS16: + case PT_SYSCALLID: + return 2; + + case PT_INT32: + case PT_UINT32: + case PT_FLAGS32: + case PT_ENUMFLAGS32: + case PT_UID: + case PT_GID: + case PT_MODE: + return 4; + + case PT_INT64: + case PT_UINT64: + case PT_RELTIME: + case PT_ABSTIME: + case PT_ERRNO: + case PT_FD: + case PT_PID: + return 8; + + case PT_BYTEBUF: + case PT_CHARBUF: + case PT_SOCKADDR: + case PT_SOCKTUPLE: + case PT_FDLIST: + case PT_FSPATH: + case PT_CHARBUFARRAY: + case PT_CHARBUF_PAIR_ARRAY: + case PT_FSRELPATH: + case PT_DYN: + return 0; + + default: + // We forgot to handle something + ASSERT(false); + break; + } + ASSERT(false); + return 0; +} diff --git a/userspace/libsinsp/event.h b/userspace/libsinsp/event.h index 9eed5cfad1..3555d9cfe0 100644 --- a/userspace/libsinsp/event.h +++ b/userspace/libsinsp/event.h @@ -719,6 +719,48 @@ class SINSP_PUBLIC sinsp_evt { } } + inline bool is_syscall_event() const { return get_info()->category & EC_SYSCALL; } + + inline bool has_return_value() { + // The event has a return value: + // * if it is a syscall event and it is an exit event. + if(is_syscall_event() && PPME_IS_EXIT(get_type())) { + return true; + } + + return false; + } + + inline int64_t get_syscall_return_value() { + if(!has_return_value()) { + throw sinsp_exception( + "Called get_syscall_return_value() on an event that does not have a return " + "value. " + "Event type: " + + std::to_string(get_type())); + } + + // The return value is always the first parameter of the syscall event + // It could have different names depending on the event type `res`,`fd`, etc. + const sinsp_evt_param* p = get_param(0); + if(p == NULL) { + // We should always have the return value in the syscall + ASSERT(false); + return 0; + } + + // the only return values should be on 32 or 64 bits + switch(scap_get_size_bytes_from_type(p->get_info()->type)) { + case 4: + return (int64_t)p->as(); + case 8: + return p->as(); + default: + ASSERT(false); + return 0; + } + } + private: sinsp* m_inspector; scap_evt* m_pevt; diff --git a/userspace/libsinsp/parsers.cpp b/userspace/libsinsp/parsers.cpp index 70e50709c5..1c119dad7e 100644 --- a/userspace/libsinsp/parsers.cpp +++ b/userspace/libsinsp/parsers.cpp @@ -426,7 +426,7 @@ void sinsp_parser::process_event(sinsp_evt *evt) { break; } - auto res = evt->get_param(0)->as(); + auto res = evt->get_syscall_return_value(); if(res >= 0) { // Only if successful auto dirfd = evt->get_param(1)->as(); @@ -439,7 +439,7 @@ void sinsp_parser::process_event(sinsp_evt *evt) { break; } - auto res = evt->get_param(0)->as(); + auto res = evt->get_syscall_return_value(); if(res >= 0) { // Only if successful auto dirfd = evt->get_param(2)->as(); @@ -706,10 +706,12 @@ bool sinsp_parser::reset(sinsp_evt *evt) { (evt->get_info()->params[0].name[0] == 'f' && evt->get_info()->params[0].name[1] == 'd' && evt->get_info()->params[0].name[2] == '\0'))) { - int64_t res = evt->get_param(0)->as(); + if(evt->has_return_value()) { + int64_t res = evt->get_syscall_return_value(); - if(res < 0) { - evt->set_errorcode(-(int32_t)res); + if(res < 0) { + evt->set_errorcode(-(int32_t)res); + } } } @@ -1870,7 +1872,7 @@ void sinsp_parser::parse_clone_exit_child(sinsp_evt *evt) { } void sinsp_parser::parse_clone_exit(sinsp_evt *evt) { - int64_t childtid = evt->get_param(0)->as(); + int64_t childtid = evt->get_syscall_return_value(); /* Please note that if the child is in a namespace different from the init one * we should never use this `childtid` otherwise we will use a thread id referred to * an internal namespace and not to the init one! @@ -1895,7 +1897,7 @@ void sinsp_parser::parse_execve_exit(sinsp_evt *evt) { sinsp_evt *enter_evt = &m_tmp_evt; // Validate the return value - retval = evt->get_param(0)->as(); + retval = evt->get_syscall_return_value(); /* Some architectures like s390x send a `PPME_SYSCALL_EXECVEAT_X` exit event * when the `execveat` syscall succeeds, for this reason, we need to manage also @@ -2427,7 +2429,7 @@ void sinsp_parser::parse_open_openat_creat_exit(sinsp_evt *evt) { // // Check the return value // - fd = evt->get_param(0)->as(); + fd = evt->get_syscall_return_value(); // // Parse the parameters, based on the event type @@ -2768,7 +2770,7 @@ void sinsp_parser::parse_socket_exit(sinsp_evt *evt) { // parameters in one scan. We don't care too much because we assume that we get here // seldom enough that saving few tens of CPU cycles is not important. // - fd = evt->get_param(0)->as(); + fd = evt->get_syscall_return_value(); if(fd < 0) { // @@ -2812,7 +2814,7 @@ void sinsp_parser::parse_bind_exit(sinsp_evt *evt) { return; } - retval = evt->get_param(0)->as(); + retval = evt->get_syscall_return_value(); if(retval < 0) { return; @@ -3113,7 +3115,7 @@ void sinsp_parser::parse_connect_exit(sinsp_evt *evt) { } } - retval = evt->get_param(0)->as(); + retval = evt->get_syscall_return_value(); if(m_track_connection_status) { if(retval == -SE_EINPROGRESS) { @@ -3170,7 +3172,7 @@ void sinsp_parser::parse_accept_exit(sinsp_evt *evt) { // // Extract the fd // - fd = evt->get_param(0)->as(); + fd = evt->get_syscall_return_value(); if(fd < 0) { // @@ -3310,7 +3312,7 @@ void sinsp_parser::parse_close_exit(sinsp_evt *evt) { // // Extract the return value // - retval = evt->get_param(0)->as(); + retval = evt->get_syscall_return_value(); // // If the close() was successful, do the cleanup @@ -3391,7 +3393,7 @@ void sinsp_parser::parse_socketpair_exit(sinsp_evt *evt) { uint64_t source_address; uint64_t peer_address; - retval = evt->get_param(0)->as(); + retval = evt->get_syscall_return_value(); if(retval < 0) { // @@ -3436,7 +3438,7 @@ void sinsp_parser::parse_pipe_exit(sinsp_evt *evt) { uint64_t ino; uint32_t openflags = 0; - retval = evt->get_param(0)->as(); + retval = evt->get_syscall_return_value(); if(retval < 0) { // @@ -3745,7 +3747,7 @@ void sinsp_parser::parse_rw_exit(sinsp_evt *evt) { // // Extract the return value // - retval = evt->get_param(0)->as(); + retval = evt->get_syscall_return_value(); if(evt->get_fd_info() == NULL) { return; @@ -3984,7 +3986,7 @@ void sinsp_parser::parse_sendfile_exit(sinsp_evt *evt) { // // Extract the return value // - retval = evt->get_param(0)->as(); + retval = evt->get_syscall_return_value(); // // If the operation was successful, validate that the fd exists @@ -4021,7 +4023,7 @@ void sinsp_parser::parse_eventfd_exit(sinsp_evt *evt) { return; } - fd = evt->get_param(0)->as(); + fd = evt->get_syscall_return_value(); if(fd < 0) { // @@ -4056,7 +4058,7 @@ void sinsp_parser::parse_chdir_exit(sinsp_evt *evt) { // // Extract the return value // - retval = evt->get_param(0)->as(); + retval = evt->get_syscall_return_value(); // // In case of success, update the thread working dir @@ -4073,7 +4075,7 @@ void sinsp_parser::parse_fchdir_exit(sinsp_evt *evt) { // // Extract the return value // - retval = evt->get_param(0)->as(); + retval = evt->get_syscall_return_value(); // // In case of success, update the thread working dir @@ -4097,7 +4099,7 @@ void sinsp_parser::parse_getcwd_exit(sinsp_evt *evt) { // // Extract the return value // - retval = evt->get_param(0)->as(); + retval = evt->get_syscall_return_value(); // // Check if the syscall was successful @@ -4152,7 +4154,7 @@ void sinsp_parser::parse_shutdown_exit(sinsp_evt *evt) { // // Extract the return value // - retval = evt->get_param(0)->as(); + retval = evt->get_syscall_return_value(); // // If the operation was successful, do the cleanup @@ -4178,7 +4180,7 @@ void sinsp_parser::parse_dup_exit(sinsp_evt *evt) { // // Extract the return value // - retval = evt->get_param(0)->as(); + retval = evt->get_syscall_return_value(); // // Check if the syscall was successful @@ -4263,7 +4265,7 @@ void sinsp_parser::parse_single_param_fd_exit(sinsp_evt *evt, scap_fd_type type) // // Extract the return value // - retval = evt->get_param(0)->as(); + retval = evt->get_syscall_return_value(); if(evt->get_tinfo() == nullptr) { return; @@ -4309,7 +4311,7 @@ void sinsp_parser::parse_getrlimit_setrlimit_exit(sinsp_evt *evt) { // // Extract the return value // - retval = evt->get_param(0)->as(); + retval = evt->get_syscall_return_value(); // // Check if the syscall was successful @@ -4356,7 +4358,7 @@ void sinsp_parser::parse_prlimit_exit(sinsp_evt *evt) { // // Extract the return value // - retval = evt->get_param(0)->as(); + retval = evt->get_syscall_return_value(); // // Check if the syscall was successful @@ -4445,7 +4447,7 @@ void sinsp_parser::parse_fcntl_exit(sinsp_evt *evt) { // // Extract the return value // - retval = evt->get_param(0)->as(); + retval = evt->get_syscall_return_value(); // // If this is not a F_DUPFD or F_DUPFD_CLOEXEC command, ignore it @@ -4507,7 +4509,7 @@ void sinsp_parser::parse_setresuid_exit(sinsp_evt *evt) { // // Extract the return value // - retval = evt->get_param(0)->as(); + retval = evt->get_syscall_return_value(); if(retval == 0 && retrieve_enter_event(enter_evt, evt)) { uint32_t new_euid = enter_evt->get_param(1)->as(); @@ -4527,7 +4529,7 @@ void sinsp_parser::parse_setreuid_exit(sinsp_evt *evt) { // // Extract the return value // - retval = evt->get_param(0)->as(); + retval = evt->get_syscall_return_value(); if(retval == 0) { uint32_t new_euid = evt->get_param(1)->as(); @@ -4548,7 +4550,7 @@ void sinsp_parser::parse_setresgid_exit(sinsp_evt *evt) { // // Extract the return value // - retval = evt->get_param(0)->as(); + retval = evt->get_syscall_return_value(); if(retval == 0 && retrieve_enter_event(enter_evt, evt)) { uint32_t new_egid = enter_evt->get_param(1)->as(); @@ -4568,7 +4570,7 @@ void sinsp_parser::parse_setregid_exit(sinsp_evt *evt) { // // Extract the return value // - retval = evt->get_param(0)->as(); + retval = evt->get_syscall_return_value(); if(retval == 0) { uint32_t new_egid = evt->get_param(1)->as(); @@ -4589,7 +4591,7 @@ void sinsp_parser::parse_setuid_exit(sinsp_evt *evt) { // // Extract the return value // - retval = evt->get_param(0)->as(); + retval = evt->get_syscall_return_value(); if(retval == 0 && retrieve_enter_event(enter_evt, evt)) { uint32_t new_euid = enter_evt->get_param(0)->as(); @@ -4607,7 +4609,7 @@ void sinsp_parser::parse_setgid_exit(sinsp_evt *evt) { // // Extract the return value // - retval = evt->get_param(0)->as(); + retval = evt->get_syscall_return_value(); if(retval == 0 && retrieve_enter_event(enter_evt, evt)) { uint32_t new_egid = enter_evt->get_param(0)->as(); @@ -4998,7 +5000,7 @@ void sinsp_parser::parse_cpu_hotplug_enter(sinsp_evt *evt) { void sinsp_parser::parse_prctl_exit_event(sinsp_evt *evt) { /* Parameter 1: res (type: PT_ERRNO) */ - int64_t retval = evt->get_param(0)->as(); + int64_t retval = evt->get_syscall_return_value(); if(retval < 0) { /* we are not interested in parsing something if the syscall fails */ @@ -5053,7 +5055,7 @@ void sinsp_parser::parse_chroot_exit(sinsp_evt *evt) { return; } - int64_t retval = evt->get_param(0)->as(); + int64_t retval = evt->get_syscall_return_value(); if(retval == 0) { const char *resolved_path; auto path = evt->get_param_as_str(1, &resolved_path); @@ -5086,7 +5088,7 @@ void sinsp_parser::parse_setsid_exit(sinsp_evt *evt) { // // Extract the return value // - retval = evt->get_param(0)->as(); + retval = evt->get_syscall_return_value(); if(retval >= 0) { if(evt->get_thread_info()) { @@ -5120,7 +5122,7 @@ void sinsp_parser::parse_getsockopt_exit(sinsp_evt *evt) { // // Extract the return value // - retval = evt->get_param(0)->as(); + retval = evt->get_syscall_return_value(); if(retval < 0) { return; @@ -5164,7 +5166,7 @@ void sinsp_parser::parse_capset_exit(sinsp_evt *evt) { // // Extract the return value // - retval = evt->get_param(0)->as(); + retval = evt->get_syscall_return_value(); if(retval < 0 || evt->get_tinfo() == nullptr) { return; @@ -5188,7 +5190,7 @@ void sinsp_parser::parse_unshare_setns_exit(sinsp_evt *evt) { int64_t retval; uint32_t flags = 0; - retval = evt->get_param(0)->as(); + retval = evt->get_syscall_return_value(); if(retval < 0 || evt->get_tinfo() == nullptr) { return; @@ -5238,8 +5240,7 @@ void sinsp_parser::parse_memfd_create_exit(sinsp_evt *evt, scap_fd_type type) { } /* ret (fd) */ - ASSERT(evt->get_param_info(0)->type == PT_FD); - fd = evt->get_param(0)->as(); + fd = evt->get_syscall_return_value(); /* name */ /* @@ -5271,8 +5272,7 @@ void sinsp_parser::parse_pidfd_open_exit(sinsp_evt *evt) { } /* ret (fd) */ - ASSERT(evt->get_param_info(0)->type == PT_FD); - fd = evt->get_param(0)->as(); + fd = evt->get_syscall_return_value(); /* pid (fd) */ ASSERT(evt->get_param_info(1)->type == PT_PID); @@ -5305,8 +5305,7 @@ void sinsp_parser::parse_pidfd_getfd_exit(sinsp_evt *evt) { } /* ret (fd) */ - ASSERT(evt->get_param_info(0)->type == PT_FD); - fd = evt->get_param(0)->as(); + fd = evt->get_syscall_return_value(); /* pidfd */ ASSERT(evt->get_param_info(1)->type == PT_FD); diff --git a/userspace/libsinsp/sinsp_debug/sinsp_debug.cpp b/userspace/libsinsp/sinsp_debug/sinsp_debug.cpp index 0e6cbb9286..669b351f72 100644 --- a/userspace/libsinsp/sinsp_debug/sinsp_debug.cpp +++ b/userspace/libsinsp/sinsp_debug/sinsp_debug.cpp @@ -128,7 +128,7 @@ int main(int argc, char** argv) { case PPME_SYSCALL_VFORK_17_X: case PPME_SYSCALL_VFORK_20_X: case PPME_SYSCALL_CLONE3_X: { - int64_t child_tid = ev->get_param(0)->as(); + int64_t child_tid = ev->get_syscall_return_value(); if(child_tid == 0) { printf("🧵 CLONE CHILD EXIT: evt_num(%ld)\n", ev->get_num()); } else { diff --git a/userspace/libsinsp/sinsp_filtercheck_event.cpp b/userspace/libsinsp/sinsp_filtercheck_event.cpp index 36f3c1d85c..dbb376ee1d 100644 --- a/userspace/libsinsp/sinsp_filtercheck_event.cpp +++ b/userspace/libsinsp/sinsp_filtercheck_event.cpp @@ -705,7 +705,7 @@ uint8_t* sinsp_filter_check_event::extract_abspath(sinsp_evt* evt, uint32_t* len // // We can extract the file path only in case of a successful file opening (fd>0). // - fd = evt->get_param(0)->as(); + fd = evt->get_syscall_return_value(); if(fd > 0) { // @@ -799,7 +799,7 @@ inline uint8_t* sinsp_filter_check_event::extract_buflen(sinsp_evt* evt, uint32_ // // Extract the return value // - m_val.s64 = evt->get_param(0)->as(); + m_val.s64 = evt->get_syscall_return_value(); if(m_val.s64 >= 0) { RETURN_EXTRACT_VAR(m_val.s64); @@ -833,31 +833,17 @@ Json::Value sinsp_filter_check_event::extract_as_js(sinsp_evt* evt, uint32_t* le } uint8_t* sinsp_filter_check_event::extract_error_count(sinsp_evt* evt, uint32_t* len) { - const sinsp_evt_param* pi = evt->get_param_by_name("res"); - - if(pi != NULL) { - int64_t res = pi->as(); - if(res < 0) { - m_val.u32 = 1; - RETURN_EXTRACT_VAR(m_val.u32); - } else { - return NULL; - } + // todo!: we need to understand if we want to return `0` or ``. + // At the moment we return ``. + if(!evt->has_return_value()) { + return NULL; } - if((evt->get_info_flags() & EF_CREATES_FD) && PPME_IS_EXIT(evt->get_type())) { - pi = evt->get_param_by_name("fd"); - - if(pi != NULL) { - int64_t res = pi->as(); - if(res < 0) { - m_val.u32 = 1; - RETURN_EXTRACT_VAR(m_val.u32); - } - } + m_val.u32 = 0; + if(evt->get_syscall_return_value() < 0) { + m_val.u32 = 1; } - - return NULL; + RETURN_EXTRACT_VAR(m_val.u32); } uint8_t* sinsp_filter_check_event::extract_single(sinsp_evt* evt, @@ -1362,26 +1348,6 @@ uint8_t* sinsp_filter_check_event::extract_single(sinsp_evt* evt, return NULL; } break; - case TYPE_FAILED: { - m_val.u32 = 0; - const sinsp_evt_param* pi = evt->get_param_by_name("res"); - - if(pi != NULL) { - if(pi->as() < 0) { - m_val.u32 = 1; - } - } else if((evt->get_info_flags() & EF_CREATES_FD) && PPME_IS_EXIT(evt->get_type())) { - pi = evt->get_param_by_name("fd"); - - if(pi != NULL) { - if(pi->as() < 0) { - m_val.u32 = 1; - } - } - } - - RETURN_EXTRACT_VAR(m_val.u32); - } break; case TYPE_ISIO: { ppm_event_flags eflags = evt->get_info_flags(); if(eflags & (EF_READS_FROM_FD | EF_WRITES_TO_FD)) { @@ -1467,6 +1433,7 @@ uint8_t* sinsp_filter_check_event::extract_single(sinsp_evt* evt, case TYPE_COUNT: m_val.u32 = 1; RETURN_EXTRACT_VAR(m_val.u32); + case TYPE_FAILED: case TYPE_COUNT_ERROR: return extract_error_count(evt, len); case TYPE_COUNT_ERROR_FILE: { @@ -1682,8 +1649,8 @@ uint8_t* sinsp_filter_check_event::extract_single(sinsp_evt* evt, } // If PPM_O_TMPFILE is set and syscall is successful the file is created - if(flags & PPM_O_TMPFILE) { - int64_t retval = evt->get_param(0)->as(); + if((flags & PPM_O_TMPFILE) && evt->has_return_value()) { + int64_t retval = evt->get_syscall_return_value(); if(retval >= 0) { m_val.u32 = 1; diff --git a/userspace/libsinsp/sinsp_filtercheck_fd.cpp b/userspace/libsinsp/sinsp_filtercheck_fd.cpp index a1cb409d6b..2b0b8e5467 100644 --- a/userspace/libsinsp/sinsp_filtercheck_fd.cpp +++ b/userspace/libsinsp/sinsp_filtercheck_fd.cpp @@ -534,7 +534,7 @@ uint8_t *sinsp_filter_check_fd::extract_single(sinsp_evt *evt, case TYPE_FDNAME: case TYPE_CONTAINERNAME: if(evt->get_type() == PPME_SOCKET_CONNECT_X) { - int64_t retval = evt->get_param(0)->as(); + int64_t retval = evt->get_syscall_return_value(); // this is a weird behavior, see the `net_connect_exit_event_fails` test for more info if(retval < 0) { if(!extract_fdname_from_event(evt, sanitize_strings)) {