diff options
author | Lennart Poettering <lennart@poettering.net> | 2020-12-03 14:58:20 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-03 14:58:20 +0100 |
commit | 6dd16814a56d2ce96ab3c4c611a61e47f2f7b663 (patch) | |
tree | 38cdececafec3b424ca0acbcd8d268e7419931e8 /src/shared/exec-util.c | |
parent | 03d8ebb935fb989e03ec27065a16bf9b79a5816b (diff) | |
parent | ceedbf8185fc7593366679f02d31da63af8c4bd1 (diff) | |
download | systemd-6dd16814a56d2ce96ab3c4c611a61e47f2f7b663.tar.gz |
Merge pull request #17079 from keszybz/late-exec-resolution
Resolve executable paths before execution, use fexecve()
Diffstat (limited to 'src/shared/exec-util.c')
-rw-r--r-- | src/shared/exec-util.c | 26 |
1 files changed, 25 insertions, 1 deletions
diff --git a/src/shared/exec-util.c b/src/shared/exec-util.c index 61ee3b18d5..bdea60ca02 100644 --- a/src/shared/exec-util.c +++ b/src/shared/exec-util.c @@ -11,11 +11,13 @@ #include "conf-files.h" #include "env-file.h" #include "env-util.h" +#include "errno-util.h" #include "exec-util.h" #include "fd-util.h" #include "fileio.h" #include "hashmap.h" #include "macro.h" +#include "missing_syscall.h" #include "process-util.h" #include "rlimit-util.h" #include "serialize.h" @@ -33,7 +35,6 @@ assert_cc(EAGAIN == EWOULDBLOCK); static int do_spawn(const char *path, char *argv[], int stdout_fd, pid_t *pid) { - pid_t _pid; int r; @@ -444,3 +445,26 @@ ExecCommandFlags exec_command_flags_from_string(const char *s) { else return 1 << idx; } + +int fexecve_or_execve(int executable_fd, const char *executable, char *const argv[], char *const envp[]) { +#if ENABLE_FEXECVE + execveat(executable_fd, "", argv, envp, AT_EMPTY_PATH); + + if (IN_SET(errno, ENOSYS, ENOENT) || ERRNO_IS_PRIVILEGE(errno)) + /* Old kernel or a script or an overzealous seccomp filter? Let's fall back to execve(). + * + * fexecve(3): "If fd refers to a script (i.e., it is an executable text file that names a + * script interpreter with a first line that begins with the characters #!) and the + * close-on-exec flag has been set for fd, then fexecve() fails with the error ENOENT. This + * error occurs because, by the time the script interpreter is executed, fd has already been + * closed because of the close-on-exec flag. Thus, the close-on-exec flag can't be set on fd + * if it refers to a script." + * + * Unfortunately, if we unset close-on-exec, the script will be executed just fine, but (at + * least in case of bash) the script name, $0, will be shown as /dev/fd/nnn, which breaks + * scripts which make use of $0. Thus, let's fall back to execve() in this case. + */ +#endif + execve(executable, argv, envp); + return -errno; +} |