Skip to content

Commit c9388df

Browse files
committed
tests(modern_bpf): add a new test for execveat success
Signed-off-by: Andrea Terzolo <[email protected]>
1 parent 90a8d5e commit c9388df

File tree

1 file changed

+112
-3
lines changed

1 file changed

+112
-3
lines changed

test/modern_bpf/test_suites/syscall_exit_suite/execveat_x.cpp

+112-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
#if defined(__NR_execveat) && defined(__NR_capget)
66

7-
TEST(SyscallExit, execveatX)
7+
TEST(SyscallExit, execveatX_failure)
88
{
99
auto evt_test = get_syscall_event_test(__NR_execveat, EXIT_EVENT);
1010

@@ -40,8 +40,8 @@ TEST(SyscallExit, execveatX)
4040
*/
4141
int dirfd = AT_FDCWD;
4242
char pathname[] = "//**null-file-path**//";
43-
const char* newargv[] = {pathname, "first_argv", "second_argv", NULL};
44-
const char* newenviron[] = {"IN_TEST=yes", "3_ARGUMENT=yes", "2_ARGUMENT=no", NULL};
43+
const char *newargv[] = {pathname, "first_argv", "second_argv", NULL};
44+
const char *newenviron[] = {"IN_TEST=yes", "3_ARGUMENT=yes", "2_ARGUMENT=no", NULL};
4545
int flags = AT_SYMLINK_NOFOLLOW;
4646
assert_syscall_state(SYSCALL_FAILURE, "execveat", syscall(__NR_execveat, dirfd, pathname, newargv, newenviron, flags));
4747
int64_t errno_value = -errno;
@@ -143,4 +143,113 @@ TEST(SyscallExit, execveatX)
143143

144144
evt_test->assert_num_params_pushed(23);
145145
}
146+
147+
#if !defined(CAPTURE_SCHED_PROC_EXEC) && defined(__NR_clone3) && defined(__NR_wait4) && defined(__NR_execve)
148+
149+
#include <linux/sched.h>
150+
151+
TEST(SyscallExit, execveatX_success)
152+
{
153+
/* In case of success the `execveat` syscall returns a `PPME_EXECVE_X` event
154+
* and not a `PPME_EXECVEAT_X`
155+
*/
156+
auto evt_test = get_syscall_event_test(__NR_execve, EXIT_EVENT);
157+
158+
evt_test->enable_capture();
159+
160+
/*=============================== TRIGGER SYSCALL ===========================*/
161+
162+
/* Prepare the execve args */
163+
int dirfd = 0;
164+
const char *pathname = "/usr/bin/echo";
165+
const char *comm = "echo";
166+
const char *argv[] = {pathname, "[OUTPUT] SyscallExit.execveatX_success test", NULL};
167+
const char *envp[] = {"IN_TEST=yes", "3_ARGUMENT=yes", "2_ARGUMENT=no", NULL};
168+
int flags = 0;
169+
170+
/* We need to use `SIGCHLD` otherwise the parent won't receive any signal
171+
* when the child terminates.
172+
*/
173+
struct clone_args cl_args = {0};
174+
cl_args.exit_signal = SIGCHLD;
175+
pid_t ret_pid = syscall(__NR_clone3, &cl_args, sizeof(cl_args));
176+
177+
if(ret_pid == 0)
178+
{
179+
syscall(__NR_execveat, dirfd, pathname, argv, envp, flags);
180+
exit(EXIT_FAILURE);
181+
}
182+
183+
assert_syscall_state(SYSCALL_SUCCESS, "clone3", ret_pid, NOT_EQUAL, -1);
184+
185+
/* Catch the child before doing anything else. */
186+
int status = 0;
187+
int options = 0;
188+
assert_syscall_state(SYSCALL_SUCCESS, "wait4", syscall(__NR_wait4, ret_pid, &status, options, NULL), NOT_EQUAL, -1);
189+
190+
if(__WEXITSTATUS(status) == EXIT_FAILURE)
191+
{
192+
FAIL() << "The child execveat failed." << std::endl;
193+
}
194+
195+
/*=============================== TRIGGER SYSCALL ===========================*/
196+
197+
evt_test->disable_capture();
198+
199+
/* We search for a child event. */
200+
evt_test->assert_event_presence(ret_pid);
201+
202+
if(HasFatalFailure())
203+
{
204+
return;
205+
}
206+
207+
evt_test->parse_event();
208+
209+
evt_test->assert_header();
210+
211+
/*=============================== ASSERT PARAMETERS ===========================*/
212+
213+
/* Please note here we cannot assert all the params, we check only the possible ones. */
214+
215+
/* Parameter 1: res (type: PT_ERRNO)*/
216+
evt_test->assert_numeric_param(1, (int64_t)0);
217+
218+
/* Parameter 2: exe (type: PT_CHARBUF) */
219+
evt_test->assert_charbuf_param(2, pathname);
220+
221+
/* Parameter 3: args (type: PT_CHARBUFARRAY) */
222+
/* Starting from `1` because the first is `exe`. */
223+
evt_test->assert_charbuf_array_param(3, &argv[1]);
224+
225+
/* Parameter 4: tid (type: PT_PID) */
226+
evt_test->assert_numeric_param(4, (int64_t)ret_pid);
227+
228+
/* Parameter 5: pid (type: PT_PID) */
229+
/* We are the main thread of the process so it's equal to `tid`. */
230+
evt_test->assert_numeric_param(5, (int64_t)ret_pid);
231+
232+
/* Parameter 6: ptid (type: PT_PID) */
233+
evt_test->assert_numeric_param(6, (int64_t)::getpid());
234+
235+
/* Parameter 7: cwd (type: PT_CHARBUF) */
236+
/* leave the current working directory empty like in the old probe. */
237+
evt_test->assert_empty_param(7);
238+
239+
/* Parameter 14: comm (type: PT_CHARBUF) */
240+
evt_test->assert_charbuf_param(14, comm);
241+
242+
/* Parameter 16: env (type: PT_CHARBUFARRAY) */
243+
evt_test->assert_charbuf_array_param(16, &envp[0]);
244+
245+
/* Parameter 20: flags (type: PT_UINT32) */
246+
/* Right now we send always `0`. */
247+
evt_test->assert_numeric_param(20, (uint32_t)0);
248+
249+
/*=============================== ASSERT PARAMETERS ===========================*/
250+
251+
evt_test->assert_num_params_pushed(23);
252+
}
253+
#endif
254+
146255
#endif

0 commit comments

Comments
 (0)