mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-08-07 10:20:29 +00:00
New new style program path passing
The M1 loader now passes the program executable name directly as x2, which is the third argument to `cosmo()`. From there it is assigned to `__myname`. `GetProgramExecutableName` now always returns `__myname`, and it is `InitProgramExecutableName`’s job to set that variable if it is not already assigned. `InitProgramExecutableName` now dies if `issetugid()` and `__myname` is null, pending a rework of the path-finding logic.
This commit is contained in:
parent
8dbfb77890
commit
daf2156b5a
7 changed files with 56 additions and 49 deletions
34
ape/ape-m1.c
34
ape/ape-m1.c
|
@ -36,8 +36,6 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#define pagesz 16384
|
#define pagesz 16384
|
||||||
#define VARNAME "COSMOPOLITAN_PROGRAM_EXECUTABLE="
|
|
||||||
#define VARSIZE (sizeof(VARNAME) - 1)
|
|
||||||
/* maximum path size that cosmo can take */
|
/* maximum path size that cosmo can take */
|
||||||
#define PATHSIZE (PATH_MAX < 1024 ? PATH_MAX : 1024)
|
#define PATHSIZE (PATH_MAX < 1024 ? PATH_MAX : 1024)
|
||||||
#define SYSLIB_MAGIC ('s' | 'l' << 8 | 'i' << 16 | 'b' << 24)
|
#define SYSLIB_MAGIC ('s' | 'l' << 8 | 'i' << 16 | 'b' << 24)
|
||||||
|
@ -203,11 +201,8 @@ struct PathSearcher {
|
||||||
unsigned long namelen;
|
unsigned long namelen;
|
||||||
const char *name;
|
const char *name;
|
||||||
const char *syspath;
|
const char *syspath;
|
||||||
char varname[VARSIZE];
|
|
||||||
char path[PATHSIZE];
|
char path[PATHSIZE];
|
||||||
};
|
};
|
||||||
_Static_assert(offsetof(struct PathSearcher, varname) + VARSIZE ==
|
|
||||||
offsetof(struct PathSearcher, path), "struct layout");
|
|
||||||
|
|
||||||
struct ApeLoader {
|
struct ApeLoader {
|
||||||
struct PathSearcher ps;
|
struct PathSearcher ps;
|
||||||
|
@ -563,7 +558,8 @@ static long sys_pselect(int nfds, fd_set *readfds, fd_set *writefds,
|
||||||
__attribute__((__noreturn__)) static void Spawn(const char *exe, int fd,
|
__attribute__((__noreturn__)) static void Spawn(const char *exe, int fd,
|
||||||
long *sp, struct ElfEhdr *e,
|
long *sp, struct ElfEhdr *e,
|
||||||
struct ElfPhdr *p,
|
struct ElfPhdr *p,
|
||||||
struct Syslib *lib) {
|
struct Syslib *lib,
|
||||||
|
char *path) {
|
||||||
long rc;
|
long rc;
|
||||||
int prot;
|
int prot;
|
||||||
int flags;
|
int flags;
|
||||||
|
@ -734,10 +730,10 @@ __attribute__((__noreturn__)) static void Spawn(const char *exe, int fd,
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
register long *x0 __asm__("x0") = sp;
|
register long *x0 __asm__("x0") = sp;
|
||||||
|
register char *x2 __asm__("x2") = path;
|
||||||
register struct Syslib *x15 __asm__("x15") = lib;
|
register struct Syslib *x15 __asm__("x15") = lib;
|
||||||
register long x16 __asm__("x16") = e->e_entry;
|
register long x16 __asm__("x16") = e->e_entry;
|
||||||
__asm__ volatile("mov\tx1,#0\n\t"
|
__asm__ volatile("mov\tx1,#0\n\t"
|
||||||
"mov\tx2,#0\n\t"
|
|
||||||
"mov\tx3,#0\n\t"
|
"mov\tx3,#0\n\t"
|
||||||
"mov\tx4,#0\n\t"
|
"mov\tx4,#0\n\t"
|
||||||
"mov\tx5,#0\n\t"
|
"mov\tx5,#0\n\t"
|
||||||
|
@ -767,7 +763,7 @@ __attribute__((__noreturn__)) static void Spawn(const char *exe, int fd,
|
||||||
"mov\tx0,#0\n\t"
|
"mov\tx0,#0\n\t"
|
||||||
"br\tx16"
|
"br\tx16"
|
||||||
: /* no outputs */
|
: /* no outputs */
|
||||||
: "r"(x0), "r"(x15), "r"(x16)
|
: "r"(x0), "r"(x2), "r"(x15), "r"(x16)
|
||||||
: "memory");
|
: "memory");
|
||||||
__builtin_unreachable();
|
__builtin_unreachable();
|
||||||
}
|
}
|
||||||
|
@ -891,7 +887,7 @@ static const char *TryElf(struct ApeLoader *M, union ElfEhdrBuf *ebuf,
|
||||||
auxv[28] = 0;
|
auxv[28] = 0;
|
||||||
|
|
||||||
/* we're now ready to load */
|
/* we're now ready to load */
|
||||||
Spawn(exe, fd, sp, e, p, &M->lib);
|
Spawn(exe, fd, sp, e, p, &M->lib, M->ps.path);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv, char **envp) {
|
int main(int argc, char **argv, char **envp) {
|
||||||
|
@ -901,7 +897,7 @@ int main(int argc, char **argv, char **envp) {
|
||||||
long *sp, *sp2, *auxv;
|
long *sp, *sp2, *auxv;
|
||||||
union ElfEhdrBuf *ebuf;
|
union ElfEhdrBuf *ebuf;
|
||||||
char *p, *pe, *exe, *prog,
|
char *p, *pe, *exe, *prog,
|
||||||
*execfn, *shell, **varpos;
|
*execfn, *shell;
|
||||||
|
|
||||||
/* allocate loader memory in program's arg block */
|
/* allocate loader memory in program's arg block */
|
||||||
n = sizeof(struct ApeLoader);
|
n = sizeof(struct ApeLoader);
|
||||||
|
@ -965,13 +961,9 @@ int main(int argc, char **argv, char **envp) {
|
||||||
|
|
||||||
/* getenv("_") is close enough to at_execfn */
|
/* getenv("_") is close enough to at_execfn */
|
||||||
execfn = argc > 0 ? argv[0] : 0;
|
execfn = argc > 0 ? argv[0] : 0;
|
||||||
varpos = 0;
|
|
||||||
for (i = 0; envp[i]; ++i) {
|
for (i = 0; envp[i]; ++i) {
|
||||||
if (envp[i][0] == '_' && envp[i][1] == '=') {
|
if (envp[i][0] == '_' && envp[i][1] == '=') {
|
||||||
execfn = envp[i] + 2;
|
execfn = envp[i] + 2;
|
||||||
} else if (!memcmp(VARNAME, envp[i], VARSIZE)) {
|
|
||||||
assert(!varpos);
|
|
||||||
varpos = envp + i;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -982,7 +974,7 @@ int main(int argc, char **argv, char **envp) {
|
||||||
/* create new bottom of stack for spawned program
|
/* create new bottom of stack for spawned program
|
||||||
system v abi aligns this on a 16-byte boundary
|
system v abi aligns this on a 16-byte boundary
|
||||||
grows down the alloc by poking the guard pages */
|
grows down the alloc by poking the guard pages */
|
||||||
n = (auxv - sp + !varpos + AUXV_WORDS + 1) * sizeof(long);
|
n = (auxv - sp + AUXV_WORDS + 1) * sizeof(long);
|
||||||
sp2 = (long *)__builtin_alloca(n);
|
sp2 = (long *)__builtin_alloca(n);
|
||||||
if ((long)sp2 & 15) ++sp2;
|
if ((long)sp2 & 15) ++sp2;
|
||||||
for (; n > 0; n -= pagesz) {
|
for (; n > 0; n -= pagesz) {
|
||||||
|
@ -991,12 +983,6 @@ int main(int argc, char **argv, char **envp) {
|
||||||
memmove(sp2, sp, (auxv - sp) * sizeof(long));
|
memmove(sp2, sp, (auxv - sp) * sizeof(long));
|
||||||
argv = (char **)(sp2 + 1);
|
argv = (char **)(sp2 + 1);
|
||||||
envp = (char **)(sp2 + 1 + argc + 1);
|
envp = (char **)(sp2 + 1 + argc + 1);
|
||||||
if (varpos) {
|
|
||||||
varpos = (char **)((long *)varpos - sp + sp2);
|
|
||||||
} else {
|
|
||||||
varpos = envp + i++;
|
|
||||||
*(envp + i) = 0;
|
|
||||||
}
|
|
||||||
auxv = (long *)(envp + i + 1);
|
auxv = (long *)(envp + i + 1);
|
||||||
sp = sp2;
|
sp = sp2;
|
||||||
|
|
||||||
|
@ -1061,12 +1047,6 @@ int main(int argc, char **argv, char **envp) {
|
||||||
}
|
}
|
||||||
pe = ebuf->buf + rc;
|
pe = ebuf->buf + rc;
|
||||||
|
|
||||||
/* inject program executable as first environment variable,
|
|
||||||
swapping the old first variable for it. */
|
|
||||||
memmove(M->ps.varname, VARNAME, VARSIZE);
|
|
||||||
*varpos = *envp;
|
|
||||||
*envp = M->ps.varname;
|
|
||||||
|
|
||||||
/* generate some hard random data */
|
/* generate some hard random data */
|
||||||
if ((rc = sys_getentropy(M->rando, sizeof(M->rando))) < 0) {
|
if ((rc = sys_getentropy(M->rando, sizeof(M->rando))) < 0) {
|
||||||
Pexit(argv[0], rc, "getentropy");
|
Pexit(argv[0], rc, "getentropy");
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/assert.h"
|
||||||
#include "libc/atomic.h"
|
#include "libc/atomic.h"
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/calls/metalfile.internal.h"
|
#include "libc/calls/metalfile.internal.h"
|
||||||
|
@ -51,6 +52,11 @@ static inline int IsAlpha(int c) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void InitProgramExecutableNameImpl(void) {
|
static inline void InitProgramExecutableNameImpl(void) {
|
||||||
|
if (__myname) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
npassert(!issetugid()); // TODO(mrdomino): pathname security
|
||||||
|
// https://github.com/jart/cosmopolitan/issues/991
|
||||||
|
|
||||||
if (IsWindows()) {
|
if (IsWindows()) {
|
||||||
int n = GetModuleFileName(0, g_prog.u.buf16, ARRAYLEN(g_prog.u.buf16));
|
int n = GetModuleFileName(0, g_prog.u.buf16, ARRAYLEN(g_prog.u.buf16));
|
||||||
|
@ -69,21 +75,20 @@ static inline void InitProgramExecutableNameImpl(void) {
|
||||||
g_prog.u.buf16[2] = '/';
|
g_prog.u.buf16[2] = '/';
|
||||||
}
|
}
|
||||||
tprecode16to8(g_prog.u.buf, sizeof(g_prog.u.buf), g_prog.u.buf16);
|
tprecode16to8(g_prog.u.buf, sizeof(g_prog.u.buf), g_prog.u.buf16);
|
||||||
return;
|
goto UseBuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
char c, *q;
|
char c, *q;
|
||||||
if (IsMetal()) {
|
if (IsMetal()) {
|
||||||
q = APE_COM_NAME;
|
__myname = APE_COM_NAME;
|
||||||
goto CopyString;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* the new-style loader supplies the full program path as the first
|
/* the previous loader supplied the full program path as the first
|
||||||
environment variable. in the spirit of Postel's Law ("be liberal
|
environment variable. */
|
||||||
in what you accept"), we use __getenv to read it. */
|
|
||||||
if ((q = __getenv(__envp, "COSMOPOLITAN_PROGRAM_EXECUTABLE").s)) {
|
if ((q = __getenv(__envp, "COSMOPOLITAN_PROGRAM_EXECUTABLE").s)) {
|
||||||
strlcpy(g_prog.u.buf, q, sizeof(g_prog.u.buf));
|
strlcpy(g_prog.u.buf, q, sizeof(g_prog.u.buf));
|
||||||
return;
|
goto UseBuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if argv[0] exists then turn it into an absolute path. we also try
|
// if argv[0] exists then turn it into an absolute path. we also try
|
||||||
|
@ -107,10 +112,10 @@ static inline void InitProgramExecutableNameImpl(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*p = 0;
|
*p = 0;
|
||||||
if (!sys_faccessat(AT_FDCWD, g_prog.u.buf, F_OK, 0)) return;
|
if (!sys_faccessat(AT_FDCWD, g_prog.u.buf, F_OK, 0)) goto UseBuf;
|
||||||
p = WRITE32LE(p, READ32LE(".com"));
|
p = WRITE32LE(p, READ32LE(".com"));
|
||||||
*p = 0;
|
*p = 0;
|
||||||
if (!sys_faccessat(AT_FDCWD, g_prog.u.buf, F_OK, 0)) return;
|
if (!sys_faccessat(AT_FDCWD, g_prog.u.buf, F_OK, 0)) goto UseBuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if getenv("_") exists then use that
|
// if getenv("_") exists then use that
|
||||||
|
@ -127,7 +132,7 @@ static inline void InitProgramExecutableNameImpl(void) {
|
||||||
if ((got = sys_readlinkat(AT_FDCWD, "/proc/self/exe", b, n)) > 0 ||
|
if ((got = sys_readlinkat(AT_FDCWD, "/proc/self/exe", b, n)) > 0 ||
|
||||||
(got = sys_readlinkat(AT_FDCWD, "/proc/curproc/file", b, n)) > 0) {
|
(got = sys_readlinkat(AT_FDCWD, "/proc/curproc/file", b, n)) > 0) {
|
||||||
b[got] = 0;
|
b[got] = 0;
|
||||||
return;
|
goto UseBuf;
|
||||||
}
|
}
|
||||||
if (IsFreebsd() || IsNetbsd()) {
|
if (IsFreebsd() || IsNetbsd()) {
|
||||||
int cmd[4];
|
int cmd[4];
|
||||||
|
@ -140,7 +145,7 @@ static inline void InitProgramExecutableNameImpl(void) {
|
||||||
}
|
}
|
||||||
cmd[3] = -1; // current process
|
cmd[3] = -1; // current process
|
||||||
if (sys_sysctl(cmd, ARRAYLEN(cmd), b, &n, 0, 0) != -1) {
|
if (sys_sysctl(cmd, ARRAYLEN(cmd), b, &n, 0, 0) != -1) {
|
||||||
return;
|
goto UseBuf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,14 +160,17 @@ static inline void InitProgramExecutableNameImpl(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*p = 0;
|
*p = 0;
|
||||||
return;
|
goto UseBuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we don't even have that then empty the string
|
// if we don't even have that then empty the string
|
||||||
g_prog.u.buf[0] = 0;
|
g_prog.u.buf[0] = 0;
|
||||||
|
|
||||||
|
UseBuf:
|
||||||
|
__myname = g_prog.u.buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
void __InitProgramExecutableName(void) {
|
static void InitProgramExecutableName(void) {
|
||||||
int e = errno;
|
int e = errno;
|
||||||
InitProgramExecutableNameImpl();
|
InitProgramExecutableNameImpl();
|
||||||
errno = e;
|
errno = e;
|
||||||
|
@ -172,6 +180,6 @@ void __InitProgramExecutableName(void) {
|
||||||
* Returns absolute path of program.
|
* Returns absolute path of program.
|
||||||
*/
|
*/
|
||||||
char *GetProgramExecutableName(void) {
|
char *GetProgramExecutableName(void) {
|
||||||
cosmo_once(&g_prog.once, __InitProgramExecutableName);
|
cosmo_once(&g_prog.once, InitProgramExecutableName);
|
||||||
return g_prog.u.buf;
|
return __myname;
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,6 +140,8 @@ _start:
|
||||||
// should be set to zero on other platforms
|
// should be set to zero on other platforms
|
||||||
mov x1,x15
|
mov x1,x15
|
||||||
|
|
||||||
|
// third arg (x2) is the program path passed by ape-m1.c
|
||||||
|
|
||||||
// switch to c code
|
// switch to c code
|
||||||
bl cosmo
|
bl cosmo
|
||||||
.unreachable
|
.unreachable
|
||||||
|
|
21
libc/nexgen32e/myname2.c
Normal file
21
libc/nexgen32e/myname2.c
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
|
│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/runtime/runtime.h"
|
||||||
|
|
||||||
|
char *__myname;
|
|
@ -78,7 +78,7 @@ static const char *DecodeMagnum(const char *p, long *r) {
|
||||||
return *r = x, p;
|
return *r = x, p;
|
||||||
}
|
}
|
||||||
|
|
||||||
wontreturn textstartup void cosmo(long *sp, struct Syslib *m1) {
|
wontreturn textstartup void cosmo(long *sp, struct Syslib *m1, char *myname) {
|
||||||
|
|
||||||
// get startup timestamp as early as possible
|
// get startup timestamp as early as possible
|
||||||
// its used by --strace and also kprintf() %T
|
// its used by --strace and also kprintf() %T
|
||||||
|
@ -110,6 +110,7 @@ wontreturn textstartup void cosmo(long *sp, struct Syslib *m1) {
|
||||||
environ = envp;
|
environ = envp;
|
||||||
program_invocation_name = argv[0];
|
program_invocation_name = argv[0];
|
||||||
__oldstack = (intptr_t)sp;
|
__oldstack = (intptr_t)sp;
|
||||||
|
__myname = myname;
|
||||||
|
|
||||||
// detect apple m1 environment
|
// detect apple m1 environment
|
||||||
const char *magnums;
|
const char *magnums;
|
||||||
|
|
|
@ -71,6 +71,7 @@ extern char **__argv;
|
||||||
extern char **__envp;
|
extern char **__envp;
|
||||||
extern unsigned long *__auxv;
|
extern unsigned long *__auxv;
|
||||||
extern intptr_t __oldstack;
|
extern intptr_t __oldstack;
|
||||||
|
extern char *__myname;
|
||||||
extern uint64_t __nosync;
|
extern uint64_t __nosync;
|
||||||
extern int __strace;
|
extern int __strace;
|
||||||
extern int __ftrace;
|
extern int __ftrace;
|
||||||
|
|
|
@ -108,9 +108,3 @@ TEST(GetProgramExecutableName, movedSelf) {
|
||||||
abort();
|
abort();
|
||||||
EXITS(0);
|
EXITS(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __InitProgramExecutableName(void);
|
|
||||||
|
|
||||||
BENCH(GetProgramExecutableName, bench) {
|
|
||||||
EZBENCH2("Init", donothing, __InitProgramExecutableName());
|
|
||||||
}
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue