mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-08-08 10:50:28 +00:00
sysv execve add zipos support. Add Linux zipos APE execve by leaking fd
This commit is contained in:
parent
a2b0542349
commit
385dca4ec0
2 changed files with 58 additions and 2 deletions
|
@ -25,14 +25,18 @@
|
|||
#include "libc/errno.h"
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/intrin/safemacros.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/mem/alloca.h"
|
||||
#include "libc/paths.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
#include "libc/sysv/consts/fd.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/ok.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
||||
static bool CanExecute(const char *path) {
|
||||
return !sys_faccessat(AT_FDCWD, path, X_OK, 0);
|
||||
|
@ -71,16 +75,42 @@ static const char *Join(const char *a, const char *b, char buf[PATH_MAX]) {
|
|||
|
||||
int sys_execve(const char *prog, char *const argv[], char *const envp[]) {
|
||||
size_t i;
|
||||
int e, rc;
|
||||
char *buf;
|
||||
int e, rc, fd, flags;
|
||||
char *buf, *newprog;
|
||||
char **shargs;
|
||||
const char *ape;
|
||||
struct ZiposUri uri;
|
||||
if (_weaken(__zipos_parseuri)(prog, &uri) != -1) {
|
||||
if (IsLinux()) {
|
||||
newprog = alloca(PATH_MAX);
|
||||
fd = _weaken(__zipos_uri_to_mem_file)(&uri, newprog);
|
||||
prog = newprog;
|
||||
} else if (IsFreebsd()) {
|
||||
if ((fd = _weaken(__zipos_uri_to_mem_file)(&uri, NULL)) != -1) {
|
||||
return sys_fexecve(fd, argv, envp);
|
||||
}
|
||||
} else {
|
||||
return enosys();
|
||||
}
|
||||
if (fd == -1) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
fd = -1;
|
||||
}
|
||||
e = errno;
|
||||
__sys_execve(prog, argv, envp);
|
||||
if (errno == ENOEXEC) {
|
||||
for (i = 0; argv[i];) ++i;
|
||||
buf = alloca(PATH_MAX);
|
||||
shargs = alloca((i + 4) * sizeof(char *));
|
||||
if (fd != -1) {
|
||||
flags = fcntl(fd, F_GETFD);
|
||||
if (flags != -1) {
|
||||
fcntl(fd, F_SETFD, flags & (~FD_CLOEXEC));
|
||||
flags = fcntl(fd, F_GETFD);
|
||||
}
|
||||
}
|
||||
if (IsApeBinary(prog) &&
|
||||
(CanExecute((ape = "/usr/bin/ape")) ||
|
||||
CanExecute((ape = Join(firstnonnull(getenv("TMPDIR"),
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
@ -58,3 +60,27 @@ TEST(execve, testArgPassing) {
|
|||
EXITS(0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(execve, ziposELF) {
|
||||
if (!IsLinux() && !IsFreebsd()) {
|
||||
EXPECT_SYS(ENOSYS, -1,
|
||||
execve("/zip/life.elf", (char *const[]){0}, (char *const[]){0}));
|
||||
return;
|
||||
}
|
||||
SPAWN(fork);
|
||||
execve("/zip/life.elf", (char *const[]){0}, (char *const[]){0});
|
||||
notpossible;
|
||||
EXITS(42);
|
||||
}
|
||||
|
||||
TEST(execve, ziposAPE) {
|
||||
if (!IsLinux()) {
|
||||
EXPECT_EQ(-1, execve("/zip/life-nomod.com", (char *const[]){0},
|
||||
(char *const[]){0}));
|
||||
return;
|
||||
}
|
||||
SPAWN(fork);
|
||||
execve("/zip/life-nomod.com", (char *const[]){0}, (char *const[]){0});
|
||||
notpossible;
|
||||
EXITS(42);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue