From ae2f69d3b8c8cd93c8f79aef17ad8092c5140355 Mon Sep 17 00:00:00 2001 From: Qwinci <32550582+Qwinci@users.noreply.github.com> Date: Mon, 13 Jan 2025 16:15:08 +0200 Subject: [PATCH] elf: add AT_EXECFN --- kernel-src/include/kernel/elf.h | 4 +++- kernel-src/sys/elf.c | 13 ++++++++++--- kernel-src/sys/proc.c | 2 +- kernel-src/sys/syscalls/execve.c | 2 +- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/kernel-src/include/kernel/elf.h b/kernel-src/include/kernel/elf.h index beec12ca..28aff67a 100644 --- a/kernel-src/include/kernel/elf.h +++ b/kernel-src/include/kernel/elf.h @@ -28,6 +28,7 @@ #define AT_PHENT 4 #define AT_PHNUM 5 #define AT_ENTRY 9 +#define AT_EXECFN 31 typedef struct { uint64_t type; @@ -39,6 +40,7 @@ typedef struct { auxv64_t phnum; auxv64_t phent; auxv64_t entry; + auxv64_t execfn; auxv64_t null; } auxv64list_t; @@ -83,6 +85,6 @@ typedef struct{ } __attribute__((packed)) elfph64_t; int elf_load(vnode_t *vnode, void *base, void **entry, char **interpreter, auxv64list_t *auxv64); -void *elf_preparestack(void *top, auxv64list_t *auxv64, char **argv, char **envp); +void *elf_preparestack(void *top, auxv64list_t *auxv64, char **argv, char **envp, char *path); #endif diff --git a/kernel-src/sys/elf.c b/kernel-src/sys/elf.c index 74b7a6a5..91cf57a4 100644 --- a/kernel-src/sys/elf.c +++ b/kernel-src/sys/elf.c @@ -215,11 +215,12 @@ int elf_load(vnode_t *vnode, void *base, void **entry, char **interpreter, auxv6 #define STACK_SIZE (1024 * 1024 * 4) #define STACK_TOP_BUFFER 8 -void *elf_preparestack(void *top, auxv64list_t *auxv64, char **argv, char **envp) { +void *elf_preparestack(void *top, auxv64list_t *auxv64, char **argv, char **envp, char *path) { size_t argc; size_t envc; size_t argdatasize = 0; size_t envdatasize = 0; + size_t pathsize = strlen(path) + 1; for (argc = 0; argv[argc]; ++argc) argdatasize += strlen(argv[argc]) + 1; @@ -231,7 +232,7 @@ void *elf_preparestack(void *top, auxv64list_t *auxv64, char **argv, char **envp int alignment = ((argc + 1) + (envc + 1) + 1) & 1 ? 8 : 0; // env data + arg data + pointers to arg and env data + argc + buffer at the top - size_t initialsize = argdatasize + envdatasize + (argc + envc) * sizeof(char *) + sizeof(size_t) + sizeof(auxv64list_t) + alignment + STACK_TOP_BUFFER; + size_t initialsize = argdatasize + envdatasize + pathsize + (argc + envc) * sizeof(char *) + sizeof(size_t) + sizeof(auxv64list_t) + alignment + STACK_TOP_BUFFER; size_t initialsizeround = ROUND_UP(initialsize, PAGE_SIZE); void *initialpagebase = (void *)((uintptr_t)top - initialsizeround); @@ -247,7 +248,8 @@ void *elf_preparestack(void *top, auxv64list_t *auxv64, char **argv, char **envp char *argdatastart = (char *)((uintptr_t)top - argdatasize); char *envdatastart = (char *)((uintptr_t)argdatastart - envdatasize); - auxv64list_t *auxvstart = (auxv64list_t *)envdatastart - 1; + char *pathdatastart = (char *)((uintptr_t)envdatastart - pathsize); + auxv64list_t *auxvstart = (auxv64list_t *)pathdatastart - 1; auxvstart = (auxv64list_t *)(((uintptr_t)auxvstart & ~(uintptr_t)0xf) - alignment); @@ -256,6 +258,11 @@ void *elf_preparestack(void *top, auxv64list_t *auxv64, char **argv, char **envp char **argstart = (char **)envstart - argc - 1; size_t *argcptr = (size_t *)argstart - 1; + auxv64->execfn.type = AT_EXECFN; + auxv64->execfn.val = (uint64_t)pathdatastart; + + memcpy(pathdatastart, path, pathsize); + memcpy(auxvstart, auxv64, sizeof(auxv64list_t)); for (int i = 0; i < argc; ++i) { diff --git a/kernel-src/sys/proc.c b/kernel-src/sys/proc.c index 89383060..f56ebb81 100644 --- a/kernel-src/sys/proc.c +++ b/kernel-src/sys/proc.c @@ -361,7 +361,7 @@ void proc_run_init() { char *argv[] = {"/init", cmdline_get("initarg"), NULL}; char *envp[] = {NULL}; - void *stack = elf_preparestack(STACK_TOP, &auxv64, argv, envp); + void *stack = elf_preparestack(STACK_TOP, &auxv64, argv, envp, "/init"); __assert(stack); // reenter kernel context diff --git a/kernel-src/sys/syscalls/execve.c b/kernel-src/sys/syscalls/execve.c index 51d87740..d067de4e 100644 --- a/kernel-src/sys/syscalls/execve.c +++ b/kernel-src/sys/syscalls/execve.c @@ -258,7 +258,7 @@ static syscallret_t execve(context_t *context, char *upath, char *uargv[], char VOP_RELEASE(interpnode); } - stack = elf_preparestack(STACK_TOP, &auxv64, argv, envp); + stack = elf_preparestack(STACK_TOP, &auxv64, argv, envp, path); if (stack == NULL) { ret.errno = ENOMEM; goto error;