diff options
author | dzwdz | 2022-08-26 23:50:53 +0200 |
---|---|---|
committer | dzwdz | 2022-08-27 10:18:11 +0200 |
commit | 48e612a8c19ae1fd6aa1ab8fb48b03a0291110b4 (patch) | |
tree | 8c8d3da6c38206503364693b545aa6228a8c1f5a /src/user | |
parent | 35cbc783713c814298987ee636d26cfccc5aca96 (diff) |
user/elfload: fix argv corruption when it's passed from the stack
Diffstat (limited to 'src/user')
-rw-r--r-- | src/user/app/testelf/main.c | 13 | ||||
-rw-r--r-- | src/user/lib/elfload.c | 35 |
2 files changed, 39 insertions, 9 deletions
diff --git a/src/user/app/testelf/main.c b/src/user/app/testelf/main.c index ee7465b..ea97b4a 100644 --- a/src/user/app/testelf/main.c +++ b/src/user/app/testelf/main.c @@ -1,4 +1,6 @@ #include <stdio.h> +#include <string.h> +#include <unistd.h> const char *str = "Hello!", *str2 = "World."; @@ -8,5 +10,16 @@ int main(int argc, char **argv) { printf("argc == %u\n", argc); for (int i = 0; i < argc; i++) printf("argv[%u] == 0x%x == \"%s\"\n", i, argv[i], argv[i]); + if (strcmp(argv[1], "stackexec") == 0) { + /* exec something with arguments on the stack */ + const char s_d[] = "I am a pretty long string on the stack. Oh my. " \ + "I hope I won't get corrupted.\0"; + char s[sizeof(s_d)]; + memcpy(s, s_d, sizeof(s_d)); + const char *argv2[] = {argv[0], s, s, "hello", s, s, s, "lol", NULL}; + printf("argv2 == 0x%x, s == 0x%x\n== exec ==\n", argv2, s); + execv(argv[0], (void*)argv2); + puts("stackexec failed"); + } return 0; } diff --git a/src/user/lib/elfload.c b/src/user/lib/elfload.c index 4fcc1db..6912239 100644 --- a/src/user/lib/elfload.c +++ b/src/user/lib/elfload.c @@ -65,16 +65,36 @@ static size_t elf_spread(const void *elf) { return high - low; } +static void *malloccpy(const void *orig, size_t len) { + void *n = malloc(len); + memcpy(n, orig, len); + return n; +} + /* frees memory outside of [low; low + len] and jumps to *entry * also sets up main's stack */ -void _freejmp_chstack(void *entry, void *low, size_t len, char **argv, char **envp, void *stack); // elfload.s +void _freejmp_chstack(void *entry, void *low, size_t len, const char **argv, char **envp, void *stack); // elfload.s _Noreturn void execbuf_chstack(void *stack, void __user *buf, size_t len); -void _freejmp(void *entry, void *low, size_t imglen, char **argv, char **envp) { +void _freejmp(void *entry, void *low, size_t imglen, const char **argv, char **envp) { size_t len; union {void *b; void **ptr; uintptr_t *n;} stack; stack.b = (void*)~0; /* default stack location */ + void *stack_start = stack.b - 0x1000; void *cwd; + /* copy argv off the stack */ + int argc = 0; + size_t argv_len; + if (argv) { + while (argv[argc]) argc++; + argv_len = argc * sizeof(char *); + if ((void*)argv > stack_start) + argv = malloccpy(argv, argv_len); + for (int i = 0; argv[i]; i++) + if ((void*)argv[i] > stack_start) + argv[i] = malloccpy(argv[i], strlen(argv[i]) + 1); + } + /* push cwd */ len = absolutepath(NULL, NULL, 0); stack.b -= len; @@ -82,19 +102,16 @@ void _freejmp(void *entry, void *low, size_t imglen, char **argv, char **envp) { getcwd(cwd, len); /* push argv */ - int argc = 0; if (argv) { - for (int i = 0; argv[i]; i++) { + for (int i = 0; i < argc; i++) { len = strlen(argv[i]) + 1; stack.b -= len; memcpy(stack.b, argv[i], len); argv[i] = stack.b; - argc++; } - len = sizeof(char*) * argc; *--(stack.ptr) = NULL; /* NULL terminate argv */ - stack.b -= len; - memcpy(stack.b, argv, len); + stack.b -= argv_len; + memcpy(stack.b, argv, argv_len); argv = stack.b; } @@ -147,7 +164,7 @@ void elf_exec(void *base, char **argv, char **envp) { void *newstack = _syscall_memflag((void*)0x1000, 0x1000, MEMFLAG_FINDFREE | MEMFLAG_PRESENT); if (!newstack) return; - _freejmp_chstack(exebase + ehdr->e_entry, exebase, elf_spread(ehdr) + 0x1000, argv, envp, newstack); + _freejmp_chstack(exebase + ehdr->e_entry, exebase, elf_spread(ehdr) + 0x1000, (const char**)argv, envp, newstack); } void *elf_partialexec(void *base) { |