From b1316a27eef70cfe576f164b7147505c13a32b3c Mon Sep 17 00:00:00 2001 From: Lorenzo Susini Date: Tue, 11 Jun 2024 15:37:52 +0000 Subject: [PATCH 1/5] update(userspace/libsinsp): add filter checks to extract process' stdin,stdout,stderr types Signed-off-by: Lorenzo Susini --- .../libsinsp/sinsp_filtercheck_thread.cpp | 48 +++++++++++++++++++ userspace/libsinsp/sinsp_filtercheck_thread.h | 3 ++ 2 files changed, 51 insertions(+) diff --git a/userspace/libsinsp/sinsp_filtercheck_thread.cpp b/userspace/libsinsp/sinsp_filtercheck_thread.cpp index 9b3bf4edaf..42d9e2f630 100644 --- a/userspace/libsinsp/sinsp_filtercheck_thread.cpp +++ b/userspace/libsinsp/sinsp_filtercheck_thread.cpp @@ -126,6 +126,9 @@ 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.fd.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.fd.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.fd.stderr.type", "Standard Error fd type", "The type of file descriptor 2, corresponding to stderr, of the process generating the event."}, }; sinsp_filter_check_thread::sinsp_filter_check_thread() @@ -1612,6 +1615,51 @@ uint8_t* sinsp_filter_check_thread::extract_single(sinsp_evt *evt, uint32_t* len return NULL; } } + case TYPE_FD_STDIN_TYPE: + { + auto fdtable_ptr = tinfo->get_fd_table(); + if (fdtable_ptr == nullptr) + { + return NULL; + } + auto fdinfo = fdtable_ptr->find(0); + if (fdinfo == nullptr) + { + return NULL; + } + m_tstr = fdinfo->get_typestring(); + RETURN_EXTRACT_STRING(m_tstr); + } + case TYPE_FD_STDOUT_TYPE: + { + auto fdtable_ptr = tinfo->get_fd_table(); + if (fdtable_ptr == nullptr) + { + return NULL; + } + auto fdinfo = fdtable_ptr->find(1); + if (fdinfo == nullptr) + { + return NULL; + } + m_tstr = fdinfo->get_typestring(); + RETURN_EXTRACT_STRING(m_tstr); + } + case TYPE_FD_STDERR_TYPE: + { + auto fdtable_ptr = tinfo->get_fd_table(); + if (fdtable_ptr == nullptr) + { + return NULL; + } + auto fdinfo = fdtable_ptr->find(2); + if (fdinfo == nullptr) + { + return NULL; + } + m_tstr = fdinfo->get_typestring(); + 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..1539610832 100644 --- a/userspace/libsinsp/sinsp_filtercheck_thread.h +++ b/userspace/libsinsp/sinsp_filtercheck_thread.h @@ -106,6 +106,9 @@ 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, }; sinsp_filter_check_thread(); From d8015d2c09559738155f1b4209705e94c35b63f5 Mon Sep 17 00:00:00 2001 From: Lorenzo Susini Date: Tue, 11 Jun 2024 16:50:12 +0000 Subject: [PATCH 2/5] update(userspace/libsinsp): add also proc.fd.*.name fields Signed-off-by: Lorenzo Susini --- .../libsinsp/sinsp_filtercheck_thread.cpp | 48 +++++++++++++++++++ userspace/libsinsp/sinsp_filtercheck_thread.h | 3 ++ 2 files changed, 51 insertions(+) diff --git a/userspace/libsinsp/sinsp_filtercheck_thread.cpp b/userspace/libsinsp/sinsp_filtercheck_thread.cpp index 42d9e2f630..044f71c94d 100644 --- a/userspace/libsinsp/sinsp_filtercheck_thread.cpp +++ b/userspace/libsinsp/sinsp_filtercheck_thread.cpp @@ -129,6 +129,9 @@ static const filtercheck_field_info sinsp_filter_check_thread_fields[] = {PT_CHARBUF, EPF_NONE, PF_NA, "proc.fd.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.fd.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.fd.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.fd.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.fd.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.fd.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() @@ -1660,6 +1663,51 @@ uint8_t* sinsp_filter_check_thread::extract_single(sinsp_evt *evt, uint32_t* len m_tstr = fdinfo->get_typestring(); RETURN_EXTRACT_STRING(m_tstr); } + case TYPE_FD_STDIN_NAME: + { + auto fdtable_ptr = tinfo->get_fd_table(); + if (fdtable_ptr == nullptr) + { + return NULL; + } + auto fdinfo = fdtable_ptr->find(0); + if (fdinfo == nullptr) + { + return NULL; + } + m_tstr = fdinfo->m_name.c_str(); + RETURN_EXTRACT_STRING(m_tstr); + } + case TYPE_FD_STDOUT_NAME: + { + auto fdtable_ptr = tinfo->get_fd_table(); + if (fdtable_ptr == nullptr) + { + return NULL; + } + auto fdinfo = fdtable_ptr->find(1); + if (fdinfo == nullptr) + { + return NULL; + } + m_tstr = fdinfo->m_name.c_str(); + RETURN_EXTRACT_STRING(m_tstr); + } + case TYPE_FD_STDERR_NAME: + { + auto fdtable_ptr = tinfo->get_fd_table(); + if (fdtable_ptr == nullptr) + { + return NULL; + } + auto fdinfo = fdtable_ptr->find(2); + 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 1539610832..e3af894b97 100644 --- a/userspace/libsinsp/sinsp_filtercheck_thread.h +++ b/userspace/libsinsp/sinsp_filtercheck_thread.h @@ -109,6 +109,9 @@ class sinsp_filter_check_thread : public sinsp_filter_check 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(); From 73545f530806c1075e2df06a4a2b02fca4f921a9 Mon Sep 17 00:00:00 2001 From: Lorenzo Susini Date: Fri, 14 Jun 2024 10:56:11 +0000 Subject: [PATCH 3/5] update(userspace/libsinsp): avoid code duplication when handling proc.fd fields Signed-off-by: Lorenzo Susini --- .../libsinsp/sinsp_filtercheck_thread.cpp | 70 ++++++------------- 1 file changed, 20 insertions(+), 50 deletions(-) diff --git a/userspace/libsinsp/sinsp_filtercheck_thread.cpp b/userspace/libsinsp/sinsp_filtercheck_thread.cpp index 044f71c94d..82fe9d35bc 100644 --- a/userspace/libsinsp/sinsp_filtercheck_thread.cpp +++ b/userspace/libsinsp/sinsp_filtercheck_thread.cpp @@ -1619,43 +1619,28 @@ uint8_t* sinsp_filter_check_thread::extract_single(sinsp_evt *evt, uint32_t* len } } case TYPE_FD_STDIN_TYPE: + case TYPE_FD_STDOUT_TYPE: + case TYPE_FD_STDERR_TYPE: { - auto fdtable_ptr = tinfo->get_fd_table(); - if (fdtable_ptr == nullptr) - { - return NULL; - } - auto fdinfo = fdtable_ptr->find(0); - if (fdinfo == nullptr) + int64_t fd = -1; + if (m_field_id == TYPE_FD_STDIN_TYPE) { - return NULL; + fd = 0; } - m_tstr = fdinfo->get_typestring(); - RETURN_EXTRACT_STRING(m_tstr); - } - case TYPE_FD_STDOUT_TYPE: - { - auto fdtable_ptr = tinfo->get_fd_table(); - if (fdtable_ptr == nullptr) + else if (m_field_id == TYPE_FD_STDOUT_TYPE) { - return NULL; + fd = 1; } - auto fdinfo = fdtable_ptr->find(1); - if (fdinfo == nullptr) + else if (m_field_id == TYPE_FD_STDERR_TYPE) { - return NULL; + fd = 2; } - m_tstr = fdinfo->get_typestring(); - RETURN_EXTRACT_STRING(m_tstr); - } - case TYPE_FD_STDERR_TYPE: - { auto fdtable_ptr = tinfo->get_fd_table(); if (fdtable_ptr == nullptr) { return NULL; } - auto fdinfo = fdtable_ptr->find(2); + auto fdinfo = fdtable_ptr->find(fd); if (fdinfo == nullptr) { return NULL; @@ -1664,43 +1649,28 @@ uint8_t* sinsp_filter_check_thread::extract_single(sinsp_evt *evt, uint32_t* len RETURN_EXTRACT_STRING(m_tstr); } case TYPE_FD_STDIN_NAME: + case TYPE_FD_STDOUT_NAME: + case TYPE_FD_STDERR_NAME: { - auto fdtable_ptr = tinfo->get_fd_table(); - if (fdtable_ptr == nullptr) - { - return NULL; - } - auto fdinfo = fdtable_ptr->find(0); - if (fdinfo == nullptr) + int64_t fd = -1; + if (m_field_id == TYPE_FD_STDIN_NAME) { - return NULL; + fd = 0; } - m_tstr = fdinfo->m_name.c_str(); - RETURN_EXTRACT_STRING(m_tstr); - } - case TYPE_FD_STDOUT_NAME: - { - auto fdtable_ptr = tinfo->get_fd_table(); - if (fdtable_ptr == nullptr) + else if (m_field_id == TYPE_FD_STDOUT_NAME) { - return NULL; + fd = 1; } - auto fdinfo = fdtable_ptr->find(1); - if (fdinfo == nullptr) + else if (m_field_id == TYPE_FD_STDERR_NAME) { - return NULL; + fd = 2; } - m_tstr = fdinfo->m_name.c_str(); - RETURN_EXTRACT_STRING(m_tstr); - } - case TYPE_FD_STDERR_NAME: - { auto fdtable_ptr = tinfo->get_fd_table(); if (fdtable_ptr == nullptr) { return NULL; } - auto fdinfo = fdtable_ptr->find(2); + auto fdinfo = fdtable_ptr->find(fd); if (fdinfo == nullptr) { return NULL; From f20de4a916d65319b01341b67b1a7cb5f9adfe21 Mon Sep 17 00:00:00 2001 From: Lorenzo Susini Date: Tue, 18 Jun 2024 08:35:35 +0000 Subject: [PATCH 4/5] test(userspace/libsinsp): test stdin, stdout, stderr type and name fields Signed-off-by: Lorenzo Susini --- userspace/libsinsp/test/filterchecks/proc.cpp | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/userspace/libsinsp/test/filterchecks/proc.cpp b/userspace/libsinsp/test/filterchecks/proc.cpp index 18b6152e4e..a4fcda7bd9 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.fd.stdin.type"), "ipv4"); + ASSERT_EQ(get_field_as_string(evt, "proc.fd.stdout.type"), "ipv4"); + ASSERT_EQ(get_field_as_string(evt, "proc.fd.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.fd.stdin.name"), tuple_str); + ASSERT_EQ(get_field_as_string(evt, "proc.fd.stdout.name"), tuple_str); + ASSERT_EQ(get_field_as_string(evt, "proc.fd.stderr.name"), tuple_str); +} +#endif \ No newline at end of file From 62a08b7888859827dc6746754e9b79e7615e6471 Mon Sep 17 00:00:00 2001 From: Lorenzo Susini Date: Tue, 18 Jun 2024 09:10:01 +0000 Subject: [PATCH 5/5] chore: change naming to proc.std{in,out,err} for simplicity Signed-off-by: Lorenzo Susini --- userspace/libsinsp/sinsp_filtercheck_thread.cpp | 12 ++++++------ userspace/libsinsp/test/filterchecks/proc.cpp | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/userspace/libsinsp/sinsp_filtercheck_thread.cpp b/userspace/libsinsp/sinsp_filtercheck_thread.cpp index 82fe9d35bc..2d59cfbd50 100644 --- a/userspace/libsinsp/sinsp_filtercheck_thread.cpp +++ b/userspace/libsinsp/sinsp_filtercheck_thread.cpp @@ -126,12 +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.fd.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.fd.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.fd.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.fd.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.fd.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.fd.stderr.name", "Standard Error fd name", "The name of the file descriptor 2, corresponding to stderr, of the process generating the event."}, + {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() diff --git a/userspace/libsinsp/test/filterchecks/proc.cpp b/userspace/libsinsp/test/filterchecks/proc.cpp index a4fcda7bd9..681034d1d2 100644 --- a/userspace/libsinsp/test/filterchecks/proc.cpp +++ b/userspace/libsinsp/test/filterchecks/proc.cpp @@ -138,13 +138,13 @@ TEST_F(sinsp_with_test_input, PROC_FILTER_stdin_stdout_stderr) // 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.fd.stdin.type"), "ipv4"); - ASSERT_EQ(get_field_as_string(evt, "proc.fd.stdout.type"), "ipv4"); - ASSERT_EQ(get_field_as_string(evt, "proc.fd.stderr.type"), "ipv4"); + 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.fd.stdin.name"), tuple_str); - ASSERT_EQ(get_field_as_string(evt, "proc.fd.stdout.name"), tuple_str); - ASSERT_EQ(get_field_as_string(evt, "proc.fd.stderr.name"), tuple_str); + 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