From d67c911af6815255e7155e8934236223ba59853a Mon Sep 17 00:00:00 2001 From: Tulio A M Mendes Date: Sat, 7 Feb 2026 23:37:06 -0300 Subject: [PATCH] fix: prevent fork clone stack overflow Fix vmm_as_clone_user to use a heap-allocated 4KB temp buffer instead of a 4KB stack array (kernel stacks are 4KB). Harden heap free/coalesce logic and diagnostics to better catch corruption/double-free. --- src/arch/x86/vmm.c | 13 ++++++++++--- src/mm/heap.c | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/arch/x86/vmm.c b/src/arch/x86/vmm.c index 3aa1590..ba8b736 100644 --- a/src/arch/x86/vmm.c +++ b/src/arch/x86/vmm.c @@ -1,5 +1,6 @@ #include "vmm.h" #include "pmm.h" +#include "heap.h" #include "uart_console.h" #include "utils.h" #include "hal/cpu.h" @@ -113,6 +114,12 @@ uintptr_t vmm_as_clone_user(uintptr_t src_as) { uintptr_t new_as = vmm_as_create_kernel_clone(); if (!new_as) return 0; + uint8_t* tmp = (uint8_t*)kmalloc(4096); + if (!tmp) { + vmm_as_destroy(new_as); + return 0; + } + uint32_t* src_pd = (uint32_t*)P2V((uint32_t)src_as); const uint32_t* const boot_pd_virt = boot_pd; @@ -148,18 +155,18 @@ uintptr_t vmm_as_clone_user(uintptr_t src_as) { // Copy contents by temporarily switching address spaces. uintptr_t old_as = hal_cpu_get_address_space(); - uint8_t tmp[4096]; vmm_as_activate(src_as); - memcpy(tmp, (const void*)va, sizeof(tmp)); + memcpy(tmp, (const void*)va, 4096); vmm_as_activate(new_as); - memcpy((void*)va, tmp, sizeof(tmp)); + memcpy((void*)va, tmp, 4096); vmm_as_activate(old_as); } } + kfree(tmp); return new_as; } diff --git a/src/mm/heap.c b/src/mm/heap.c index d958e9b..61208ea 100644 --- a/src/mm/heap.c +++ b/src/mm/heap.c @@ -3,6 +3,7 @@ #include "pmm.h" #include "vmm.h" #include "spinlock.h" +#include "utils.h" #include "hal/cpu.h" #include #include @@ -93,6 +94,15 @@ void* kmalloc(size_t size) { if (current->magic != HEAP_MAGIC) { spin_unlock_irqrestore(&heap_lock, flags); uart_print("[HEAP] Corruption Detected in kmalloc scan!\n"); + char a[11]; + char m[11]; + itoa_hex((uint32_t)(uintptr_t)current, a); + itoa_hex((uint32_t)current->magic, m); + uart_print("[HEAP] header="); + uart_print(a); + uart_print(" magic="); + uart_print(m); + uart_print("\n"); for(;;) hal_cpu_idle(); } @@ -144,11 +154,29 @@ void kfree(void* ptr) { for(;;) hal_cpu_idle(); } + if (header->is_free) { + spin_unlock_irqrestore(&heap_lock, flags); + uart_print("[HEAP] Double free detected!\n"); + char a[11]; + itoa_hex((uint32_t)(uintptr_t)header, a); + uart_print("[HEAP] header="); + uart_print(a); + uart_print("\n"); + for(;;) hal_cpu_idle(); + } + header->is_free = 1; // 1. Coalesce Right (Forward) if (header->next && header->next->is_free) { heap_header_t* next_block = header->next; + + // Only coalesce if physically adjacent. + heap_header_t* expected_next = (heap_header_t*)((uint8_t*)header + sizeof(heap_header_t) + header->size); + if (next_block != expected_next) { + spin_unlock_irqrestore(&heap_lock, flags); + return; + } header->size += sizeof(heap_header_t) + next_block->size; header->next = next_block->next; @@ -163,6 +191,13 @@ void kfree(void* ptr) { // 2. Coalesce Left (Backward) - The Power of Double Links! if (header->prev && header->prev->is_free) { heap_header_t* prev_block = header->prev; + + // Only coalesce if physically adjacent. + heap_header_t* expected_hdr = (heap_header_t*)((uint8_t*)prev_block + sizeof(heap_header_t) + prev_block->size); + if (expected_hdr != header) { + spin_unlock_irqrestore(&heap_lock, flags); + return; + } prev_block->size += sizeof(heap_header_t) + header->size; prev_block->next = header->next; -- 2.43.0