diff --git a/src/fn.c b/src/fn.c index 2f4cd18ae..51a374d55 100644 --- a/src/fn.c +++ b/src/fn.c @@ -242,6 +242,7 @@ initFn(void) GETADDR(g_fn.getaddrinfo, "getaddrinfo"); GETADDR(g_fn.sigaction, "sigaction"); GETADDR(g_fn.execve, "execve"); + GETADDR(g_fn.execv, "execv"); GETADDR(g_fn.poll, "poll"); GETADDR(g_fn.__poll_chk, "__poll_chk"); GETADDR(g_fn.select, "select"); diff --git a/src/fn.h b/src/fn.h index fec4d1efc..82a87b4dd 100644 --- a/src/fn.h +++ b/src/fn.h @@ -199,6 +199,7 @@ typedef struct { int (*PR_FileDesc2NativeHandle)(PRFileDesc *); void (*PR_SetError)(PRErrorCode, PRInt32); int (*execve)(const char *, char * const *, char * const *); + int (*execv)(const char *, char * const *); int (*poll)(struct pollfd *, nfds_t, int); int (*__poll_chk)(struct pollfd *, nfds_t, int, size_t); int (*select)(int, fd_set *, fd_set *, fd_set *, struct timeval *); diff --git a/src/wrap.c b/src/wrap.c index eccad4183..a9a20cbd8 100644 --- a/src/wrap.c +++ b/src/wrap.c @@ -151,6 +151,7 @@ static got_list_t inject_hook_list[] = { {"fstatat", NULL, &g_fn.fstatat}, {"prctl", NULL, &g_fn.prctl}, {"execve", NULL, &g_fn.execve}, + {"execv", NULL, &g_fn.execv}, {"syscall", NULL, &g_fn.syscall}, {"sendfile", NULL, &g_fn.sendfile}, {"sendfile64", NULL, &g_fn.sendfile64}, @@ -2630,20 +2631,16 @@ prctl(int option, ...) return g_fn.prctl(option, fArgs.arg[0], fArgs.arg[1], fArgs.arg[2], fArgs.arg[3]); } -EXPORTON int -execve(const char *pathname, char *const argv[], char *const envp[]) +static char* +getLdscopeExec(const char* pathname) { - int i, nargs, saverr; + char *scopexec = NULL; bool isstat = FALSE, isgo = FALSE; - char **nargv; elf_buf_t *ebuf; - char *scopexec = NULL; - - WRAP_CHECK(execve, -1); if (scope_strstr(g_proc.procname, "ldscope") || checkEnv("SCOPE_EXECVE", "false")) { - return g_fn.execve(pathname, argv, envp); + return NULL; } if ((ebuf = getElf((char *)pathname))) { @@ -2659,7 +2656,7 @@ execve(const char *pathname, char *const argv[], char *const envp[]) * In this case we use ldscope only to force the use of HTTP 1.1. */ if (getenv("LD_PRELOAD") && (isstat == FALSE) && (isgo == FALSE)) { - return g_fn.execve(pathname, argv, envp); + return NULL; } scopexec = getenv("SCOPE_EXEC_PATH"); @@ -2667,7 +2664,62 @@ execve(const char *pathname, char *const argv[], char *const envp[]) ((scopexec = getpath("ldscope")) == NULL)) { // can't find the scope executable - scopeLogWarn("execve: can't find a scope executable for %s", pathname); + scopeLogWarn("can't find a scope executable for %s", pathname); + return NULL; + } + + return scopexec; +} + +EXPORTON int +execv(const char *pathname, char *const argv[]) +{ + int i, nargs, saverr; + char *scopexec; + char **nargv; + + WRAP_CHECK(execv, -1); + + scopexec = getLdscopeExec(pathname); + if (scopexec == NULL) { + return g_fn.execv(pathname, argv); + } + + nargs = 0; + while ((argv[nargs] != NULL)) nargs++; + + size_t plen = sizeof(char *); + if ((nargs == 0) || (nargv = scope_calloc(1, ((nargs * plen) + (plen * 2)))) == NULL) { + return g_fn.execv(pathname, argv); + } + + nargv[0] = scopexec; + nargv[1] = (char *)pathname; + + for (i = 2; i <= nargs; i++) { + nargv[i] = argv[i - 1]; + } + + g_fn.execv(nargv[0], nargv); + saverr = errno; + if (nargv) scope_free(nargv); + scope_free(scopexec); + errno = saverr; + return -1; +} + + +EXPORTON int +execve(const char *pathname, char *const argv[], char *const envp[]) +{ + int i, nargs, saverr; + char *scopexec; + char **nargv; + + WRAP_CHECK(execve, -1); + + scopexec = getLdscopeExec(pathname); + if (scopexec == NULL) { return g_fn.execve(pathname, argv, envp); } @@ -2689,7 +2741,7 @@ execve(const char *pathname, char *const argv[], char *const envp[]) g_fn.execve(nargv[0], nargv, environ); saverr = errno; if (nargv) scope_free(nargv); - if (scopexec) scope_free(scopexec); + scope_free(scopexec); errno = saverr; return -1; }