From 5310da93a5b7a6651e54f244363c4af88d3741a0 Mon Sep 17 00:00:00 2001 From: Duncan Overbruck Date: Thu, 12 Nov 2020 17:48:28 +0100 Subject: [PATCH] add back execvpe fallback --- configure | 4 +- libopenbsd/execvpe.c | 160 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 libopenbsd/execvpe.c diff --git a/configure b/configure index 632c74a..94ded41 100755 --- a/configure +++ b/configure @@ -360,7 +360,9 @@ int main(void) { execvpe("", p, p); return 0; }' -check_func "execvpe" "$src" || die "system has no execvpe(3): not supported" +check_func "execvpe" "$src" || { + printf 'SRCS += libopenbsd/execvpe.c\n' >>$CONFIG_MK +} # # Check for setresuid(). diff --git a/libopenbsd/execvpe.c b/libopenbsd/execvpe.c new file mode 100644 index 0000000..223daf4 --- /dev/null +++ b/libopenbsd/execvpe.c @@ -0,0 +1,160 @@ +/* $OpenBSD: exec.c,v 1.23 2016/03/13 18:34:20 guenther Exp $ */ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "config.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "openbsd.h" + +int +execvpe(const char *name, char *const *argv, char *const *envp) +{ + char **memp; + int cnt; + size_t lp, ln, len; + char *p; + int eacces = 0; + char *bp, *cur, *path, buf[PATH_MAX]; + + /* + * Do not allow null name + */ + if (name == NULL || *name == '\0') { + errno = ENOENT; + return (-1); + } + + /* If it's an absolute or relative path name, it's easy. */ + if (strchr(name, '/')) { + bp = (char *)name; + cur = path = NULL; + goto retry; + } + bp = buf; + + /* Get the path we're searching. */ + if (!(path = getenv("PATH"))) + path = _PATH_DEFPATH; + len = strlen(path) + 1; + cur = alloca(len); + if (cur == NULL) { + errno = ENOMEM; + return (-1); + } + strlcpy(cur, path, len); + path = cur; + while ((p = strsep(&cur, ":"))) { + /* + * It's a SHELL path -- double, leading and trailing colons + * mean the current directory. + */ + if (!*p) { + p = "."; + lp = 1; + } else + lp = strlen(p); + ln = strlen(name); + + /* + * If the path is too long complain. This is a possible + * security issue; given a way to make the path too long + * the user may execute the wrong program. + */ + if (lp + ln + 2 > sizeof(buf)) { + struct iovec iov[3]; + + iov[0].iov_base = "execvp: "; + iov[0].iov_len = 8; + iov[1].iov_base = p; + iov[1].iov_len = lp; + iov[2].iov_base = ": path too long\n"; + iov[2].iov_len = 16; + (void)writev(STDERR_FILENO, iov, 3); + continue; + } + bcopy(p, buf, lp); + buf[lp] = '/'; + bcopy(name, buf + lp + 1, ln); + buf[lp + ln + 1] = '\0'; + +retry: (void)execve(bp, argv, envp); + switch(errno) { + case E2BIG: + goto done; + case EISDIR: + case ELOOP: + case ENAMETOOLONG: + case ENOENT: + break; + case ENOEXEC: + for (cnt = 0; argv[cnt]; ++cnt) + ; + memp = alloca((cnt + 2) * sizeof(char *)); + if (memp == NULL) + goto done; + memp[0] = "sh"; + memp[1] = bp; + bcopy(argv + 1, memp + 2, cnt * sizeof(char *)); + (void)execve(_PATH_BSHELL, memp, envp); + goto done; + case ENOMEM: + goto done; + case ENOTDIR: + break; + case ETXTBSY: + /* + * We used to retry here, but sh(1) doesn't. + */ + goto done; + case EACCES: + eacces = 1; + break; + default: + goto done; + } + } + if (eacces) + errno = EACCES; + else if (!errno) + errno = ENOENT; +done: + return (-1); +} -- 2.39.2