From 18a847c22a04de22cc9c431e87b63a0cfd5f1286 Mon Sep 17 00:00:00 2001 From: "A. Wilcox" Date: Mon, 6 Jul 2020 08:02:28 -0500 Subject: unistd: Interpose execv* functions for LOADER Newer releases of Chromium directly execv /proc/self/exe, missing our readlink(3) interposing. We go ahead and interpose all three execv* functions just to ensure wider compatibility. --- CHANGELOG.rst | 7 ++++++- libgcompat/unistd.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index a4d7698..1330b68 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -8,9 +8,14 @@ © 2016-2019 Adélie Linux and contributors. NCSA open source licence. -1.0.0 (20??-??-??) +0.9.0 (2020-07-??) ================== +unistd +------ + +* Add execv/execve/execvp family of functions to catch exec of /proc/self/exe. + wchar ----- diff --git a/libgcompat/unistd.c b/libgcompat/unistd.c index d2f3097..d632eee 100644 --- a/libgcompat/unistd.c +++ b/libgcompat/unistd.c @@ -3,6 +3,10 @@ #include /* NGROUPS_MAX */ #include /* NULL, size_t */ #include /* confstr, getcwd, getgroups, ... */ +#include /* ENOSYS, ENOMEM */ +#include /* calloc */ +#include /* dlsym */ +#include /* strcmp */ #include "alias.h" /* alias */ @@ -179,3 +183,53 @@ int group_member(gid_t gid) return 0; } + +#ifndef LOADER +#error LOADER must be defined +#endif + +static int (*real_execve)(const char *pathname, char *const argv[], char *const envp[]); +int execve(const char *pathname, char *const argv[], char *const envp[]) { + if(real_execve == NULL) { + real_execve = dlsym(RTLD_NEXT, "execve"); + if(real_execve == NULL) { + errno = ENOSYS; + return -1; + } + } + + if(!strcmp(pathname, "/proc/self/exe")) { + char **new_argv; + char target[PATH_MAX] = ""; + int argc = 0, i = 0; + while(argv[i++] != 0) argc++; + + i = readlink("/proc/self/exe", target, sizeof(target)); + if(i < 0 || i == sizeof(target)) { + errno = ENOMEM; + return -1; + } + + new_argv = calloc(argc + 6, sizeof(char *)); + new_argv[0] = LOADER; + new_argv[1] = "--argv0"; + new_argv[2] = argv[0]; + new_argv[3] = "--preload"; + new_argv[4] = "/lib/libgcompat.so.0"; + new_argv[5] = target; + for(int j = 1, i = 6; j < argc; ++i, ++j) { + new_argv[i] = argv[j]; + } + return execve(LINKER, new_argv, envp); + } + return real_execve(pathname, argv, envp); +} + +extern char **environ; +int execv(const char *pathname, char *const argv[]) { + return execve(pathname, argv, environ); +} + +int execvp(const char *file, char *const argv[]) { + return execv(file, argv); +} -- cgit v1.2.3-70-g09d2