From 753d43d349bfde6b83cff650c9354c4a0442a3ae Mon Sep 17 00:00:00 2001 From: dzwdz Date: Tue, 18 Oct 2022 18:41:22 +0200 Subject: user/libc: rework exec(), use a C _start2 --- src/user/lib/_start.s | 11 ++++++++ src/user/lib/_start2.c | 13 +++++++++ src/user/lib/crt0.s | 21 --------------- src/user/lib/elfload.c | 73 ++++++++++++++++++++++---------------------------- src/user/lib/elfload.h | 6 +++++ 5 files changed, 62 insertions(+), 62 deletions(-) create mode 100644 src/user/lib/_start.s create mode 100644 src/user/lib/_start2.c delete mode 100644 src/user/lib/crt0.s diff --git a/src/user/lib/_start.s b/src/user/lib/_start.s new file mode 100644 index 0000000..0d5b5de --- /dev/null +++ b/src/user/lib/_start.s @@ -0,0 +1,11 @@ +.section .text +.global _start +.type _start, @function +.weak _start +_start: + mov %rsp, %rdi + and $~0xF, %rsp + call _start2 + hlt + /* the call shouldn't return, thus the hlt. + * using a call instead of jmp for stack alignment */ diff --git a/src/user/lib/_start2.c b/src/user/lib/_start2.c new file mode 100644 index 0000000..6d1431f --- /dev/null +++ b/src/user/lib/_start2.c @@ -0,0 +1,13 @@ +#include +#include +#include +#include +#include + +int main(int argc, char **argv, char **envp); + +_Noreturn void _start2(struct execdata *ed) { + elf_selfreloc(); + __setinitialcwd(ed->cwd); + exit(main(ed->argc, ed->argv, ed->envp)); +} diff --git a/src/user/lib/crt0.s b/src/user/lib/crt0.s deleted file mode 100644 index 3548264..0000000 --- a/src/user/lib/crt0.s +++ /dev/null @@ -1,21 +0,0 @@ -.section .text -.global _start -.type _start, @function -.weak _start -_start: - mov %rsp, %rbp - and $~0xF, %rsp - call elf_selfreloc - - mov %rbp, %rsp - - pop %rdi - call __setinitialcwd - - pop %rdi - pop %rsi - pop %rdx - and $~0xF, %rsp - call main - mov %rax, %rdi - jmp exit diff --git a/src/user/lib/elfload.c b/src/user/lib/elfload.c index 777c8b8..9776a13 100644 --- a/src/user/lib/elfload.c +++ b/src/user/lib/elfload.c @@ -65,9 +65,9 @@ static size_t elf_spread(const void *elf) { return high - low; } -static void *malloccpy(const void *orig, size_t len) { +static void *memdup(const void *orig, size_t len) { void *n = malloc(len); - memcpy(n, orig, len); + if (n) memcpy(n, orig, len); return n; } @@ -76,50 +76,41 @@ static void *malloccpy(const void *orig, size_t len) { 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, 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); - } + void *stack = (void*)~0; + struct execdata ed; - /* push cwd */ - len = absolutepath(NULL, NULL, 0); - stack.b -= len; - cwd = stack.b; - getcwd(cwd, len); - - /* push argv */ if (argv) { - 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; + size_t argv_len; + ed.argc = 0; + while (argv[ed.argc]) ed.argc++; + argv_len = (ed.argc+1) * sizeof(char *); + + /* make a copy of argv, so it doesn't get overridden + * if it overlaps with the new stack. */ + argv = memdup(argv, argv_len); + for (int i = 0; i < ed.argc; i++) + argv[i] = strdup(argv[i]); + + stack -= argv_len; + ed.argv = stack; + + for (int i = 0; i < ed.argc; i++) { + size_t len = strlen(argv[i]) + 1; + stack -= len; + memcpy(stack, argv[i], len); + ed.argv[i] = stack; } - *--(stack.ptr) = NULL; /* NULL terminate argv */ - stack.b -= argv_len; - memcpy(stack.b, argv, argv_len); - argv = stack.b; + ed.argv[ed.argc] = NULL; } - *--(stack.ptr) = envp; - *--(stack.ptr) = argv; - *--(stack.n) = argc; + /* push cwd */ + size_t len = absolutepath(NULL, NULL, 0); + stack -= len; + getcwd(stack, len); + ed.cwd = stack; - *--(stack.ptr) = cwd; + stack -= sizeof ed; + memcpy(stack, &ed, sizeof ed); uintptr_t high = (uintptr_t)low + imglen; uint64_t buf[] = { @@ -127,7 +118,7 @@ void _freejmp(void *entry, void *low, size_t imglen, const char **argv, char **e EXECBUF_SYSCALL, _SYSCALL_MEMFLAG, high, ~0 - 0xF000 - high, 0, 0, 0, EXECBUF_JMP, (uintptr_t)entry, }; - execbuf_chstack(stack.b, buf, sizeof buf); + execbuf_chstack(stack, buf, sizeof buf); } static void *elf_loadmem(struct Elf64_Ehdr *ehdr) { diff --git a/src/user/lib/elfload.h b/src/user/lib/elfload.h index 283efd8..825f765 100644 --- a/src/user/lib/elfload.h +++ b/src/user/lib/elfload.h @@ -1,6 +1,12 @@ #pragma once #include +struct execdata { + int argc; + char **argv, **envp; + char *cwd; +}; + void elf_execf(FILE *f, char **argv, char **envp); void elf_exec(void *base, char **argv, char **envp); void *elf_partialexec(void *elf); /* returns pointer to entry point */ -- cgit v1.2.3