syscalls: implement basic execve syscall, no argc, argv, envp support yet
This commit is contained in:
@@ -0,0 +1,22 @@
|
|||||||
|
// callee.c
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
int main(int argc, char *argv[], char *envp[]) {
|
||||||
|
printf("--- In callee.c ---\n");
|
||||||
|
printf("This program has taken over the process.\n");
|
||||||
|
|
||||||
|
printf("argc: %d\n", argc);
|
||||||
|
|
||||||
|
printf("\nArguments (argv):\n");
|
||||||
|
for (int i = 0; argv[i] != NULL; i++) {
|
||||||
|
printf(" argv[%d]: %s\n", i, argv[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\nEnvironment Variables (envp):\n");
|
||||||
|
for (int i = 0; envp[i] != NULL; i++) {
|
||||||
|
printf(" %s\n", envp[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
// caller.c
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
printf("--- In caller.c ---\n");
|
||||||
|
printf("This message is from the original program.\n");
|
||||||
|
printf("Calling execve to run './callee'...\n\n");
|
||||||
|
|
||||||
|
// Arguments for the new program
|
||||||
|
// The first argument is conventionally the program name
|
||||||
|
char *argv[] = {NULL}; //{ "./callee", "first_arg", "second_arg", NULL };
|
||||||
|
|
||||||
|
// Environment variables for the new program
|
||||||
|
char *envp[] = {NULL}; //{ "CUSTOM_VAR=Hello from caller!", "ANOTHER_VAR=123", NULL };
|
||||||
|
|
||||||
|
// The execve system call
|
||||||
|
// The first argument is the path to the executable
|
||||||
|
// The second is the array of arguments
|
||||||
|
// The third is the array of environment variables
|
||||||
|
execve("callee.", argv, envp);
|
||||||
|
|
||||||
|
// This part of the code will only be reached if execve fails
|
||||||
|
perror("execve failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
@@ -3,4 +3,10 @@
|
|||||||
#include "../include/vfs.h"
|
#include "../include/vfs.h"
|
||||||
#include "../include/lib9660.h"
|
#include "../include/lib9660.h"
|
||||||
|
|
||||||
|
#define DivRoundUp(number, divisor) ((number + divisor - 1) / divisor)
|
||||||
|
|
||||||
|
#define USER_STACK_TOP 0xBFFFFFF0 // Top of user space memory
|
||||||
|
#define USER_STACK_SIZE 0x4000 // 16KB stack (4 pages)
|
||||||
|
#define USER_STACK_BOTTOM (USER_STACK_TOP - USER_STACK_SIZE)
|
||||||
|
|
||||||
void exec_from_file(const char* filename, const char* dirname);
|
void exec_from_file(const char* filename, const char* dirname);
|
||||||
@@ -19,4 +19,6 @@ size_t vfs_read_file_length(l9660_file *file, uint8_t* buffer, size_t length);
|
|||||||
|
|
||||||
void test_iso9660();
|
void test_iso9660();
|
||||||
|
|
||||||
|
int vsf_read_file_by_path(const char* path, uint8_t** buffer, l9660_dir* dir);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -189,4 +189,36 @@ void test_iso9660()
|
|||||||
printf("Total bytes read: ");
|
printf("Total bytes read: ");
|
||||||
printf("0x%X\n", total_bytes);
|
printf("0x%X\n", total_bytes);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int vsf_read_file_by_path(const char* path, uint8_t** buffer, l9660_dir* dir)
|
||||||
|
{
|
||||||
|
l9660_file* file = (l9660_file*)malloc(sizeof(l9660_file));
|
||||||
|
|
||||||
|
l9660_status err;
|
||||||
|
|
||||||
|
err = l9660_openat(file, dir, path);
|
||||||
|
if (err != L9660_OK)
|
||||||
|
{
|
||||||
|
debug_log("read_file: err: 0x%X\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_log("HEHE %s\n", path);
|
||||||
|
|
||||||
|
l9660_seek(file, L9660_SEEK_END, 0);
|
||||||
|
uint32_t file_size = l9660_tell(file);
|
||||||
|
debug_log("file_size: %X\n", file_size);
|
||||||
|
l9660_seek(file, L9660_SEEK_SET, 0);
|
||||||
|
|
||||||
|
*buffer = (uint8_t*)malloc(file_size);
|
||||||
|
debug_log("eeee\n");
|
||||||
|
|
||||||
|
size_t read;
|
||||||
|
|
||||||
|
read = vfs_read_file(file, *buffer);
|
||||||
|
free(file);
|
||||||
|
debug_log("bytes read: 0x%X\n", read);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
+1
-1
@@ -131,7 +131,7 @@ void kmain(unsigned int magic, unsigned int info)
|
|||||||
|
|
||||||
mount_fs();
|
mount_fs();
|
||||||
|
|
||||||
exec_from_file("main.", ".");
|
exec_from_file("caller.", ".");
|
||||||
|
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,42 +6,6 @@
|
|||||||
#include "../include/paging.h"
|
#include "../include/paging.h"
|
||||||
#include "../include/task.h"
|
#include "../include/task.h"
|
||||||
|
|
||||||
#define DivRoundUp(number, divisor) ((number + divisor - 1) / divisor)
|
|
||||||
|
|
||||||
#define USER_STACK_TOP 0xBFFFFFF0 // Top of user space memory
|
|
||||||
#define USER_STACK_SIZE 0x4000 // 16KB stack (4 pages)
|
|
||||||
#define USER_STACK_BOTTOM (USER_STACK_TOP - USER_STACK_SIZE)
|
|
||||||
|
|
||||||
int read_file(const char* path, uint8_t** buffer, l9660_dir* dir)
|
|
||||||
{
|
|
||||||
l9660_file* file = (l9660_file*)malloc(sizeof(l9660_file));
|
|
||||||
|
|
||||||
l9660_status err;
|
|
||||||
|
|
||||||
err = l9660_openat(file, dir, path);
|
|
||||||
if (err != L9660_OK)
|
|
||||||
{
|
|
||||||
debug_log("read_file: err: 0x%X\n", err);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
l9660_seek(file, L9660_SEEK_END, 0);
|
|
||||||
uint32_t file_size = l9660_tell(file);
|
|
||||||
debug_log("file_size: %X\n", file_size);
|
|
||||||
l9660_seek(file, L9660_SEEK_SET, 0);
|
|
||||||
|
|
||||||
*buffer = (uint8_t*)malloc(file_size);
|
|
||||||
debug_log("eeee\n");
|
|
||||||
|
|
||||||
size_t read;
|
|
||||||
|
|
||||||
read = vfs_read_file(file, *buffer);
|
|
||||||
free(file);
|
|
||||||
debug_log("bytes read: 0x%X\n", read);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void exec_from_file(const char* filename, const char* dirname)
|
void exec_from_file(const char* filename, const char* dirname)
|
||||||
{
|
{
|
||||||
asm volatile("cli");
|
asm volatile("cli");
|
||||||
@@ -58,7 +22,7 @@ void exec_from_file(const char* filename, const char* dirname)
|
|||||||
|
|
||||||
uint32_t bss_start, bss_end;
|
uint32_t bss_start, bss_end;
|
||||||
|
|
||||||
err = read_file(filename, &file, &dir);
|
err = vsf_read_file_by_path(filename, &file, &dir);
|
||||||
|
|
||||||
if(err != 0)
|
if(err != 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -31,5 +31,20 @@ sys_exit_handler:
|
|||||||
; Возвращаемся в Ring 3
|
; Возвращаемся в Ring 3
|
||||||
iret
|
iret
|
||||||
|
|
||||||
|
global execve_return
|
||||||
|
|
||||||
|
execve_return:
|
||||||
|
mov esp, [esp+4]
|
||||||
|
|
||||||
|
pop gs
|
||||||
|
pop fs
|
||||||
|
pop es
|
||||||
|
pop ds
|
||||||
|
popa
|
||||||
|
|
||||||
|
add esp, 8
|
||||||
|
|
||||||
|
iret
|
||||||
|
|
||||||
section .data
|
section .data
|
||||||
sys_exit_msg: db "Returned from Ring 3", 0
|
sys_exit_msg: db "Returned from Ring 3", 0
|
||||||
@@ -247,6 +247,89 @@ int sys_close(TrapFrame *tf)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "../include/exec_from_file.h"
|
||||||
|
|
||||||
|
extern void execve_return(TrapFrame *tf);
|
||||||
|
|
||||||
|
int sys_execve(TrapFrame *tf) {
|
||||||
|
const char* filename = (const char*)tf->ebx;
|
||||||
|
|
||||||
|
uint8_t* file_buffer;
|
||||||
|
int err = vsf_read_file_by_path(filename, &file_buffer, root_dir);
|
||||||
|
if (err != 0) {
|
||||||
|
debug_log("execve: failed to read file '%s'\n", filename);
|
||||||
|
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);
|
||||||
|
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;
|
||||||
|
|
||||||
|
set_page_dir(new_page_dir_phys);
|
||||||
|
current->pagedir = new_page_dir;
|
||||||
|
|
||||||
|
void* kstack_phys = get_physaddr(current->kstack);
|
||||||
|
map_page(kstack_phys, current->kstack, PAGE_PRESENT | PAGE_RW);
|
||||||
|
|
||||||
|
uint32_t highest_vaddr = 0;
|
||||||
|
for (int i = 0; i < elf_header->e_phnum; i++) {
|
||||||
|
Elf32_Phdr *p_header = (Elf32_Phdr *)(file_buffer + elf_header->e_phoff + i * elf_header->e_phentsize);
|
||||||
|
if (p_header->p_type == PT_LOAD) {
|
||||||
|
for (uint32_t vaddr = p_header->p_vaddr; vaddr < p_header->p_vaddr + p_header->p_memsz; vaddr += PAGE_SIZE) {
|
||||||
|
void* phys_addr = alloc_page();
|
||||||
|
map_page(phys_addr, (void*)(vaddr & ~0xFFF), PAGE_PRESENT | PAGE_RW | PAGE_USER);
|
||||||
|
}
|
||||||
|
memcpy((void*)p_header->p_vaddr, file_buffer + p_header->p_offset, p_header->p_filesz);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t vaddr = USER_STACK_BOTTOM; vaddr <= USER_STACK_TOP; vaddr += PAGE_SIZE) {
|
||||||
|
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
|
||||||
|
|
||||||
|
current->brk = (void*)(DivRoundUp(highest_vaddr, PAGE_SIZE) * PAGE_SIZE);
|
||||||
|
free(file_buffer);
|
||||||
|
destroy_page_dir(old_page_dir_to_free);
|
||||||
|
|
||||||
|
tf->gs = SEG_UDATA | DPL_USER;
|
||||||
|
tf->fs = SEG_UDATA | DPL_USER;
|
||||||
|
tf->es = SEG_UDATA | DPL_USER;
|
||||||
|
tf->ds = SEG_UDATA | DPL_USER;
|
||||||
|
tf->eax = 0; tf->ecx = 0; tf->edx = 0; tf->ebx = 0;
|
||||||
|
tf->ebp = 0; tf->esi = 0; tf->edi = 0;
|
||||||
|
tf->eip = elf_header->e_entry;
|
||||||
|
tf->cs = SEG_UCODE | DPL_USER;
|
||||||
|
tf->eflags = FL_IF;
|
||||||
|
tf->usermode_esp = user_esp;
|
||||||
|
tf->usermode_ss = SEG_UDATA | DPL_USER;
|
||||||
|
|
||||||
|
execve_return(tf);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int sys_chdir(TrapFrame *tf)
|
int sys_chdir(TrapFrame *tf)
|
||||||
{
|
{
|
||||||
//strcat(current->cwd->fat->path, "/");
|
//strcat(current->cwd->fat->path, "/");
|
||||||
@@ -355,6 +438,10 @@ void handle_syscall(TrapFrame *tf)
|
|||||||
case 6://close
|
case 6://close
|
||||||
tf->eax = sys_close(tf);
|
tf->eax = sys_close(tf);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 11://execve
|
||||||
|
tf->eax = sys_execve(tf);
|
||||||
|
break;
|
||||||
|
|
||||||
case 12://chdir
|
case 12://chdir
|
||||||
tf->eax = sys_chdir(tf);
|
tf->eax = sys_chdir(tf);
|
||||||
|
|||||||
Reference in New Issue
Block a user