memory leak fix userspace

This commit is contained in:
boreddevnl 2026-03-12 19:15:09 +01:00
parent 8ba03fac72
commit d19075750b
6 changed files with 72 additions and 14 deletions

Binary file not shown.

Binary file not shown.

BIN
disk.img

Binary file not shown.

View file

@ -22,16 +22,10 @@ static void write_cr3(uint64_t cr3) {
// Helper to allocate a page table and clear it
static uint64_t alloc_page_table_phys(void) {
void* ptr = kmalloc(PAGE_SIZE * 2);
void *ptr = kmalloc_aligned(PAGE_SIZE, PAGE_SIZE);
if (!ptr) return 0;
// Align to PAGE_SIZE virtually
uintptr_t addr = (uintptr_t)ptr;
if (addr % PAGE_SIZE != 0) {
addr = (addr + PAGE_SIZE) & ~(PAGE_SIZE - 1);
}
page_table_t* table = (page_table_t*)addr;
page_table_t* table = (page_table_t*)ptr;
// Clear table
for (int i = 0; i < 512; i++) {
@ -120,3 +114,44 @@ uint64_t paging_create_user_pml4_phys(void) {
// The lower half (0-255) is left empty for the user process to use
return new_pml4_phys;
}
void paging_destroy_user_pml4_phys(uint64_t pml4_phys) {
if (!pml4_phys) return;
page_table_t* pml4 = (page_table_t*)p2v(pml4_phys);
// Only traverse lower half (user space, indices 0-255)
for (int pml4_idx = 0; pml4_idx < 256; pml4_idx++) {
if (pml4->entries[pml4_idx] & PT_PRESENT) {
page_table_t* pdpt = (page_table_t*)p2v(pml4->entries[pml4_idx] & PT_ADDR_MASK);
for (int pdpt_idx = 0; pdpt_idx < 512; pdpt_idx++) {
if (pdpt->entries[pdpt_idx] & PT_PRESENT) {
page_table_t* pd = (page_table_t*)p2v(pdpt->entries[pdpt_idx] & PT_ADDR_MASK);
for (int pd_idx = 0; pd_idx < 512; pd_idx++) {
if (pd->entries[pd_idx] & PT_PRESENT) {
page_table_t* pt = (page_table_t*)p2v(pd->entries[pd_idx] & PT_ADDR_MASK);
for (int pt_idx = 0; pt_idx < 512; pt_idx++) {
if (pt->entries[pt_idx] & PT_PRESENT) {
uint64_t phys_addr = pt->entries[pt_idx] & PT_ADDR_MASK;
extern void kfree(void* ptr);
kfree((void*)p2v(phys_addr));
}
}
extern void kfree(void* ptr);
kfree((void*)pt);
}
}
extern void kfree(void* ptr);
kfree((void*)pd);
}
}
extern void kfree(void* ptr);
kfree((void*)pdpt);
}
}
// Finally free the pml4 itself
extern void kfree(void* ptr);
kfree((void*)pml4);
}

View file

@ -27,19 +27,16 @@ typedef struct {
uint64_t entries[512];
} __attribute__((aligned(PAGE_SIZE))) page_table_t;
// Get the current PML4 physical address
uint64_t paging_get_pml4_phys(void);
// Map a physical address to a virtual address
void paging_map_page(uint64_t pml4_phys, uint64_t virtual_addr, uint64_t physical_addr, uint64_t flags);
// Create a new, isolated PML4 for a user process (returns physical address)
uint64_t paging_create_user_pml4_phys(void);
// Switch the active page table (takes physical address)
void paging_switch_directory(uint64_t pml4_phys);
// Initialize paging system (if needed beyond Limine's setup)
void paging_destroy_user_pml4_phys(uint64_t pml4_phys);
void paging_init(void);
#endif // PAGING_H

View file

@ -19,6 +19,7 @@ process_t processes[MAX_PROCESSES] __attribute__((aligned(16)));
int process_count = 0;
static process_t* current_process = NULL;
static uint32_t next_pid = 0;
static void *free_kernel_stack_later = NULL;
void process_init(void) {
for (int i = 0; i < MAX_PROCESSES; i++) {
@ -329,6 +330,11 @@ process_t* process_get_current(void) {
}
uint64_t process_schedule(uint64_t current_rsp) {
if (free_kernel_stack_later) {
kfree(free_kernel_stack_later);
free_kernel_stack_later = NULL;
}
if (!current_process || !current_process->next || current_process == current_process->next)
return current_rsp;
@ -433,9 +439,22 @@ void process_terminate(process_t *to_delete) {
to_delete->pid = 0xFFFFFFFF;
if (to_delete->user_stack_alloc) kfree(to_delete->user_stack_alloc);
if (to_delete->kernel_stack_alloc) kfree(to_delete->kernel_stack_alloc);
if (to_delete->kernel_stack_alloc) {
if (to_delete == current_process) {
free_kernel_stack_later = to_delete->kernel_stack_alloc;
} else {
kfree(to_delete->kernel_stack_alloc);
}
}
extern void paging_destroy_user_pml4_phys(uint64_t pml4_phys);
if (to_delete->pml4_phys && to_delete->is_user) {
paging_destroy_user_pml4_phys(to_delete->pml4_phys);
}
to_delete->user_stack_alloc = NULL;
to_delete->kernel_stack_alloc = NULL;
to_delete->pml4_phys = 0;
asm volatile("push %0; popfq" : : "r"(rflags));
}
@ -486,9 +505,16 @@ uint64_t process_terminate_current(void) {
// kernel stack is unsafe while we are still running on it.
if (to_delete->user_stack_alloc) kfree(to_delete->user_stack_alloc);
extern void paging_destroy_user_pml4_phys(uint64_t pml4_phys);
if (to_delete->pml4_phys && to_delete->is_user) {
paging_destroy_user_pml4_phys(to_delete->pml4_phys);
}
// Clear pointers to avoid double-free during slot reuse
to_delete->user_stack_alloc = NULL;
free_kernel_stack_later = to_delete->kernel_stack_alloc;
to_delete->kernel_stack_alloc = NULL; // Leak the small kernel stack for safety
to_delete->pml4_phys = 0;
uint64_t next_rsp = current_process->rsp;
asm volatile("push %0; popfq" : : "r"(rflags));