From b6ff3c7dbab3f40d03389808d95ac27d416c35e3 Mon Sep 17 00:00:00 2001 From: Minep Date: Sun, 16 Jul 2023 18:20:16 +0100 Subject: [PATCH 1/1] refactor: decouple the executable file implementations with execve functionality. --- lunaix-os/config/make-os | 2 +- .../includes/lunaix/{elf.h => exebi/elf32.h} | 12 +- lunaix-os/includes/lunaix/exec.h | 24 ++-- lunaix-os/includes/lunaix/load.h | 10 ++ .../{loader/elf.c => exe/elf32/elf32bfmt.c} | 100 ++------------ lunaix-os/kernel/exe/elf32/ldelf32.c | 123 ++++++++++++++++++ lunaix-os/kernel/{loader => exe}/exec.c | 102 +++++---------- lunaix-os/kernel/proc0.c | 2 +- lunaix-os/uprog/init.c | 2 +- lunaix-os/uprog/ls.c | 4 +- 10 files changed, 200 insertions(+), 181 deletions(-) rename lunaix-os/includes/lunaix/{elf.h => exebi/elf32.h} (94%) create mode 100644 lunaix-os/includes/lunaix/load.h rename lunaix-os/kernel/{loader/elf.c => exe/elf32/elf32bfmt.c} (57%) create mode 100644 lunaix-os/kernel/exe/elf32/ldelf32.c rename lunaix-os/kernel/{loader => exe}/exec.c (70%) diff --git a/lunaix-os/config/make-os b/lunaix-os/config/make-os index 5cb285c..fd4908e 100644 --- a/lunaix-os/config/make-os +++ b/lunaix-os/config/make-os @@ -1,7 +1,7 @@ OS_ARCH := x86 OS_NAME := lunaix OS_ID := LunaixOS -OS_VER := dev20230618 +OS_VER := dev$(shell date +%Y%m%d) OS_BIN := $(OS_NAME).bin OS_ISO := $(OS_NAME).iso diff --git a/lunaix-os/includes/lunaix/elf.h b/lunaix-os/includes/lunaix/exebi/elf32.h similarity index 94% rename from lunaix-os/includes/lunaix/elf.h rename to lunaix-os/includes/lunaix/exebi/elf32.h index cff442c..d9f4f58 100644 --- a/lunaix-os/includes/lunaix/elf.h +++ b/lunaix-os/includes/lunaix/exebi/elf32.h @@ -1,5 +1,5 @@ -#ifndef __LUNAIX_ELF_H -#define __LUNAIX_ELF_H +#ifndef __LUNAIX_ELF32_H +#define __LUNAIX_ELF32_H #include @@ -34,6 +34,9 @@ typedef unsigned int elf32_wrd_t; #define EI_CLASS 4 #define EI_DATA 5 +#define NO_LOADER 0 +#define DEFAULT_LOADER "usr/ld" + struct elf32_ehdr { u8_t e_ident[16]; @@ -114,10 +117,7 @@ elf32_read_phdr(struct elf32* elf); size_t elf32_loadable_memsz(const struct elf32* elf); -int -elf32_load(struct load_context* ldctx, const struct elf32* elf); - #define SIZE_EHDR sizeof(struct elf32_ehdr) #define SIZE_PHDR sizeof(struct elf32_phdr) -#endif /* __LUNAIX_ELF_H */ +#endif /* __LUNAIX_ELF32_H */ diff --git a/lunaix-os/includes/lunaix/exec.h b/lunaix-os/includes/lunaix/exec.h index 00f4d39..2bc0d94 100644 --- a/lunaix-os/includes/lunaix/exec.h +++ b/lunaix-os/includes/lunaix/exec.h @@ -1,14 +1,10 @@ #ifndef __LUNAIX_EXEC_H #define __LUNAIX_EXEC_H -#include #include #include #include -#define NO_LOADER 0 -#define DEFAULT_LOADER "usr/ld" - #define MAX_VAR_PAGES 8 #define DEFAULT_HEAP_PAGES 16 @@ -29,10 +25,14 @@ struct exec_container struct proc_info* proc; ptr_t vms_mnt; - struct load_context executable; + struct load_context exe; + + // argv prependums + char* argv_pp[2]; + const char** argv; + const char** envp; ptr_t stack_top; - ptr_t entry; // mapped to one of {executable|loader}.entry int status; }; @@ -48,19 +48,13 @@ struct uexec_param #ifndef __USR_WRAPPER__ int -exec_load_byname(struct exec_container* container, - const char* filename, - const char** argv, - const char** envp); +exec_load_byname(struct exec_container* container, const char* filename); int -exec_load(struct exec_container* container, - struct v_file* executable, - const char** argv, - const char** envp); +exec_load(struct exec_container* container, struct v_file* executable); int -exec_kexecve(const char* filename, const char* argv[], const char* envp); +exec_kexecve(const char* filename, const char* argv[], const char* envp[]); #endif diff --git a/lunaix-os/includes/lunaix/load.h b/lunaix-os/includes/lunaix/load.h new file mode 100644 index 0000000..a816491 --- /dev/null +++ b/lunaix-os/includes/lunaix/load.h @@ -0,0 +1,10 @@ +#ifndef __LUNAIX_LOAD_H +#define __LUNAIX_LOAD_H + +#include +#include + +int +load_executable(struct load_context* context, const struct v_file* exefile); + +#endif /* __LUNAIX_LOAD_H */ diff --git a/lunaix-os/kernel/loader/elf.c b/lunaix-os/kernel/exe/elf32/elf32bfmt.c similarity index 57% rename from lunaix-os/kernel/loader/elf.c rename to lunaix-os/kernel/exe/elf32/elf32bfmt.c index fa6b576..1079b06 100644 --- a/lunaix-os/kernel/loader/elf.c +++ b/lunaix-os/kernel/exe/elf32/elf32bfmt.c @@ -1,13 +1,11 @@ -#include #include -#include -#include +#include #include -#include #include -#include #include +#include + static inline int elf32_read(struct v_file* elf, void* data, size_t off, size_t len) { @@ -15,56 +13,10 @@ elf32_read(struct v_file* elf, void* data, size_t off, size_t len) return pcache_read(elf->inode, data, len, off); } -int -elf32_map_segment(struct load_context* ldctx, - const struct elf32* elf, - struct elf32_phdr* phdre) -{ - struct v_file* elfile = (struct v_file*)elf->elf_file; - - assert(PG_ALIGNED(phdre->p_offset)); - - int proct = 0; - if ((phdre->p_flags & PF_R)) { - proct |= PROT_READ; - } - if ((phdre->p_flags & PF_W)) { - proct |= PROT_WRITE; - } - if ((phdre->p_flags & PF_X)) { - proct |= PROT_EXEC; - } - - struct exec_container* container = ldctx->container; - struct mmap_param param = { .vms_mnt = container->vms_mnt, - .pvms = &container->proc->mm, - .proct = proct, - .offset = PG_ALIGN(phdre->p_offset), - .mlen = ROUNDUP(phdre->p_memsz, PG_SIZE), - .flen = phdre->p_filesz + PG_MOD(phdre->p_va), - .flags = MAP_FIXED | MAP_PRIVATE, - .type = REGION_TYPE_CODE }; - - struct mm_region* seg_reg; - int status = mem_map(NULL, &seg_reg, PG_ALIGN(phdre->p_va), elfile, ¶m); - - if (!status) { - size_t next_addr = phdre->p_memsz + phdre->p_va; - ldctx->end = MAX(ldctx->end, ROUNDUP(next_addr, PG_SIZE)); - ldctx->mem_sz += phdre->p_memsz; - } else { - // we probably fucked up our process - terminate_proc(-1); - } - - return status; -} - int elf32_open(struct elf32* elf, const char* path) { struct v_dnode* elfdn; - struct v_inode* elfin; struct v_file* elffile; int error = 0; @@ -96,7 +48,7 @@ elf32_openat(struct elf32* elf, void* elf_vfile) return status; } - return status; + return 0; } int @@ -111,6 +63,8 @@ elf32_close(struct elf32* elf) } memset(elf, 0, sizeof(*elf)); + + return 0; } int @@ -156,9 +110,12 @@ elf32_find_loader(const struct elf32* elf, char* path_out, size_t len) for (size_t i = 0; i < elf->eheader.e_phnum; i++) { struct elf32_phdr* phdre = &elf->pheaders[i]; if (phdre->p_type == PT_INTERP) { - assert_msg(len >= phdre->p_filesz, "path_out: too small"); + if (len >= phdre->p_filesz) { + return EINVAL; + } + retval = - elf_read(elfile, path_out, phdre->p_offset, phdre->p_filesz); + elf32_read(elfile, path_out, phdre->p_offset, phdre->p_filesz); if (retval < 0) { return retval; @@ -175,11 +132,8 @@ int elf32_read_ehdr(struct elf32* elf) { struct v_file* elfile = (struct v_file*)elf->elf_file; - int status = elf_read(elfile, (void*)&elf->eheader, 0, SIZE_EHDR); - if (status < 0) { - return status; - } + return elf32_read(elfile, (void*)&elf->eheader, 0, SIZE_EHDR); } int @@ -198,7 +152,7 @@ elf32_read_phdr(struct elf32* elf) return ENOMEM; } - status = elf_read(elfile, phdrs, elf->eheader.e_phoff, tbl_sz); + status = elf32_read(elfile, phdrs, elf->eheader.e_phoff, tbl_sz); if (status < 0) { vfree(phdrs); @@ -212,36 +166,10 @@ elf32_read_phdr(struct elf32* elf) int elf32_check_exec(const struct elf32* elf) { - struct elf32_ehdr* ehdr = elf->pheaders; + struct elf32_ehdr* ehdr = &elf->eheader; return *(u32_t*)(ehdr->e_ident) == ELFMAGIC && ehdr->e_ident[EI_CLASS] == ELFCLASS32 && ehdr->e_ident[EI_DATA] == ELFDATA2LSB && ehdr->e_type == ET_EXEC && ehdr->e_machine == EM_386; } - -int -elf32_load(struct load_context* ldctx, const struct elf32* elf) -{ - int err = 0; - - struct v_file* elfile = (struct v_file*)elf->elf_file; - - for (size_t i = 0; i < elf->eheader.e_phnum && !err; i++) { - struct elf32_phdr* phdr = &elf->pheaders[i]; - - if (phdr->p_type == PT_LOAD) { - if (phdr->p_align != PG_SIZE) { - // surprising alignment! - err = ENOEXEC; - continue; - } - - err = elf_map_segment(ldctx, elf, phdr); - } - // TODO Handle relocation - } - -done: - return err; -} \ No newline at end of file diff --git a/lunaix-os/kernel/exe/elf32/ldelf32.c b/lunaix-os/kernel/exe/elf32/ldelf32.c new file mode 100644 index 0000000..1204be4 --- /dev/null +++ b/lunaix-os/kernel/exe/elf32/ldelf32.c @@ -0,0 +1,123 @@ +#include +#include +#include +#include +#include + +int +elf32_smap(struct load_context* ldctx, + const struct elf32* elf, + struct elf32_phdr* phdre) +{ + struct v_file* elfile = (struct v_file*)elf->elf_file; + + assert(PG_ALIGNED(phdre->p_offset)); + + int proct = 0; + if ((phdre->p_flags & PF_R)) { + proct |= PROT_READ; + } + if ((phdre->p_flags & PF_W)) { + proct |= PROT_WRITE; + } + if ((phdre->p_flags & PF_X)) { + proct |= PROT_EXEC; + } + + struct exec_container* container = ldctx->container; + struct mmap_param param = { .vms_mnt = container->vms_mnt, + .pvms = &container->proc->mm, + .proct = proct, + .offset = PG_ALIGN(phdre->p_offset), + .mlen = ROUNDUP(phdre->p_memsz, PG_SIZE), + .flen = phdre->p_filesz + PG_MOD(phdre->p_va), + .flags = MAP_FIXED | MAP_PRIVATE, + .type = REGION_TYPE_CODE }; + + struct mm_region* seg_reg; + int status = mem_map(NULL, &seg_reg, PG_ALIGN(phdre->p_va), elfile, ¶m); + + if (!status) { + size_t next_addr = phdre->p_memsz + phdre->p_va; + ldctx->end = MAX(ldctx->end, ROUNDUP(next_addr, PG_SIZE)); + ldctx->mem_sz += phdre->p_memsz; + } else { + // we probably fucked up our process + terminate_proc(-1); + } + + return status; +} + +int +load_executable(struct load_context* context, const struct v_file* exefile) +{ + int errno = 0; + + char* ldpath = NULL; + struct elf32 elf; + struct exec_container* container = context->container; + + if ((errno = elf32_openat(&elf, exefile))) { + goto done; + } + + if (!elf32_check_exec(&elf)) { + errno = ENOEXEC; + goto done; + } + + ldpath = valloc(512); + errno = elf32_find_loader(&elf, ldpath, 512); + + if (errno < 0) { + goto done; + } + + if (errno != NO_LOADER) { + container->argv_pp[1] = ldpath; + + // close old elf + if ((errno = elf32_close(&elf))) { + goto done; + } + + // open the loader instead + if ((errno = elf32_open(&elf, ldpath))) { + goto done; + } + + // Is this the valid loader? + if (!elf32_static_linked(&elf) || !elf32_check_exec(&elf)) { + errno = ELIBBAD; + goto done_close_elf32; + } + + // TODO: relocate loader + } else { + context->entry = elf.eheader.e_entry; + } + + struct v_file* elfile = (struct v_file*)elf.elf_file; + + for (size_t i = 0; i < elf.eheader.e_phnum && !errno; i++) { + struct elf32_phdr* phdr = &elf.pheaders[i]; + + if (phdr->p_type == PT_LOAD) { + if (phdr->p_align != PG_SIZE) { + // surprising alignment! + errno = ENOEXEC; + continue; + } + + errno = elf32_smap(context, &elf, phdr); + } + // TODO Handle relocation + } + +done_close_elf32: + elf32_close(&elf); +done: + vfree_safe(ldpath); + return errno; +} diff --git a/lunaix-os/kernel/loader/exec.c b/lunaix-os/kernel/exe/exec.c similarity index 70% rename from lunaix-os/kernel/loader/exec.c rename to lunaix-os/kernel/exe/exec.c index 5024a1d..535f659 100644 --- a/lunaix-os/kernel/loader/exec.c +++ b/lunaix-os/kernel/exe/exec.c @@ -1,7 +1,7 @@ #include -#include #include #include +#include #include #include #include @@ -14,11 +14,18 @@ #include void -exec_container(struct exec_container* param, struct proc_info* proc, ptr_t vms) +exec_container(struct exec_container* param, + struct proc_info* proc, + ptr_t vms, + const char** argv, + const char** envp) { *param = (struct exec_container){ .proc = proc, .vms_mnt = vms, - .executable = { .container = param } }; + .exe = { .container = param }, + .argv_pp = { 0, 0 }, + .argv = argv, + .envp = envp }; } size_t @@ -48,72 +55,28 @@ extern int create_heap(struct proc_mm* pvms, ptr_t addr); int -exec_load(struct exec_container* container, - struct v_file* executable, - const char** argv, - const char** envp) +exec_load(struct exec_container* container, struct v_file* executable) { int errno = 0; - char* ldpath = NULL; + const char **argv = container->argv, **envp = container->envp; size_t argv_len, envp_len; size_t sz_argv = exec_str_size(argv, &argv_len); size_t sz_envp = exec_str_size(envp, &envp_len); size_t var_sz = ROUNDUP(sz_envp, PG_SIZE); + char** argv_extra = container->argv_pp; - char* argv_extra[2] = { executable->dnode->name.value, 0 }; + argv_extra[0] = executable->dnode->name.value; if (var_sz / PG_SIZE > MAX_VAR_PAGES) { errno = E2BIG; goto done; } - struct elf32 elf; - - if ((errno = elf32_openat(&elf, executable))) { - goto done; - } - - if (!elf32_check_exec(&elf)) { - errno = ENOEXEC; - goto done; - } - - ldpath = valloc(512); - errno = elf32_find_loader(&elf, ldpath, 512); - - if (errno < 0) { - vfree(ldpath); + if ((errno = load_executable(&container->exe, executable))) { goto done; } - if (errno != NO_LOADER) { - // TODO load loader - argv_extra[1] = ldpath; - - // close old elf - if ((errno = elf32_close(&elf))) { - goto done; - } - - // open the loader instead - if ((errno = elf32_open(&elf, ldpath))) { - goto done; - } - - // Is this the valid loader? - if (!elf32_static_linked(&elf) || !elf32_check_exec(&elf)) { - errno = ELIBBAD; - goto done_close_elf32; - } - - // TODO: relocate loader - } - - if ((errno = elf32_load(&container->executable, &elf))) { - goto done_close_elf32; - } - struct proc_mm* pvms = &container->proc->mm; // A dedicated place for process variables (e.g. envp) @@ -134,11 +97,11 @@ exec_load(struct exec_container* container, if (!argv_extra[1]) { // If loading a statically linked file, then heap remapping we can do, // otherwise delayed. - create_heap(container->vms_mnt, PG_ALIGN(container->executable.end)); + create_heap(&container->proc->mm, PG_ALIGN(container->exe.end)); } if ((errno = mem_map(&mapped, NULL, UMMAP_END, NULL, &map_vars))) { - goto done_close_elf32; + goto done; } if (container->vms_mnt == VMS_SELF) { @@ -190,18 +153,12 @@ exec_load(struct exec_container* container, fail("not implemented"); } -done_close_elf32: - elf32_close(&elf); done: - vfree_safe(ldpath); return errno; } int -exec_load_byname(struct exec_container* container, - const char* filename, - const char** argv, - const char** envp) +exec_load_byname(struct exec_container* container, const char* filename) { int errno = 0; struct v_dnode* dnode; @@ -215,26 +172,33 @@ exec_load_byname(struct exec_container* container, goto done; } - errno = exec_load(container, file, argv, envp); + errno = exec_load(container, file); done: return errno; } int -exec_kexecve(const char* filename, const char* argv[], const char* envp) +exec_kexecve(const char* filename, const char* argv[], const char* envp[]) { int errno = 0; struct exec_container container; - exec_container(&container, __current, VMS_SELF); + exec_container(&container, __current, VMS_SELF, argv, envp); - errno = exec_load_byname(&container, filename, argv, envp); + errno = exec_load_byname(&container, filename); if (errno) { return errno; } - j_usr(container.stack_top, container.entry); + ptr_t entry = container.exe.entry; + + assert(entry); + j_usr(container.stack_top, entry); + + // should not reach + + return errno; } __DEFINE_LXSYSCALL3(int, @@ -248,9 +212,9 @@ __DEFINE_LXSYSCALL3(int, { int errno = 0; struct exec_container container; - exec_container(&container, __current, VMS_SELF); + exec_container(&container, __current, VMS_SELF, argv, envp); - if (!(errno = exec_load_byname(&container, filename, argv, envp))) { + if ((errno = exec_load_byname(&container, filename))) { goto done; } @@ -258,7 +222,7 @@ __DEFINE_LXSYSCALL3(int, // return so execve 'will not return' from the perspective of it's invoker volatile struct exec_param* execp = __current->intr_ctx.execp; execp->esp = container.stack_top; - execp->eip = container.entry; + execp->eip = container.exe.entry; done: // set return value diff --git a/lunaix-os/kernel/proc0.c b/lunaix-os/kernel/proc0.c index d765691..2029bc5 100644 --- a/lunaix-os/kernel/proc0.c +++ b/lunaix-os/kernel/proc0.c @@ -68,7 +68,7 @@ exec_initd() { int errno = 0; - if (exec_kexecve("/mnt/lunaix-os/usr/init", NULL, NULL)) { + if ((errno = exec_kexecve("/mnt/lunaix-os/usr/init", NULL, NULL))) { goto fail; } diff --git a/lunaix-os/uprog/init.c b/lunaix-os/uprog/init.c index 82e3ea3..b78cd3b 100644 --- a/lunaix-os/uprog/init.c +++ b/lunaix-os/uprog/init.c @@ -28,7 +28,7 @@ main(int argc, const char** argv) pid_t pid; if (!(pid = fork())) { - err = execve("/mnt/lunaix-os/usr/sh", NULL, NULL); + err = execve("/usr/sh", NULL, NULL); printf("fail to execute (%d)\n", errno); _exit(err); } diff --git a/lunaix-os/uprog/ls.c b/lunaix-os/uprog/ls.c index da4cca3..bac3c71 100644 --- a/lunaix-os/uprog/ls.c +++ b/lunaix-os/uprog/ls.c @@ -6,8 +6,8 @@ int main(int argc, const char* argv[]) { char* path = "."; - if (argc > 0) { - path = argv[0]; + if (argc > 1) { + path = argv[1]; } DIR* dir = opendir(path); -- 2.27.0