| // SPDX-License-Identifier: GPL-2.0-or-later |
| /* Copyright (c) 2018 FUJITSU LIMITED. All rights reserved. |
| * Authors: Jinhui huang <[email protected]> |
| * Xiao Yang <[email protected]> |
| */ |
| /* Test Description: |
| * This case checks the basic functionality of the execveat(2): |
| * 1) When pathname is relative, it is relative to the directory where |
| * the executed process is located and the dirfd is the descriptor of |
| * the directory. |
| * 2) When pathname is relative and dirfd is the special value AT_FDCWD, |
| * the pathname is the relative to the current working directory of |
| * the calling process. |
| * 3) When pathname is absolute, dirfd can be ignored. |
| * 4) When pathname is an empty string and the flag AT_EMPTY_PATH is |
| * specified, dirfd specifies the file to be executed. |
| */ |
| |
| #define _GNU_SOURCE |
| #include "config.h" |
| |
| #include <stdio.h> |
| #include <errno.h> |
| |
| #include "tst_test.h" |
| #include "lapi/execveat.h" |
| #include "lapi/fcntl.h" |
| #include "execveat.h" |
| |
| #define TESTDIR "testdir" |
| #define TEST_APP "execveat_child" |
| #define TEST_REL_APP TESTDIR"/"TEST_APP |
| |
| static int fd1, fd4; |
| static int fd2 = AT_FDCWD, fd3 = -1; |
| static char app_abs_path[512]; |
| |
| static struct tcase { |
| int *fd; |
| char *pathname; |
| int flag; |
| } tcases[] = { |
| {&fd1, TEST_APP, 0}, |
| {&fd2, TEST_REL_APP, 0}, |
| {&fd3, app_abs_path, 0}, |
| {&fd4, "", AT_EMPTY_PATH}, |
| }; |
| |
| static void verify_execveat(unsigned int i) |
| { |
| struct tcase *tc = &tcases[i]; |
| char *argv[2] = {TEST_APP, NULL}; |
| pid_t pid; |
| |
| pid = SAFE_FORK(); |
| if (pid == 0) { |
| TEST(execveat(*tc->fd, tc->pathname, argv, environ, tc->flag)); |
| tst_res(TFAIL | TERRNO, "execveat() returns unexpected errno"); |
| } |
| } |
| |
| static void setup(void) |
| { |
| char cur_dir_path[512]; |
| |
| check_execveat(); |
| |
| SAFE_MKDIR(TESTDIR, 0777); |
| SAFE_CP(TEST_APP, TEST_REL_APP); |
| |
| SAFE_GETCWD(cur_dir_path, sizeof(cur_dir_path)); |
| sprintf(app_abs_path, "%s/%s", cur_dir_path, TEST_REL_APP); |
| |
| fd1 = SAFE_OPEN(TESTDIR, O_DIRECTORY); |
| fd4 = SAFE_OPEN(TEST_REL_APP, O_PATH); |
| } |
| |
| static void cleanup(void) |
| { |
| if (fd1 > 0) |
| SAFE_CLOSE(fd1); |
| |
| if (fd4 > 0) |
| SAFE_CLOSE(fd4); |
| } |
| |
| static const char *const resource_files[] = { |
| TEST_APP, |
| NULL, |
| }; |
| |
| static struct tst_test test = { |
| .resource_files = resource_files, |
| .tcnt = ARRAY_SIZE(tcases), |
| .test = verify_execveat, |
| .child_needs_reinit = 1, |
| .forks_child = 1, |
| .cleanup = cleanup, |
| .setup = setup, |
| }; |