summaryrefslogtreecommitdiff
path: root/posix/tst-execveat.c
diff options
context:
space:
mode:
Diffstat (limited to 'posix/tst-execveat.c')
-rw-r--r--posix/tst-execveat.c142
1 files changed, 142 insertions, 0 deletions
diff --git a/posix/tst-execveat.c b/posix/tst-execveat.c
new file mode 100644
index 0000000000..0e0a33deb5
--- /dev/null
+++ b/posix/tst-execveat.c
@@ -0,0 +1,142 @@
+/* Copyright (C) 2017-2020 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <support/check.h>
+#include <support/xdlfcn.h>
+#include <support/xstdio.h>
+#include <support/xunistd.h>
+#include <wait.h>
+#include <support/test-driver.h>
+
+int
+call_execveat (int fd, const char *pathname, int flags, int expected_fail, int num)
+{
+ char *argv[] = { (char *) "sh", (char *) "-c", (char *) "exit 3", NULL };
+ char *envp[] = { (char *) "FOO=BAR", NULL };
+ pid_t pid;
+ int status;
+
+ printf("call number: %d\n", num);
+
+ pid = xfork ();
+ if (pid == 0)
+ {
+
+ TEST_COMPARE (execveat (fd, "sh", argv, envp, flags), -1);
+ if (errno == ENOSYS)
+ FAIL_UNSUPPORTED ("execveat is unimplemented");
+ else if (errno == expected_fail)
+ {
+ if (test_verbose > 0)
+ printf ("expected fail: errno %d\n", errno);
+ _exit(0);
+ }
+ else
+ FAIL_EXIT1 ("execveat failed, errno %d", errno);
+ }
+ xwaitpid (pid, &status, 0);
+
+ if (WIFEXITED (status))
+ if (expected_fail)
+ TEST_COMPARE (WEXITSTATUS (status), 0);
+ else
+ TEST_COMPARE (WEXITSTATUS (status), 3);
+ else if (!expected_fail)
+ FAIL_EXIT1 ("execveat failed");
+ return 0;
+}
+
+static int
+do_test (void)
+{
+ DIR *dirp;
+ int fd;
+
+ dirp = opendir ("/bin");
+ if (dirp == NULL)
+ FAIL_EXIT1 ("failed to open /bin");
+ fd = dirfd (dirp);
+
+ /* Call execveat for various fd/pathname combinations */
+
+ /* fd: valid dir, pathname: relative, flags:: 0 */
+ call_execveat (fd, "sh", 0, 0, 1);
+ /* fd: valid dir, pathname: relative, flags: O_PATH */
+ call_execveat (fd, "sh", O_PATH, 0, 2);
+ /* fd: AT_FDCWD, pathname: relative, flags: 0
+ If pathname is relative and dirfd is the special value AT_FDCWD, then
+ pathname is interpreted relative to the current working directory of
+ the calling process */
+ chdir("/bin");
+ call_execveat (AT_FDCWD, "sh", 0, 0, 3);
+ xclose (fd);
+ closedir (dirp);
+
+ dirp = opendir ("/usr");
+ fd = dirfd (dirp);
+ chdir ("/etc");
+ /* fd: AT_FDCWD, pathname: absolute in different dir, flags: 0 */
+ call_execveat (AT_FDCWD, "/bin/sh", 0, 0, 4);
+
+ /* fd: valid dir, pathname: absolute in differen dir, flags: 0 */
+ call_execveat (fd, "/bin/sh", 0, 0, 5);
+ /* fd: valid dir, pathname: absolute, flags: O_PATH */
+ call_execveat (fd, "/bin/sh", O_PATH, 0, 6);
+ xclose (fd);
+ closedir (dirp);
+
+ fd = xopen ("/bin/sh", 0, 0);
+ /* fd: regular file, pathname: relative, flags: 0 */
+ call_execveat(fd, "sh", 0, ENOTDIR, 7);
+ /* fd: regular file, pathname: absolute, flags: 0 */
+ call_execveat (fd, "/bin/sh", 0, 0, 8);
+ xclose (fd);
+
+ fd = xopen ("/bin/sh", O_PATH, 0);
+ /* fd: O_PATH of regular file, pathname: empty, flags: 0 */
+ call_execveat (fd, "", 0, ENOTDIR, 10);
+ /* fd: O_PATH of regular file, pathname: empty, flags: AT_EMPTY_PATH */
+ call_execveat (fd, "", AT_EMPTY_PATH, 0, 11); // fails with ENOTDIR (20)
+ /* fd: O_PATH of regular file, pathname: empty,
+ flags: AT_EMPTY_PATH AT_SYMLINK_NOFOLLOW */
+ // call_execveat (fd, "", AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW, NULL, 0, 12); //fails with ENOTDIR
+ xclose (fd);
+
+ fd = xopen ("/bin/sh", O_NOFOLLOW | O_PATH, 0);
+ /* fd: O_PATH of symbolic link, pathname: empty, flags: */
+// call_execveat(fd, "", 0, 1, 13); //fails with errno ENOTDIR
+ /* fd: O_PATH of symbolic link, pathname: empty, flags: */
+// call_execveat (fd, "", AT_EMPTY_PATH, 0, 14); //fails with errno ENOTDIR
+ /* fd: O_PATH of symbolic link, pathname: empty,
+ flags: AT_EMPTY_PATH AT_SYMLINK_NOFOLLOW */
+ call_execveat (fd, "", AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW, ENOTDIR, 15);
+ xclose (fd);
+
+ /* Call execveat with closed fd, we expect this to fail with EBADF */
+ call_execveat (fd, "sh", 0, EBADF, 16);
+ /* Call execveat with closed fd, we expect this to pass because the pathname is
+ absolute */
+ call_execveat (fd, "/bin/sh", 0, 0, 17);
+
+ return 0;
+}
+
+#include <support/test-driver.c>