From 998765a7a63f406131bdf49b800482e98fffe8b9 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sat, 1 Feb 2020 16:05:04 +0100 Subject: [PATCH] LibC: The exec() family of functions should not search "." by default We should only execute the filename verbatim if it contains a slash (/) character somewhere. Otherwise, we need to look through the entries in the PATH environment variable. This fixes an issue where you could easily "override" system programs by placing them in a directory you control, and then waiting for someone to come there and run e.g "ls" :^) Test: LibC/exec-should-not-search-current-directory.cpp --- Libraries/LibC/unistd.cpp | 9 +++------ ...ec-should-not-search-current-directory.cpp | 20 +++++++++++++++++++ 2 files changed, 23 insertions(+), 6 deletions(-) create mode 100644 Tests/LibC/exec-should-not-search-current-directory.cpp diff --git a/Libraries/LibC/unistd.cpp b/Libraries/LibC/unistd.cpp index fe07434a68..db2434c7f4 100644 --- a/Libraries/LibC/unistd.cpp +++ b/Libraries/LibC/unistd.cpp @@ -111,13 +111,10 @@ int execve(const char* filename, char* const argv[], char* const envp[]) int execvpe(const char* filename, char* const argv[], char* const envp[]) { + if (strchr(filename, '/')) + return execve(filename, argv, envp); + ScopedValueRollback errno_rollback(errno); - int rc = execve(filename, argv, envp); - if (rc < 0 && errno != ENOENT) { - errno_rollback.set_override_rollback_value(errno); - dbg() << "execvpe() failed on first with" << strerror(errno); - return rc; - } String path = getenv("PATH"); if (path.is_empty()) path = "/bin:/usr/bin"; diff --git a/Tests/LibC/exec-should-not-search-current-directory.cpp b/Tests/LibC/exec-should-not-search-current-directory.cpp new file mode 100644 index 0000000000..57a023a6df --- /dev/null +++ b/Tests/LibC/exec-should-not-search-current-directory.cpp @@ -0,0 +1,20 @@ +#include +#include +#include + +int main() +{ + int fd = open("hax", O_CREAT | O_RDWR, 0755); + ftruncate(fd, 0); + close(fd); + + int rc = execlp("hax", "hax", nullptr); + int saved_errno = errno; + unlink("hax"); + if (rc == -1 && saved_errno == ENOEXEC) { + printf("FAIL\n"); + return 1; + } + printf("PASS\n"); + return 0; +}