avoid assimilating

This commit is contained in:
Gavin Hayes 2024-01-19 02:49:26 -05:00
parent 2df75e902b
commit 64275e9cd7

View file

@ -21,6 +21,7 @@
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/cp.internal.h" #include "libc/calls/cp.internal.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/state.internal.h"
#include "libc/calls/struct/sigset.internal.h" #include "libc/calls/struct/sigset.internal.h"
#include "libc/calls/struct/stat.internal.h" #include "libc/calls/struct/stat.internal.h"
#include "libc/calls/syscall-sysv.internal.h" #include "libc/calls/syscall-sysv.internal.h"
@ -199,9 +200,9 @@ static int fd_to_mem_fd(const int infd, char *path) {
bool success = readRc != -1; bool success = readRc != -1;
if (success) { if (success) {
int ziperror; int ziperror;
if ((st.st_size > 8) && IsApeMagic(space)) { //if ((st.st_size > 8) && IsApeMagic(space)) {
success = ape_to_elf(space, st.st_size); // success = ape_to_elf(space, st.st_size);
} //}
// we need to preserve the fd over exec if there's zipos // we need to preserve the fd over exec if there's zipos
if (success && _weaken(GetZipEocd) && _weaken(GetZipEocd)(space, st.st_size, &ziperror)) { if (success && _weaken(GetZipEocd) && _weaken(GetZipEocd)(space, st.st_size, &ziperror)) {
int flags = fcntl(fd, F_GETFD); int flags = fcntl(fd, F_GETFD);
@ -232,6 +233,30 @@ static int fd_to_mem_fd(const int infd, char *path) {
return -1; return -1;
} }
static int isZipFd(const int fd) {
if (!_weaken(mmap) || !_weaken(munmap) || !_weaken(GetZipEocd)) {
return enosys();
}
if (__vforked) {
return 0;
}
struct stat st;
if (fstat(fd, &st) == -1) {
return -1;
}
void *space = _weaken(mmap)(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
if (space == MAP_FAILED) {
STRACE("map failed");
return -1;
}
int ziperror;
int rc = _weaken(GetZipEocd)(space, st.st_size, &ziperror) != NULL;
if(_weaken(munmap)(space, st.st_size) == -1) {
return -1;
}
return rc;
}
/** /**
* Executes binary executable at file descriptor. * Executes binary executable at file descriptor.
* *
@ -260,55 +285,81 @@ int fexecve(int fd, char *const argv[], char *const envp[]) {
rc = enosys(); rc = enosys();
break; break;
} }
if (!__isfdkind(fd, kFdZip)) { int newfd = fd;
bool memfdReq; if (__isfdkind(fd, kFdZip)) {
BLOCK_SIGNALS; BLOCK_SIGNALS;
BLOCK_CANCELATION; BLOCK_CANCELATION;
strace_enabled(-1); strace_enabled(-1);
memfdReq = ((rc = fcntl(fd, F_GETFD)) != -1) && (rc & FD_CLOEXEC) && newfd = fd_to_mem_fd(fd, NULL);
IsAPEFd(fd);
strace_enabled(+1); strace_enabled(+1);
ALLOW_CANCELATION; ALLOW_CANCELATION;
ALLOW_SIGNALS; ALLOW_SIGNALS;
if (rc == -1) { if (newfd == -1) {
break; break;
} else if (!memfdReq) {
fexecve_impl(fd, argv, envp);
if (errno != ENOEXEC) {
break;
}
savedErr = ENOEXEC;
} }
} }
int newfd; int isZipFdRc;
char *path = alloca(PATH_MAX);
BLOCK_SIGNALS; BLOCK_SIGNALS;
BLOCK_CANCELATION; BLOCK_CANCELATION;
strace_enabled(-1); //strace_enabled(-1);
newfd = fd_to_mem_fd(fd, path); isZipFdRc = isZipFd(newfd);
strace_enabled(+1); strace_enabled(+1);
ALLOW_CANCELATION; ALLOW_CANCELATION;
ALLOW_SIGNALS; ALLOW_SIGNALS;
if (newfd == -1) { if (isZipFdRc == -1) {
//savedErr = EACCES;
//STRACE("EACCESS 1");
//break;
isZipFdRc = 0;
}
bool isAPE;
BLOCK_SIGNALS;
BLOCK_CANCELATION;
isAPE = IsAPEFd(newfd);
ALLOW_CANCELATION;
ALLOW_SIGNALS;
if ((isZipFdRc == 1) || isAPE) {
int flags = fcntl(newfd, F_GETFD);
if ((flags == -1) || (fcntl(newfd, F_SETFD, flags & (~FD_CLOEXEC)) == -1)) {
savedErr = EACCES;
STRACE("EACCESS 2");
break;
}
const int highfd = fcntl(newfd, F_DUPFD, 9001);
if (highfd != -1) {
close(newfd);
newfd = highfd;
}
}
if (isZipFdRc == 1) {
char *path = alloca(PATH_MAX);
FormatInt32(stpcpy(path, "COSMOPOLITAN_INIT_ZIPOS="), newfd);
size_t numenvs;
for (numenvs = 0; envp[numenvs];) ++numenvs;
static _Thread_local char *envs[500];
memcpy(envs, envp, numenvs * sizeof(char *));
envs[numenvs] = path;
envs[numenvs + 1] = NULL;
envp = envs;
}
if (isAPE) {
char path[14 + 12];
FormatInt32(stpcpy(path, "/proc/self/fd/"), newfd);
rc = sys_execve(path, argv, envp);
savedErr = errno;
BLOCK_SIGNALS;
BLOCK_CANCELATION;
strace_enabled(-1);
if (newfd != fd) {
close(newfd);
}
strace_enabled(+1);
ALLOW_CANCELATION;
ALLOW_SIGNALS;
break; break;
} }
size_t numenvs; fexecve_impl(newfd, argv, envp);
for (numenvs = 0; envp[numenvs];) ++numenvs; savedErr = errno;
static _Thread_local char *envs[500];
memcpy(envs, envp, numenvs * sizeof(char *));
envs[numenvs] = path;
envs[numenvs + 1] = NULL;
fexecve_impl(newfd, argv, envs);
if (!savedErr) {
savedErr = errno;
}
BLOCK_SIGNALS;
BLOCK_CANCELATION;
strace_enabled(-1);
close(newfd);
strace_enabled(+1);
ALLOW_CANCELATION;
ALLOW_SIGNALS;
} while (0); } while (0);
if (savedErr) { if (savedErr) {
errno = savedErr; errno = savedErr;