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>
|
||||
|
||||
#define pagesz 16384
|
||||
#define VARNAME "COSMOPOLITAN_PROGRAM_EXECUTABLE="
|
||||
#define VARSIZE (sizeof(VARNAME) - 1)
|
||||
/* maximum path size that cosmo can take */
|
||||
#define PATHSIZE (PATH_MAX < 1024 ? PATH_MAX : 1024)
|
||||
#define SYSLIB_MAGIC ('s' | 'l' << 8 | 'i' << 16 | 'b' << 24)
|
||||
|
@ -203,11 +201,8 @@ struct PathSearcher {
|
|||
unsigned long namelen;
|
||||
const char *name;
|
||||
const char *syspath;
|
||||
char varname[VARSIZE];
|
||||
char path[PATHSIZE];
|
||||
};
|
||||
_Static_assert(offsetof(struct PathSearcher, varname) + VARSIZE ==
|
||||
offsetof(struct PathSearcher, path), "struct layout");
|
||||
|
||||
struct ApeLoader {
|
||||
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,
|
||||
long *sp, struct ElfEhdr *e,
|
||||
struct ElfPhdr *p,
|
||||
struct Syslib *lib) {
|
||||
struct Syslib *lib,
|
||||
char *path) {
|
||||
long rc;
|
||||
int prot;
|
||||
int flags;
|
||||
|
@ -734,10 +730,10 @@ __attribute__((__noreturn__)) static void Spawn(const char *exe, int fd,
|
|||
close(fd);
|
||||
|
||||
register long *x0 __asm__("x0") = sp;
|
||||
register char *x2 __asm__("x2") = path;
|
||||
register struct Syslib *x15 __asm__("x15") = lib;
|
||||
register long x16 __asm__("x16") = e->e_entry;
|
||||
__asm__ volatile("mov\tx1,#0\n\t"
|
||||
"mov\tx2,#0\n\t"
|
||||
"mov\tx3,#0\n\t"
|
||||
"mov\tx4,#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"
|
||||
"br\tx16"
|
||||
: /* no outputs */
|
||||
: "r"(x0), "r"(x15), "r"(x16)
|
||||
: "r"(x0), "r"(x2), "r"(x15), "r"(x16)
|
||||
: "memory");
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
@ -891,7 +887,7 @@ static const char *TryElf(struct ApeLoader *M, union ElfEhdrBuf *ebuf,
|
|||
auxv[28] = 0;
|
||||
|
||||
/* 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) {
|
||||
|
@ -901,7 +897,7 @@ int main(int argc, char **argv, char **envp) {
|
|||
long *sp, *sp2, *auxv;
|
||||
union ElfEhdrBuf *ebuf;
|
||||
char *p, *pe, *exe, *prog,
|
||||
*execfn, *shell, **varpos;
|
||||
*execfn, *shell;
|
||||
|
||||
/* allocate loader memory in program's arg block */
|
||||
n = sizeof(struct ApeLoader);
|
||||
|
@ -965,13 +961,9 @@ int main(int argc, char **argv, char **envp) {
|
|||
|
||||
/* getenv("_") is close enough to at_execfn */
|
||||
execfn = argc > 0 ? argv[0] : 0;
|
||||
varpos = 0;
|
||||
for (i = 0; envp[i]; ++i) {
|
||||
if (envp[i][0] == '_' && envp[i][1] == '=') {
|
||||
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
|
||||
system v abi aligns this on a 16-byte boundary
|
||||
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);
|
||||
if ((long)sp2 & 15) ++sp2;
|
||||
for (; n > 0; n -= pagesz) {
|
||||
|
@ -991,12 +983,6 @@ int main(int argc, char **argv, char **envp) {
|
|||
memmove(sp2, sp, (auxv - sp) * sizeof(long));
|
||||
argv = (char **)(sp2 + 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);
|
||||
sp = sp2;
|
||||
|
||||
|
@ -1061,12 +1047,6 @@ int main(int argc, char **argv, char **envp) {
|
|||
}
|
||||
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 */
|
||||
if ((rc = sys_getentropy(M->rando, sizeof(M->rando))) < 0) {
|
||||
Pexit(argv[0], rc, "getentropy");
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/atomic.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/metalfile.internal.h"
|
||||
|
@ -51,6 +52,11 @@ static inline int IsAlpha(int c) {
|
|||
}
|
||||
|
||||
static inline void InitProgramExecutableNameImpl(void) {
|
||||
if (__myname) {
|
||||
return;
|
||||
}
|
||||
npassert(!issetugid()); // TODO(mrdomino): pathname security
|
||||
// https://github.com/jart/cosmopolitan/issues/991
|
||||
|
||||
if (IsWindows()) {
|
||||
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] = '/';
|
||||
}
|
||||
tprecode16to8(g_prog.u.buf, sizeof(g_prog.u.buf), g_prog.u.buf16);
|
||||
return;
|
||||
goto UseBuf;
|
||||
}
|
||||
|
||||
char c, *q;
|
||||
if (IsMetal()) {
|
||||
q = APE_COM_NAME;
|
||||
goto CopyString;
|
||||
__myname = APE_COM_NAME;
|
||||
return;
|
||||
}
|
||||
|
||||
/* the new-style loader supplies the full program path as the first
|
||||
environment variable. in the spirit of Postel's Law ("be liberal
|
||||
in what you accept"), we use __getenv to read it. */
|
||||
/* the previous loader supplied the full program path as the first
|
||||
environment variable. */
|
||||
if ((q = __getenv(__envp, "COSMOPOLITAN_PROGRAM_EXECUTABLE").s)) {
|
||||
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
|
||||
|
@ -107,10 +112,10 @@ static inline void InitProgramExecutableNameImpl(void) {
|
|||
}
|
||||
}
|
||||
*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 = 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
|
||||
|
@ -127,7 +132,7 @@ static inline void InitProgramExecutableNameImpl(void) {
|
|||
if ((got = sys_readlinkat(AT_FDCWD, "/proc/self/exe", b, n)) > 0 ||
|
||||
(got = sys_readlinkat(AT_FDCWD, "/proc/curproc/file", b, n)) > 0) {
|
||||
b[got] = 0;
|
||||
return;
|
||||
goto UseBuf;
|
||||
}
|
||||
if (IsFreebsd() || IsNetbsd()) {
|
||||
int cmd[4];
|
||||
|
@ -140,7 +145,7 @@ static inline void InitProgramExecutableNameImpl(void) {
|
|||
}
|
||||
cmd[3] = -1; // current process
|
||||
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;
|
||||
return;
|
||||
goto UseBuf;
|
||||
}
|
||||
|
||||
// if we don't even have that then empty the string
|
||||
g_prog.u.buf[0] = 0;
|
||||
|
||||
UseBuf:
|
||||
__myname = g_prog.u.buf;
|
||||
}
|
||||
|
||||
void __InitProgramExecutableName(void) {
|
||||
static void InitProgramExecutableName(void) {
|
||||
int e = errno;
|
||||
InitProgramExecutableNameImpl();
|
||||
errno = e;
|
||||
|
@ -172,6 +180,6 @@ void __InitProgramExecutableName(void) {
|
|||
* Returns absolute path of program.
|
||||
*/
|
||||
char *GetProgramExecutableName(void) {
|
||||
cosmo_once(&g_prog.once, __InitProgramExecutableName);
|
||||
return g_prog.u.buf;
|
||||
cosmo_once(&g_prog.once, InitProgramExecutableName);
|
||||
return __myname;
|
||||
}
|
||||
|
|
|
@ -140,6 +140,8 @@ _start:
|
|||
// should be set to zero on other platforms
|
||||
mov x1,x15
|
||||
|
||||
// third arg (x2) is the program path passed by ape-m1.c
|
||||
|
||||
// switch to c code
|
||||
bl cosmo
|
||||
.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;
|
||||
}
|
||||
|
||||
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
|
||||
// its used by --strace and also kprintf() %T
|
||||
|
@ -110,6 +110,7 @@ wontreturn textstartup void cosmo(long *sp, struct Syslib *m1) {
|
|||
environ = envp;
|
||||
program_invocation_name = argv[0];
|
||||
__oldstack = (intptr_t)sp;
|
||||
__myname = myname;
|
||||
|
||||
// detect apple m1 environment
|
||||
const char *magnums;
|
||||
|
|
|
@ -71,6 +71,7 @@ extern char **__argv;
|
|||
extern char **__envp;
|
||||
extern unsigned long *__auxv;
|
||||
extern intptr_t __oldstack;
|
||||
extern char *__myname;
|
||||
extern uint64_t __nosync;
|
||||
extern int __strace;
|
||||
extern int __ftrace;
|
||||
|
|
|
@ -108,9 +108,3 @@ TEST(GetProgramExecutableName, movedSelf) {
|
|||
abort();
|
||||
EXITS(0);
|
||||
}
|
||||
|
||||
void __InitProgramExecutableName(void);
|
||||
|
||||
BENCH(GetProgramExecutableName, bench) {
|
||||
EZBENCH2("Init", donothing, __InitProgramExecutableName());
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue