about summary refs log tree commit diff
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>