summaryrefslogtreecommitdiff
path: root/posix
diff options
context:
space:
mode:
Diffstat (limited to 'posix')
-rw-r--r--posix/Makefile5
-rw-r--r--posix/Versions3
-rw-r--r--posix/execveat.c40
-rw-r--r--posix/tst-execveat.c142
-rw-r--r--posix/unistd.h5
5 files changed, 193 insertions, 2 deletions
diff --git a/posix/Makefile b/posix/Makefile
index 605ddbade8..2e96d7e4a1 100644
--- a/posix/Makefile
+++ b/posix/Makefile
@@ -65,7 +65,8 @@ routines := \
spawnattr_setsigmask spawnattr_setschedpolicy spawnattr_setschedparam \
posix_madvise \
get_child_max sched_cpucount sched_cpualloc sched_cpufree \
- streams-compat
+ streams-compat \
+ execveat
aux := init-posix environ
tests := test-errno tstgetopt testfnm runtests runptests \
@@ -102,7 +103,7 @@ tests := test-errno tstgetopt testfnm runtests runptests \
tst-sysconf-empty-chroot tst-glob_symlinks tst-fexecve \
tst-glob-tilde test-ssize-max tst-spawn4 bug-regex37 \
bug-regex38 tst-regcomp-truncated tst-spawn-chdir \
- tst-wordexp-nocmd
+ tst-wordexp-nocmd tst-execveat
tests-internal := bug-regex5 bug-regex20 bug-regex33 \
tst-rfc3484 tst-rfc3484-2 tst-rfc3484-3 \
tst-glob_lstat_compat tst-spawn4-compat
diff --git a/posix/Versions b/posix/Versions
index 7d06a6d0c0..8a50a2b617 100644
--- a/posix/Versions
+++ b/posix/Versions
@@ -147,6 +147,9 @@ libc {
}
GLIBC_2.30 {
}
+ GLIBC_2.32 {
+ execveat;
+ }
GLIBC_PRIVATE {
__libc_fork; __libc_pread; __libc_pwrite;
__nanosleep_nocancel; __pause_nocancel;
diff --git a/posix/execveat.c b/posix/execveat.c
new file mode 100644
index 0000000000..cab61952b3
--- /dev/null
+++ b/posix/execveat.c
@@ -0,0 +1,40 @@
+/* Copyright (C) 1991-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 <errno.h>
+#include <stddef.h>
+#include <unistd.h>
+
+/* Replace the current process, executing PATH relative to DIFRD with
+ * arguments ARGV and environment ENVP.
+ * ARGV and ENVP are terminated by NULL pointers. */
+int
+__execveat (int dirfd, const char *path, char *const argv[], char *const envp[],
+ int flags)
+{
+ if (difrd < 0 || path == NULL || argv == NULL || envp == NULL)
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ __set_errno (ENOSYS);
+ return -1;
+}
+stub_warning (execveat)
+
+weak_alias (__execveat, execveat)
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>
diff --git a/posix/unistd.h b/posix/unistd.h
index 32b8161619..b1117f2eda 100644
--- a/posix/unistd.h
+++ b/posix/unistd.h
@@ -295,6 +295,11 @@ extern int euidaccess (const char *__name, int __type)
/* An alias for `euidaccess', used by some other systems. */
extern int eaccess (const char *__name, int __type)
__THROW __nonnull ((1));
+
+/* Execute program relative to a directory file descriptor. */
+extern int execveat (int __fd, const char *__path, char *const __argv[],
+ char *const __envp[], int __flags)
+ __THROW __nonnull ((2, 3));
#endif
#ifdef __USE_ATFILE