Skip to content

Commit

Permalink
Docs, safer -l flag injection
Browse files Browse the repository at this point in the history
  • Loading branch information
mrdomino committed Dec 3, 2023
1 parent badaf03 commit 37a6f4a
Showing 1 changed file with 22 additions and 16 deletions.
38 changes: 22 additions & 16 deletions ape/ape-m1.c
Original file line number Diff line number Diff line change
Expand Up @@ -882,10 +882,10 @@ static const char *TryElf(struct ApeLoader *M, union ElfEhdrBuf *ebuf,

int main(int argc, char **argv, char **envp) {
unsigned i;
int c, n, fd, rc;
struct ApeLoader *M;
long *sp, *sp2, *auxv;
union ElfEhdrBuf *ebuf;
int c, islogin, n, fd, rc;
char *p, *pe, *exe, *prog, *shell, *execfn;

/* allocate loader memory in program's arg block */
Expand Down Expand Up @@ -960,18 +960,25 @@ int main(int argc, char **argv, char **envp) {
sp = (long *)(argv - 1);
auxv = (long *)(envp + i + 1);

/* there is a common convention of shells being told that they
are login shells via the OS prepending a - to their argv[0].
the APE system doesn't like it when argv[0] is not the full
path of the binary. to rectify this, the loader puts a "-l"
flag in argv[1] and ignores the dash. */
islogin = argc > 0 && *argv[0] == '-' && (shell = GetEnv(envp, "SHELL")) &&
!StrCmp(argv[0] + 1, BaseName(shell));

/* 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 */

c = argc > 0 && *argv[0] == '-';
n = (auxv - sp + c + AUXV_WORDS + 1) * sizeof(long);
n = (auxv - sp + islogin + AUXV_WORDS + 1) * sizeof(long);
sp2 = (long *)__builtin_alloca(n);
if ((long)sp2 & 15) ++sp2;
for (; n > 0; n -= pagesz) {
((char *)sp2)[n - 1] = 0;
}
if (c) {
if (islogin) {
memmove(sp2, sp, 2 * sizeof(long));
memmove(M->dash_l, "-l", 3);
*((char **)sp2 + 2) = M->dash_l;
Expand All @@ -991,14 +998,19 @@ int main(int argc, char **argv, char **envp) {
if ((M->ps.indirect = argc > 0 ? GetIndirectOffset(argv[0]) : 0)) {
M->ps.literally = 0;
/* if argv[0] is $prog.ape, then we strip off the .ape and run
$prog. */
$prog. This allows you to use symlinks to trick the OS when
a native executable is required. For example, let's say you
want to use the APE binary /opt/cosmos/bin/bash as a system
shell in /etc/shells, or perhaps in shebang lines like e.g.
`#!/opt/cosmos/bin/bash`. That won't work with APE normally,
but it will if you say:
ln -sf /usr/local/bin/ape /opt/cosmos/bin/bash.ape
and then use #!/opt/cosmos/bin/bash.ape instead. */
prog = (char *)sp[1];
argc = sp[0];
argv = (char **)(sp + 1);
/* when we are started as a login shell, a '-' is prepended to
our name. TODO: indicate this to the loaded process somehow. */
if (*prog == '-' && ((shell = GetEnv(envp, "SHELL")) &&
!StrCmp(BaseName(shell), prog + 1))) {
if (islogin) {
++argv[0];
prog = shell;
}
} else if ((M->ps.literally = argc >= 3 && !StrCmp(argv[1], "-"))) {
Expand Down Expand Up @@ -1042,15 +1054,9 @@ int main(int argc, char **argv, char **envp) {
}
pe = ebuf->buf + rc;

if (M->ps.indirect) {
prog = M->ps.path;
argv[0][M->ps.indirect] = 0;
if (*argv[0] == '-' && *BaseName(exe) != '-') ++argv[0]; /* XXX */
}

/* resolve argv[0] to reflect path search */
if (argc > 0 && ((*prog != '/' && *exe == '/' && !StrCmp(prog, argv[0])) ||
!StrCmp(BaseName(prog), argv[0]))) {
M->ps.indirect || !StrCmp(BaseName(prog), argv[0]))) {
argv[0] = exe;
}

Expand Down

0 comments on commit 37a6f4a

Please sign in to comment.