diff --git a/userspace/libsinsp/sinsp_filtercheck_thread.cpp b/userspace/libsinsp/sinsp_filtercheck_thread.cpp index 9b3bf4edaf..2d59cfbd50 100644 --- a/userspace/libsinsp/sinsp_filtercheck_thread.cpp +++ b/userspace/libsinsp/sinsp_filtercheck_thread.cpp @@ -126,6 +126,12 @@ static const filtercheck_field_info sinsp_filter_check_thread_fields[] = {PT_UINT64, EPF_NONE, PF_DEC, "thread.vmrss", "Thread VM RSS (kb)", "For the process main thread, this is the resident non-swapped memory for the process (as kb). For the other threads, this field is zero."}, {PT_UINT64, EPF_TABLE_ONLY, PF_DEC, "thread.vmsize.b", "Thread VM Size (b)", "For the process main thread, this is the total virtual memory for the process (in bytes). For the other threads, this field is zero."}, {PT_UINT64, EPF_TABLE_ONLY, PF_DEC, "thread.vmrss.b", "Thread VM RSS (b)", "For the process main thread, this is the resident non-swapped memory for the process (in bytes). For the other threads, this field is zero."}, + {PT_CHARBUF, EPF_NONE, PF_NA, "proc.stdin.type", "Standard Input fd type", "The type of file descriptor 0, corresponding to stdin, of the process generating the event."}, + {PT_CHARBUF, EPF_NONE, PF_NA, "proc.stdout.type", "Standard Output fd type", "The type of file descriptor 1, corresponding to stdout, of the process generating the event."}, + {PT_CHARBUF, EPF_NONE, PF_NA, "proc.stderr.type", "Standard Error fd type", "The type of file descriptor 2, corresponding to stderr, of the process generating the event."}, + {PT_CHARBUF, EPF_NONE, PF_NA, "proc.stdin.name", "Standard Input fd name", "The name of the file descriptor 0, corresponding to stdin, of the process generating the event."}, + {PT_CHARBUF, EPF_NONE, PF_NA, "proc.stdout.name", "Standard Output fd name", "The name of the file descriptor 1, corresponding to stdout, of the process generating the event."}, + {PT_CHARBUF, EPF_NONE, PF_NA, "proc.stderr.name", "Standard Error fd name", "The name of the file descriptor 2, corresponding to stderr, of the process generating the event."}, }; sinsp_filter_check_thread::sinsp_filter_check_thread() @@ -1612,6 +1618,66 @@ uint8_t* sinsp_filter_check_thread::extract_single(sinsp_evt *evt, uint32_t* len return NULL; } } + case TYPE_FD_STDIN_TYPE: + case TYPE_FD_STDOUT_TYPE: + case TYPE_FD_STDERR_TYPE: + { + int64_t fd = -1; + if (m_field_id == TYPE_FD_STDIN_TYPE) + { + fd = 0; + } + else if (m_field_id == TYPE_FD_STDOUT_TYPE) + { + fd = 1; + } + else if (m_field_id == TYPE_FD_STDERR_TYPE) + { + fd = 2; + } + auto fdtable_ptr = tinfo->get_fd_table(); + if (fdtable_ptr == nullptr) + { + return NULL; + } + auto fdinfo = fdtable_ptr->find(fd); + if (fdinfo == nullptr) + { + return NULL; + } + m_tstr = fdinfo->get_typestring(); + RETURN_EXTRACT_STRING(m_tstr); + } + case TYPE_FD_STDIN_NAME: + case TYPE_FD_STDOUT_NAME: + case TYPE_FD_STDERR_NAME: + { + int64_t fd = -1; + if (m_field_id == TYPE_FD_STDIN_NAME) + { + fd = 0; + } + else if (m_field_id == TYPE_FD_STDOUT_NAME) + { + fd = 1; + } + else if (m_field_id == TYPE_FD_STDERR_NAME) + { + fd = 2; + } + auto fdtable_ptr = tinfo->get_fd_table(); + if (fdtable_ptr == nullptr) + { + return NULL; + } + auto fdinfo = fdtable_ptr->find(fd); + if (fdinfo == nullptr) + { + return NULL; + } + m_tstr = fdinfo->m_name.c_str(); + RETURN_EXTRACT_STRING(m_tstr); + } default: ASSERT(false); return NULL; diff --git a/userspace/libsinsp/sinsp_filtercheck_thread.h b/userspace/libsinsp/sinsp_filtercheck_thread.h index 5f59812eea..e3af894b97 100644 --- a/userspace/libsinsp/sinsp_filtercheck_thread.h +++ b/userspace/libsinsp/sinsp_filtercheck_thread.h @@ -106,6 +106,12 @@ class sinsp_filter_check_thread : public sinsp_filter_check TYPE_THREAD_VMRSS, TYPE_THREAD_VMSIZE_B, TYPE_THREAD_VMRSS_B, + TYPE_FD_STDIN_TYPE, + TYPE_FD_STDOUT_TYPE, + TYPE_FD_STDERR_TYPE, + TYPE_FD_STDIN_NAME, + TYPE_FD_STDOUT_NAME, + TYPE_FD_STDERR_NAME, }; sinsp_filter_check_thread(); diff --git a/userspace/libsinsp/test/filterchecks/proc.cpp b/userspace/libsinsp/test/filterchecks/proc.cpp index 18b6152e4e..681034d1d2 100644 --- a/userspace/libsinsp/test/filterchecks/proc.cpp +++ b/userspace/libsinsp/test/filterchecks/proc.cpp @@ -105,3 +105,46 @@ TEST_F(sinsp_with_test_input, PROC_FILTER_pexepath_aexepath) /* this field shouldn't exist */ ASSERT_FALSE(field_has_value(evt, "proc.aexepath[6]")); } + +#if !defined(_WIN32) && !defined(__EMSCRIPTEN__) && !defined(__APPLE__) +TEST_F(sinsp_with_test_input, PROC_FILTER_stdin_stdout_stderr) +{ + DEFAULT_TREE + sinsp_evt* evt = NULL; + int64_t client_fd = 3, return_value = 0; + int64_t stdin_fd = 0, stdout_fd = 1, stderr_fd = 2; + + // Create a connected socket + add_event_advance_ts(increasing_ts(), 1, PPME_SOCKET_SOCKET_E, 3, (uint32_t) PPM_AF_INET, (uint32_t) SOCK_STREAM, 0); + add_event_advance_ts(increasing_ts(), 1, PPME_SOCKET_SOCKET_X, 1, client_fd); + + sockaddr_in client = test_utils::fill_sockaddr_in(DEFAULT_CLIENT_PORT, DEFAULT_IPV4_CLIENT_STRING); + + sockaddr_in server = test_utils::fill_sockaddr_in(DEFAULT_SERVER_PORT, DEFAULT_IPV4_SERVER_STRING); + + std::vector server_sockaddr = test_utils::pack_sockaddr(reinterpret_cast(&server)); + evt = add_event_advance_ts(increasing_ts(), 1, PPME_SOCKET_CONNECT_E, 2, client_fd, scap_const_sized_buffer{server_sockaddr.data(), server_sockaddr.size()}); + + 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()}, client_fd); + + // The socket is duped to stdin, stdout, stderr + evt = add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_DUP2_E, 1, client_fd); + evt = add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_DUP2_X, 3, stdin_fd, client_fd, stdin_fd); + evt = add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_DUP2_E, 1, client_fd); + evt = add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_DUP2_X, 3, stdout_fd, client_fd, stdout_fd); + evt = add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_DUP2_E, 1, client_fd); + evt = add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_DUP2_X, 3, stderr_fd, client_fd, stderr_fd); + + // Exec a process and check stdin, stdout and stderr types and names + evt = generate_execve_enter_and_exit_event(0, 1, 1, 1, 1, "/proc_filter_stdin_stdout_stderr", "proc_filter_stdin_stdout_stderr", "/usr/bin/proc_filter_stdin_stdout_stderr"); + ASSERT_EQ(get_field_as_string(evt, "proc.stdin.type"), "ipv4"); + ASSERT_EQ(get_field_as_string(evt, "proc.stdout.type"), "ipv4"); + ASSERT_EQ(get_field_as_string(evt, "proc.stderr.type"), "ipv4"); + + std::string tuple_str = std::string(DEFAULT_IPV4_CLIENT_STRING) + ":" + std::to_string(DEFAULT_CLIENT_PORT) + "->" + std::string(DEFAULT_IPV4_SERVER_STRING) + ":" + std::to_string(DEFAULT_SERVER_PORT); + ASSERT_EQ(get_field_as_string(evt, "proc.stdin.name"), tuple_str); + ASSERT_EQ(get_field_as_string(evt, "proc.stdout.name"), tuple_str); + ASSERT_EQ(get_field_as_string(evt, "proc.stderr.name"), tuple_str); +} +#endif \ No newline at end of file