summaryrefslogtreecommitdiff
path: root/src/shared/exec-util.c
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2020-09-23 16:23:30 +0200
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2020-11-06 15:20:34 +0100
commit8939eeae528ef9b9ad2a21995279b76d382d5c81 (patch)
treebb18c4c23b36911c87d09c1c69c80ada5c707104 /src/shared/exec-util.c
parenta6d9111c67264a8828a563ccc23a24144b879942 (diff)
downloadsystemd-8939eeae528ef9b9ad2a21995279b76d382d5c81.tar.gz
shared/exec-util: use our own execveat() wrapper instead of fexecve()
For scripts, when we call fexecve(), on new kernels glibc calls execveat(), which fails with ENOENT, and then we fall back to execve() which succeeds: [pid 63039] execveat(3, "", ["/home/zbyszek/src/systemd/test/test-path-util/script.sh", "--version"], 0x7ffefa3633f0 /* 0 vars */, AT_EMPTY_PATH) = -1 ENOENT (No such file or directory) [pid 63039] execve("/home/zbyszek/src/systemd/test/test-path-util/script.sh", ["/home/zbyszek/src/systemd/test/test-path-util/script.sh", "--version"], 0x7ffefa3633f0 /* 0 vars */) = 0 But on older kernels glibc (some versions?) implement a fallback which falls into the same trap with bash $0: [pid 13534] execve("/proc/self/fd/3", ["/home/test/systemd/test/test-path-util/script.sh", "--version"], 0x7fff84995870 /* 0 vars */) = 0 We don't want that, so let's call execveat() ourselves. Then we can do the execve() fallback as we want.
Diffstat (limited to 'src/shared/exec-util.c')
-rw-r--r--src/shared/exec-util.c7
1 files changed, 4 insertions, 3 deletions
diff --git a/src/shared/exec-util.c b/src/shared/exec-util.c
index a0bb1567ce..d4ebeea301 100644
--- a/src/shared/exec-util.c
+++ b/src/shared/exec-util.c
@@ -16,6 +16,7 @@
#include "fileio.h"
#include "hashmap.h"
#include "macro.h"
+#include "missing_syscall.h"
#include "process-util.h"
#include "rlimit-util.h"
#include "serialize.h"
@@ -445,9 +446,9 @@ ExecCommandFlags exec_command_flags_from_string(const char *s) {
}
int fexecve_or_execve(int executable_fd, const char *executable, char *const argv[], char *const envp[]) {
- fexecve(executable_fd, argv, envp);
- if (errno == ENOENT)
- /* A script? Let's fall back to execve().
+ execveat(executable_fd, "", argv, envp, AT_EMPTY_PATH);
+ if (IN_SET(errno, ENOSYS, ENOENT))
+ /* Old kernel or a script? 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