syscalls: fix execve to use heap and make it work better with fork
This commit is contained in:
+41
-44
@@ -331,68 +331,68 @@ 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
|
||||
* string
|
||||
*/
|
||||
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;
|
||||
while(argv[argc] != NULL) argc++;
|
||||
|
||||
int envc = 0;
|
||||
while(envp[envc] != NULL) envc++;
|
||||
|
||||
while(argv[argc] != NULL)
|
||||
{
|
||||
argc++;
|
||||
}
|
||||
while(envp[envc] != NULL)
|
||||
{
|
||||
envc++;
|
||||
}
|
||||
char** kernel_argv = malloc((argc + 1) * sizeof(char*));
|
||||
if (!kernel_argv) return -1;
|
||||
|
||||
//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++)
|
||||
{
|
||||
for(int i = 0; i < argc; i++) {
|
||||
kernel_argv[i] = malloc(EXECVE_MAX_ARGUMENT_SIZE);
|
||||
strcpy(kernel_argv[i], argv[i]);
|
||||
}
|
||||
kernel_argv[argc] = NULL;
|
||||
|
||||
for(int i = 0; i < envc; i++)
|
||||
{
|
||||
char** kernel_envp = malloc((envc + 1) * sizeof(char*));
|
||||
if (!kernel_envp) return -1; // TODO: cleanup kernel_argv
|
||||
|
||||
for(int i = 0; i < envc; i++) {
|
||||
kernel_envp[i] = malloc(EXECVE_MAX_ARGUMENT_SIZE);
|
||||
strcpy(kernel_envp[i], envp[i]);
|
||||
}
|
||||
kernel_envp[envc] = NULL;
|
||||
|
||||
uint8_t* file_buffer;
|
||||
int err = vfs_read_file_by_path(filename, &file_buffer);
|
||||
if (err != 0) {
|
||||
debug_log("execve: failed to read file '%s'\n", filename);
|
||||
// TODO: Free kernel_argv/envp
|
||||
debug_log("execve: failed to read file\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
Elf32_Ehdr *elf_header = (Elf32_Ehdr*)file_buffer;
|
||||
if (memcmp(elf_header->e_ident, "\x7F" "ELF", 4) != 0) {
|
||||
debug_log("execve: '%s' is not a valid ELF file\n", filename);
|
||||
free(file_buffer);
|
||||
// TODO: Free resources
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint32_t* new_page_dir = create_page_dir();
|
||||
if (!new_page_dir) {
|
||||
free(file_buffer);
|
||||
return -1;
|
||||
}
|
||||
uint32_t new_page_dir_phys = (uint32_t)get_physaddr((void*)new_page_dir);
|
||||
uint32_t* old_page_dir_to_free = current->pagedir;
|
||||
if (!new_page_dir) return -1;
|
||||
|
||||
set_page_dir(new_page_dir_phys);
|
||||
current->pagedir = new_page_dir;
|
||||
uint32_t new_page_dir_phys = (uint32_t)get_physaddr((void*)new_page_dir);
|
||||
|
||||
void* process_phys = get_physaddr(current);
|
||||
map_page_in_directory(new_page_dir, process_phys, current, PAGE_PRESENT | PAGE_RW);
|
||||
|
||||
void* kstack_phys = get_physaddr(current->kstack);
|
||||
map_page(kstack_phys, current->kstack, PAGE_PRESENT | PAGE_RW);
|
||||
map_page_in_directory(new_page_dir, kstack_phys, current->kstack, PAGE_PRESENT | PAGE_RW);
|
||||
|
||||
void* argv_phys = get_physaddr(kernel_argv);
|
||||
map_page_in_directory(new_page_dir, argv_phys, kernel_argv, PAGE_PRESENT | PAGE_RW);
|
||||
|
||||
uint32_t* old_page_dir_to_free = current->pagedir;
|
||||
set_page_dir(new_page_dir_phys);
|
||||
current->pagedir = new_page_dir;
|
||||
|
||||
uint32_t highest_vaddr = 0;
|
||||
for (int i = 0; i < elf_header->e_phnum; i++) {
|
||||
@@ -400,7 +400,6 @@ int sys_execve(TrapFrame *tf) {
|
||||
if (p_header->p_type == PT_LOAD) {
|
||||
uint32_t start_addr = p_header->p_vaddr;
|
||||
uint32_t end_addr = start_addr + p_header->p_memsz;
|
||||
|
||||
uint32_t start_page = start_addr & ~0xFFF;
|
||||
uint32_t end_page = (end_addr - 1) & ~0xFFF;
|
||||
|
||||
@@ -413,9 +412,7 @@ int sys_execve(TrapFrame *tf) {
|
||||
if (p_header->p_memsz > p_header->p_filesz) {
|
||||
memset((void*)(p_header->p_vaddr + p_header->p_filesz), 0, p_header->p_memsz - p_header->p_filesz);
|
||||
}
|
||||
if (p_header->p_vaddr + p_header->p_memsz > highest_vaddr) {
|
||||
highest_vaddr = p_header->p_vaddr + p_header->p_memsz;
|
||||
}
|
||||
if (end_addr > highest_vaddr) highest_vaddr = end_addr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -426,7 +423,6 @@ int sys_execve(TrapFrame *tf) {
|
||||
|
||||
uint32_t user_esp = USER_STACK_TOP;
|
||||
|
||||
//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;
|
||||
@@ -434,9 +430,8 @@ int sys_execve(TrapFrame *tf) {
|
||||
memcpy((void*)user_esp, kernel_envp[i], len);
|
||||
envp_pointers[i] = user_esp;
|
||||
}
|
||||
envp_pointers[envc] = 0;//null terminator
|
||||
|
||||
//push argument strings
|
||||
envp_pointers[envc] = 0;
|
||||
|
||||
uint32_t argv_pointers[argc + 1];
|
||||
for (int i = argc - 1; i >= 0; i--) {
|
||||
size_t len = strlen(kernel_argv[i]) + 1;
|
||||
@@ -444,22 +439,25 @@ int sys_execve(TrapFrame *tf) {
|
||||
memcpy((void*)user_esp, kernel_argv[i], len);
|
||||
argv_pointers[i] = user_esp;
|
||||
}
|
||||
argv_pointers[argc] = 0;//null terminator
|
||||
argv_pointers[argc] = 0;
|
||||
|
||||
//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);
|
||||
for(int i=0; i<argc; i++) free(kernel_argv[i]);
|
||||
free(kernel_argv);
|
||||
for(int i=0; i<envc; i++) free(kernel_envp[i]);
|
||||
free(kernel_envp);
|
||||
|
||||
destroy_page_dir(old_page_dir_to_free);
|
||||
|
||||
tf->gs = SEG_UDATA | DPL_USER;
|
||||
@@ -475,7 +473,6 @@ int sys_execve(TrapFrame *tf) {
|
||||
tf->usermode_ss = SEG_UDATA | DPL_USER;
|
||||
|
||||
execve_return(tf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user