diff --git a/userspace/libsinsp/parsers.cpp b/userspace/libsinsp/parsers.cpp index fdb8d17b072..cc3808ea8d4 100644 --- a/userspace/libsinsp/parsers.cpp +++ b/userspace/libsinsp/parsers.cpp @@ -442,6 +442,33 @@ void sinsp_parser::process_event(sinsp_evt *evt) case PPME_SYSCALL_PRCTL_X: parse_prctl_exit_event(evt); break; + case PPME_SYSCALL_NEWFSTATAT_X: + case PPME_SYSCALL_FCHOWNAT_X: + case PPME_SYSCALL_FCHMODAT_X: + case PPME_SYSCALL_MKDIRAT_X: + case PPME_SYSCALL_UNLINKAT_2_X: + case PPME_SYSCALL_MKNODAT_X: + { + auto res = evt->get_param(0)->as(); + if (res >= 0) + { + // Only if successful + auto dirfd = evt->get_param(1)->as(); + evt->set_fd_info(evt->get_tinfo()->get_fd(dirfd)); + } + break; + } + case PPME_SYSCALL_SYMLINKAT_X: + { + auto res = evt->get_param(0)->as(); + if (res >= 0) + { + // Only if successful + auto dirfd = evt->get_param(2)->as(); + evt->set_fd_info(evt->get_tinfo()->get_fd(dirfd)); + } + break; + } default: break; } @@ -452,7 +479,7 @@ void sinsp_parser::process_event(sinsp_evt *evt) // if(do_filter_later) { - if(m_inspector->run_filters_on_evt(evt) == false) + if(!m_inspector->run_filters_on_evt(evt)) { evt->set_filtered_out(true); return; @@ -2307,6 +2334,12 @@ void sinsp_parser::parse_execve_exit(sinsp_evt *evt) */ std::string sdir = parse_dirfd(evt, pathname, dirfd); + // Update event fdinfo since parse_dirfd is stateless + if (sdir != "." && sdir != "") + { + evt->set_fd_info(evt->get_tinfo()->get_fd(dirfd)); + } + /* (4) In this case, we were not able to recover the pathname from the kernel or * we are not able to recover information about `dirfd` in our `sinsp` state. * Fallback to ``. @@ -2499,7 +2532,6 @@ void sinsp_parser::parse_execve_exit(sinsp_evt *evt) m_inspector->remove_thread(thread_ptr->m_tid); } } - return; } /* Different possible cases: @@ -2519,8 +2551,6 @@ std::string sinsp_parser::parse_dirfd(sinsp_evt *evt, std::string_view name, int is_absolute = (!name.empty() && name[0] == '/'); } - std::string tdirstr; - if(is_absolute) { // @@ -2544,20 +2574,17 @@ std::string sinsp_parser::parse_dirfd(sinsp_evt *evt, std::string_view name, int return evt->get_tinfo()->get_cwd(); } - evt->set_fd_info(evt->get_tinfo()->get_fd(dirfd)); - - if(evt->get_fd_info() == NULL) + auto fdinfo = evt->get_tinfo()->get_fd(dirfd); + if(fdinfo == NULL) { return ""; } - if(evt->get_fd_info()->m_name[evt->get_fd_info()->m_name.length()] == '/') + if(fdinfo->m_name.back() == '/') { - return evt->get_fd_info()->m_name; + return fdinfo->m_name; } - - tdirstr = evt->get_fd_info()->m_name + '/'; - return tdirstr; + return fdinfo->m_name + '/'; } void sinsp_parser::parse_open_openat_creat_exit(sinsp_evt *evt) diff --git a/userspace/libsinsp/sinsp_filtercheck_fspath.cpp b/userspace/libsinsp/sinsp_filtercheck_fspath.cpp index 7db2015f5a3..909b6436791 100644 --- a/userspace/libsinsp/sinsp_filtercheck_fspath.cpp +++ b/userspace/libsinsp/sinsp_filtercheck_fspath.cpp @@ -240,54 +240,23 @@ std::unique_ptr sinsp_filter_check_fspath::allocate_new() return ret; } -std::string sinsp_filter_check_fspath::parse_dirfd_stateless(sinsp_evt *evt, std::string_view name, int64_t dirfd) -{ - // Slight alteration ("stateless" meaning no writes to the thread table's fd_info) - // else a 1:1 adoption of sinsp_parser::parse_dirfd - - bool is_absolute = false; - /* This should never happen but just to be sure. */ - if(name.data() != nullptr) - { - is_absolute = (!name.empty() && name[0] == '/'); - } - - std::string tdirstr; - - if(is_absolute) - { - // - // The path is absolute. - // Some processes (e.g. irqbalance) actually do this: they pass an invalid fd and - // and absolute path, and openat succeeds. - // - return "."; - } - - if(!evt->get_tinfo()) - { - return ""; - } - - if(dirfd == PPM_AT_FDCWD) - { - return evt->get_tinfo()->get_cwd(); - } - - auto fd_info_dirfd = evt->get_tinfo()->get_fd(dirfd); - if(!fd_info_dirfd) +// Similar to sinsp_parser::parse_dirfd(). +// Makes only sense when called against a directory fdinfo. +static inline std::string format_dirfd(sinsp_evt* evt) +{ + auto fd_info_dirfd = evt->get_fd_info(); + if(!fd_info_dirfd || !fd_info_dirfd->is_directory()) { return ""; } - if(fd_info_dirfd->m_name[fd_info_dirfd->m_name.length()] == '/') + if(fd_info_dirfd->m_name.back() == '/') { return fd_info_dirfd->m_name; } - tdirstr = fd_info_dirfd->m_name + '/'; - return tdirstr; + return fd_info_dirfd->m_name + '/'; } uint8_t* sinsp_filter_check_fspath::extract_single(sinsp_evt* evt, uint32_t* len, bool sanitize_strings) @@ -407,66 +376,73 @@ uint8_t* sinsp_filter_check_fspath::extract_single(sinsp_evt* evt, uint32_t* len { std::string sdir; // init // Compare to `sinsp_filter_check_fd::extract_fdname_from_creator` logic + // note: no implementation for old / legacy event definitions switch(evt->get_type()) { - // note: no implementation for old / legacy event definitions - case PPME_SYSCALL_OPENAT_2_E: // dirfd - case PPME_SYSCALL_OPENAT2_E: + // For openat, event fdinfo is already correctly expanded by parsers; + // See sinsp_parser::parse_open_openat_creat_exit(). + case PPME_SYSCALL_OPENAT_2_X: + case PPME_SYSCALL_OPENAT2_X: { - int64_t dirfd = evt->get_param(0)->as(); - sdir = parse_dirfd_stateless(evt, m_tstr, dirfd); + sdir = ""; + auto fdinfo = evt->get_fd_info(); + if (fdinfo != nullptr) + { + m_tstr = evt->get_fd_info()->m_name; + } + else + { + m_tstr = ""; + } + break; } - break; - case PPME_SYSCALL_OPENAT_2_X: // dirfd - case PPME_SYSCALL_OPENAT2_X: + // For the following syscalls, the event fdinfo is set to their dirfd. + // Set `sdir` to the dirfd info path. case PPME_SYSCALL_NEWFSTATAT_X: case PPME_SYSCALL_FCHOWNAT_X: case PPME_SYSCALL_FCHMODAT_X: case PPME_SYSCALL_MKDIRAT_X: case PPME_SYSCALL_UNLINKAT_2_X: case PPME_SYSCALL_MKNODAT_X: - { - int64_t dirfd = evt->get_param(1)->as(); - sdir = parse_dirfd_stateless(evt, m_tstr, dirfd); - } - break; + sdir = format_dirfd(evt); + break; case PPME_SYSCALL_SYMLINKAT_X: // linkdirfd { if (m_field_id == TYPE_SOURCE) { - // linkdirfd - int64_t dirfd = evt->get_param(2)->as(); - sdir = parse_dirfd_stateless(evt, m_tstr, dirfd); - } else + sdir = format_dirfd(evt); + } + else { sdir = ""; } + break; } - break; - case PPME_SYSCALL_RENAMEAT2_X: // newdirfd or olddirfd + case PPME_SYSCALL_RENAMEAT2_X: { + // newdirfd or olddirfd, we need to extract the dirfd on the fly here int64_t dirfd; if (m_field_id == TYPE_TARGET) { // newdirfd dirfd = evt->get_param(3)->as(); - sdir = parse_dirfd_stateless(evt, m_tstr, dirfd); - } else if (m_field_id == TYPE_SOURCE) + sdir = m_inspector->get_parser()->parse_dirfd(evt, m_tstr, dirfd); + } + else if (m_field_id == TYPE_SOURCE) { // olddirfd dirfd = evt->get_param(1)->as(); - sdir = parse_dirfd_stateless(evt, m_tstr, dirfd); - } else + sdir = m_inspector->get_parser()->parse_dirfd(evt, m_tstr, dirfd); + } + else { sdir = ""; } + break; } - break; default: // assign cwd as sdir - { sdir = tinfo->get_cwd(); - } - break; + break; } /* Note on what `sdir` is: @@ -481,7 +457,8 @@ uint8_t* sinsp_filter_check_fspath::extract_single(sinsp_evt* evt, uint32_t* len */ m_tstr = sinsp_utils::concatenate_paths(sdir, m_tstr); - } else + } + else { /* Note about `concatenate_paths` * It takes care of resolving the path and as such needed even if sdir is empty diff --git a/userspace/libsinsp/sinsp_filtercheck_fspath.h b/userspace/libsinsp/sinsp_filtercheck_fspath.h index 9203c5ebcc0..a38584e6fc4 100644 --- a/userspace/libsinsp/sinsp_filtercheck_fspath.h +++ b/userspace/libsinsp/sinsp_filtercheck_fspath.h @@ -58,7 +58,7 @@ class sinsp_filter_check_fspath : public sinsp_filter_check bool extract_fspath(sinsp_evt* evt, std::vector& values, const std::shared_ptr& map); - std::string parse_dirfd_stateless(sinsp_evt *evt, std::string_view name, int64_t dirfd); + std::string m_tstr; std::shared_ptr m_success_checks; diff --git a/userspace/libsinsp/test/events_fspath.ut.cpp b/userspace/libsinsp/test/events_fspath.ut.cpp index ad484cd448c..98fe25547f3 100644 --- a/userspace/libsinsp/test/events_fspath.ut.cpp +++ b/userspace/libsinsp/test/events_fspath.ut.cpp @@ -213,7 +213,8 @@ class fspath : public sinsp_with_test_input case PPME_SYSCALL_UNLINKAT_2_X: { add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_OPENAT2_E, 2, evt_dirfd, dirfd_path); - add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_OPENAT2_X, 5, evt_dirfd, evt_dirfd, dirfd_path, open_flags, mode); + // pass PPM_O_DIRECTORY since we are creating a folder! + add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_OPENAT2_X, 5, evt_dirfd, evt_dirfd, dirfd_path, open_flags | PPM_O_DIRECTORY, mode); } break; default: @@ -242,7 +243,7 @@ class fspath : public sinsp_with_test_input case PPME_SYSCALL_SYMLINKAT_X: { add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_OPENAT2_E, 2, evt_dirfd, dirfd_path); - add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_OPENAT2_X, 5, evt_dirfd, evt_dirfd, dirfd_path, open_flags, mode); + add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_OPENAT2_X, 5, evt_dirfd, evt_dirfd, dirfd_path, open_flags | PPM_O_DIRECTORY, mode); } break; default: