|
4 | 4 |
|
5 | 5 | #if defined(__NR_execveat) && defined(__NR_capget)
|
6 | 6 |
|
7 |
| -TEST(SyscallExit, execveatX) |
| 7 | +TEST(SyscallExit, execveatX_failure) |
8 | 8 | {
|
9 | 9 | auto evt_test = get_syscall_event_test(__NR_execveat, EXIT_EVENT);
|
10 | 10 |
|
@@ -40,8 +40,8 @@ TEST(SyscallExit, execveatX)
|
40 | 40 | */
|
41 | 41 | int dirfd = AT_FDCWD;
|
42 | 42 | 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}; |
45 | 45 | int flags = AT_SYMLINK_NOFOLLOW;
|
46 | 46 | assert_syscall_state(SYSCALL_FAILURE, "execveat", syscall(__NR_execveat, dirfd, pathname, newargv, newenviron, flags));
|
47 | 47 | int64_t errno_value = -errno;
|
@@ -143,4 +143,113 @@ TEST(SyscallExit, execveatX)
|
143 | 143 |
|
144 | 144 | evt_test->assert_num_params_pushed(23);
|
145 | 145 | }
|
| 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 | + |
146 | 255 | #endif
|
0 commit comments