Skip to content

Commit

Permalink
update(userspace): support execveat exit event for s390x
Browse files Browse the repository at this point in the history
Signed-off-by: Andrea Terzolo <[email protected]>
  • Loading branch information
Andreagit97 committed Oct 25, 2022
1 parent 145b691 commit 9288fb8
Show file tree
Hide file tree
Showing 2 changed files with 165 additions and 6 deletions.
18 changes: 12 additions & 6 deletions userspace/libsinsp/parsers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1711,17 +1711,17 @@ void sinsp_parser::parse_execve_exit(sinsp_evt *evt)
ASSERT(parinfo->m_len == sizeof(int64_t));
retval = *(int64_t *)parinfo->m_val;

/* Please note here we will never parse an `PPME_SYSCALL_EXECVEAT_X` event since it is
* generated only in case of failure, here if `retval<0` we return immediately.
* If we remove this `if` we need to support also the `PPME_SYSCALL_EXECVEAT_X` event.
/* 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
* this event in the parser.
*/
if(retval < 0)
{
return;
}

//
// We get here when `execve` return. The thread has already been added by a previous fork or clone,
// We get here when `execve` or `execveat` return. The thread has already been added by a previous fork or clone,
// and we just update the entry with the new information.
//
if(!evt->m_tinfo)
Expand Down Expand Up @@ -1754,6 +1754,7 @@ void sinsp_parser::parse_execve_exit(sinsp_evt *evt)
case PPME_SYSCALL_EXECVE_17_X:
case PPME_SYSCALL_EXECVE_18_X:
case PPME_SYSCALL_EXECVE_19_X:
case PPME_SYSCALL_EXECVEAT_X:
// Get the comm
parinfo = evt->get_param(13);
evt->m_tinfo->m_comm = parinfo->m_val;
Expand Down Expand Up @@ -1799,6 +1800,7 @@ void sinsp_parser::parse_execve_exit(sinsp_evt *evt)
case PPME_SYSCALL_EXECVE_17_X:
case PPME_SYSCALL_EXECVE_18_X:
case PPME_SYSCALL_EXECVE_19_X:
case PPME_SYSCALL_EXECVEAT_X:
// Get the pgflt_maj
parinfo = evt->get_param(8);
ASSERT(parinfo->m_len == sizeof(uint64_t));
Expand Down Expand Up @@ -1847,6 +1849,7 @@ void sinsp_parser::parse_execve_exit(sinsp_evt *evt)
case PPME_SYSCALL_EXECVE_17_X:
case PPME_SYSCALL_EXECVE_18_X:
case PPME_SYSCALL_EXECVE_19_X:
case PPME_SYSCALL_EXECVEAT_X:
// Get the environment
parinfo = evt->get_param(15);
evt->m_tinfo->set_env(parinfo->m_val, parinfo->m_len);
Expand Down Expand Up @@ -1884,6 +1887,7 @@ void sinsp_parser::parse_execve_exit(sinsp_evt *evt)
case PPME_SYSCALL_EXECVE_17_X:
case PPME_SYSCALL_EXECVE_18_X:
case PPME_SYSCALL_EXECVE_19_X:
case PPME_SYSCALL_EXECVEAT_X:
// Get the tty
parinfo = evt->get_param(16);
ASSERT(parinfo->m_len == sizeof(int32_t));
Expand All @@ -1903,7 +1907,8 @@ void sinsp_parser::parse_execve_exit(sinsp_evt *evt)
* we can do nothing.
*/
if((etype == PPME_SYSCALL_EXECVE_18_X ||
etype == PPME_SYSCALL_EXECVE_19_X)
etype == PPME_SYSCALL_EXECVE_19_X ||
etype == PPME_SYSCALL_EXECVEAT_X)
&&
retrieve_enter_event(enter_evt, evt))
{
Expand Down Expand Up @@ -2036,6 +2041,7 @@ void sinsp_parser::parse_execve_exit(sinsp_evt *evt)
case PPME_SYSCALL_EXECVE_18_X:
break;
case PPME_SYSCALL_EXECVE_19_X:
case PPME_SYSCALL_EXECVEAT_X:
// Get the vpgid
parinfo = evt->get_param(17);
ASSERT(parinfo->m_len == sizeof(int64_t));
Expand Down Expand Up @@ -2077,7 +2083,7 @@ void sinsp_parser::parse_execve_exit(sinsp_evt *evt)
// Get capabilities
if(evt->get_num_params() > 22)
{
if(etype == PPME_SYSCALL_EXECVE_19_X)
if(etype == PPME_SYSCALL_EXECVE_19_X || etype == PPME_SYSCALL_EXECVEAT_X)
{
parinfo = evt->get_param(20);
ASSERT(parinfo->m_len == sizeof(uint64_t));
Expand Down
153 changes: 153 additions & 0 deletions userspace/libsinsp/test/sinsp.ut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,159 @@ TEST_F(sinsp_with_test_input, execveat_invalid_path)
}
}

/* Same as `execveat_empty_path_flag` but with `PPME_SYSCALL_EXECVEAT_X` as exit event
* since on s390x architectures the `execveat` syscall correctly returns a `PPME_SYSCALL_EXECVEAT_X`
* exit event in case of success.
*/
TEST_F(sinsp_with_test_input, execveat_empty_path_flag_s390)
{
add_default_init_thread();

open_inspector();
sinsp_evt *evt = NULL;

/* We generate a `dirfd` associated with the file that
* we want to run with the `execveat`,
*/
int64_t dirfd = 3;
const char *file_to_run = "/tmp/s390x/file_to_run";
add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_OPEN_E, 3, file_to_run, 0, 0);
add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_OPEN_X, 6, dirfd, file_to_run, 0, 0, 0, 0);

