From 2c8b5d4752e2c325f2699f82102bce4369b22ec6 Mon Sep 17 00:00:00 2001 From: Ruslan Isaev Date: Tue, 16 Sep 2025 22:41:32 +0300 Subject: [PATCH] syscalls: implement argv and envp handling in execve --- grubshit/caller.c | 4 +-- src/tasking/syscalls.c | 73 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 72 insertions(+), 5 deletions(-) diff --git a/grubshit/caller.c b/grubshit/caller.c index bc6a312..0cbb593 100644 --- a/grubshit/caller.c +++ b/grubshit/caller.c @@ -9,10 +9,10 @@ int main() { // Arguments for the new program // The first argument is conventionally the program name - char *argv[] = {NULL}; //{ "./callee", "first_arg", "second_arg", NULL }; + char *argv[] = { "./callee", "first_arg", "second_arg", NULL }; // Environment variables for the new program - char *envp[] = {NULL}; //{ "CUSTOM_VAR=Hello from caller!", "ANOTHER_VAR=123", NULL }; + char *envp[] = { "CUSTOM_VAR=Hello from caller!", "ANOTHER_VAR=123", NULL }; // The execve system call // The first argument is the path to the executable diff --git a/src/tasking/syscalls.c b/src/tasking/syscalls.c index 6f81440..c270350 100644 --- a/src/tasking/syscalls.c +++ b/src/tasking/syscalls.c @@ -18,6 +18,8 @@ extern void switchProcess(Process* next); #define EBADF 9 +#define EXECVE_MAX_ARGUMENT_SIZE 255 + const char* flags_to_mode_str(int flags) { static char mode[4] = {0}; int accmode = flags & 3; @@ -251,9 +253,44 @@ int sys_close(TrapFrame *tf) extern void execve_return(TrapFrame *tf); +/** + * this might be a not really good implementation as it only supports + * up to EXECVE_MAX_ARGUMENT_SIZE characters in each argument or environment + * string and for some reason I was unable to use malloc for kernel_argv and + * kernel_envp +*/ int sys_execve(TrapFrame *tf) { const char* filename = (const char*)tf->ebx; + char **argv = (char**)tf->ecx; + char **envp = (char**)tf->edx; + + int argc = 0; + int envc = 0; + + while(argv[argc] != NULL) + { + argc++; + } + while(envp[envc] != NULL) + { + envc++; + } + + //TODO: check why was there a triple fault when I tried using malloc + char kernel_argv[argc][EXECVE_MAX_ARGUMENT_SIZE]; + char kernel_envp[envc][EXECVE_MAX_ARGUMENT_SIZE]; + + for(int i = 0; i < argc; i++) + { + strcpy(kernel_argv[i], argv[i]); + } + + for(int i = 0; i < envc; i++) + { + strcpy(kernel_envp[i], envp[i]); + } + uint8_t* file_buffer; int err = vsf_read_file_by_path(filename, &file_buffer, root_dir); if (err != 0) { @@ -304,10 +341,40 @@ int sys_execve(TrapFrame *tf) { void* phys_addr = alloc_page(); map_page(phys_addr, (void*)(vaddr & ~0xFFF), PAGE_PRESENT | PAGE_RW | PAGE_USER); } + uint32_t user_esp = USER_STACK_TOP; - user_esp -= 4; *(uint32_t*)user_esp = 0; // envp - user_esp -= 4; *(uint32_t*)user_esp = 0; // argv - user_esp -= 4; *(uint32_t*)user_esp = 0; // argc + + //push environment strings + uint32_t envp_pointers[envc + 1]; + for (int i = envc - 1; i >= 0; i--) { + size_t len = strlen(kernel_envp[i]) + 1; + user_esp -= len; + memcpy((void*)user_esp, kernel_envp[i], len); + envp_pointers[i] = user_esp; + } + envp_pointers[envc] = 0;//null terminator + + //push argument strings + uint32_t argv_pointers[argc + 1]; + for (int i = argc - 1; i >= 0; i--) { + size_t len = strlen(kernel_argv[i]) + 1; + user_esp -= len; + memcpy((void*)user_esp, kernel_argv[i], len); + argv_pointers[i] = user_esp; + } + argv_pointers[argc] = 0;//null terminator + + //push envp pointers + user_esp -= (envc + 1) * sizeof(uint32_t); + memcpy((void*)user_esp, envp_pointers, (envc + 1) * sizeof(uint32_t)); + + //push argv pointers + user_esp -= (argc + 1) * sizeof(uint32_t); + memcpy((void*)user_esp, argv_pointers, (argc + 1) * sizeof(uint32_t)); + + //push argc + user_esp -= sizeof(uint32_t); + *((uint32_t*)user_esp) = argc; current->brk = (void*)(DivRoundUp(highest_vaddr, PAGE_SIZE) * PAGE_SIZE); free(file_buffer);