/* Now we call the `execveat_e` event,`sinsp` will store this enter
* event in the thread storage, in this way the exit event can use it.
*/
add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_EXECVEAT_E, 3, dirfd, "<NA>", PPM_EXVAT_AT_EMPTY_PATH);

struct scap_const_sized_buffer empty_bytebuf = {nullptr, 0};
evt = add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_EXECVEAT_X, 23, 0, "<NA>", empty_bytebuf, 1, 1, 1, "<NA>", 0, 0, 0, 0, 0, 0, "<NA>", empty_bytebuf, empty_bytebuf, 0, 0, 0, 0, 0, 0, 0);

/* The `exepath` should be the file pointed by the `dirfd` since `execveat` is called with
* `AT_EMPTY_PATH` flag.
*/
if(evt->get_thread_info())
{
ASSERT_STREQ(evt->get_thread_info()->m_exepath.c_str(), file_to_run);
}
else
{
FAIL();
}
}

/* Same as `execveat_relative_path` but with `PPME_SYSCALL_EXECVEAT_X` as exit event
* since on s390x architectures the `execveat` syscall correctly returns a `PPME_SYSCALL_EXECVEAT_X`
* exit event in case of success.
*/
TEST_F(sinsp_with_test_input, execveat_relative_path_s390)
{
add_default_init_thread();

open_inspector();
sinsp_evt *evt = NULL;

/* We generate a `dirfd` associated with the directory that contains the file that
* we want to run with the `execveat`,
*/
int64_t dirfd = 3;
const char *directory = "/tmp/s390x/dir";
add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_OPEN_E, 3, directory, 0, 0);
add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_OPEN_X, 6, dirfd, directory, 0, 0, 0, 0);

/* Now we call the `execveat_e` event,`sinsp` will store this enter
* event in the thread storage, in this way the exit event can use it.
*/
add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_EXECVEAT_E, 3, dirfd, "file", 0);

struct scap_const_sized_buffer empty_bytebuf = {nullptr, 0};
evt = add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_EXECVEAT_X, 23, 0, "<NA>", empty_bytebuf, 1, 1, 1, "<NA>", 0, 0, 0, 0, 0, 0, "<NA>", empty_bytebuf, empty_bytebuf, 0, 0, 0, 0, 0, 0, 0);

/* The `exepath` should be the directory pointed by the `dirfd` + the pathname
* specified in the `execveat` enter event.
*/
if(evt->get_thread_info())
{
ASSERT_STREQ(evt->get_thread_info()->m_exepath.c_str(), "/tmp/s390x/dir/file");
}
else
{
FAIL();
}
}

/* Same as `execveat_absolute_path` but with `PPME_SYSCALL_EXECVEAT_X` as exit event
* since on s390x architectures the `execveat` syscall correctly returns a `PPME_SYSCALL_EXECVEAT_X`
* exit event in case of success.
*/
TEST_F(sinsp_with_test_input, execveat_absolute_path_s390)
{
add_default_init_thread();

open_inspector();
sinsp_evt *evt = NULL;

/* Now we call the `execveat_e` event,`sinsp` will store this enter
* event in the thread storage, in this way the exit event can use it.
*/
int invalid_dirfd = 0;
add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_EXECVEAT_E, 3, invalid_dirfd, "/tmp/s390/file", 0);

struct scap_const_sized_buffer empty_bytebuf = {nullptr, 0};
evt = add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_EXECVEAT_X, 23, 0, "<NA>", empty_bytebuf, 1, 1, 1, "<NA>", 0, 0, 0, 0, 0, 0, "<NA>", empty_bytebuf, empty_bytebuf, 0, 0, 0, 0, 0, 0, 0);

/* The `exepath` should be the absolute file path that we passed in the
* `execveat` enter event.
*/
if(evt->get_thread_info())
{
ASSERT_STREQ(evt->get_thread_info()->m_exepath.c_str(), "/tmp/s390/file");
}
else
{
FAIL();
}
}

/* Same as `execveat_invalid_path` but with `PPME_SYSCALL_EXECVEAT_X` as exit event
* since on s390x architectures the `execveat` syscall correctly returns a `PPME_SYSCALL_EXECVEAT_X`
* exit event in case of success.
*/
TEST_F(sinsp_with_test_input, execveat_invalid_path_s390)
{
add_default_init_thread();

open_inspector();
sinsp_evt *evt = NULL;

/* We generate a `dirfd` associated with the directory that contains the file that
* we want to run with the `execveat`,
*/
int64_t dirfd = 3;
const char *directory = "/tmp/s390/dir";
add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_OPEN_E, 3, directory, 0, 0);
add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_OPEN_X, 6, dirfd, directory, 0, 0, 0, 0);

/* Now we call the `execveat_e` event,`sinsp` will store this enter
* event in the thread storage, in this way the exit event can use it.
*/
add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_EXECVEAT_E, 3, dirfd, "<NA>", 0);

struct scap_const_sized_buffer empty_bytebuf = {nullptr, 0};
evt = add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_EXECVEAT_X, 23, 0, "<NA>", empty_bytebuf, 1, 1, 1, "<NA>", 0, 0, 0, 0, 0, 0, "<NA>", empty_bytebuf, empty_bytebuf, 0, 0, 0, 0, 0, 0, 0);

/* The `exepath` should be `<NA>`, sinsp should recognize that the `pathname`
* is invalid and should set `<NA>`.
*/
if(evt->get_thread_info())
{
ASSERT_STREQ(evt->get_thread_info()->m_exepath.c_str(), "<NA>");
}
else
{
FAIL();
}
}

TEST_F(sinsp_with_test_input, creates_fd_generic)
{
add_default_init_thread();
Expand Down

0 comments on commit 9288fb8

Please sign in to comment.