From: Tulio A M Mendes Date: Sun, 8 Feb 2026 02:37:06 +0000 (-0300) Subject: fix: prevent fork clone stack overflow X-Git-Url: https://projects.tadryanom.me/?a=commitdiff_plain;h=29dbb2e0a19cdb500103e3ccc8ee60545a6e5fd3;p=AdrOS.git 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. --- diff --git a/src/arch/x86/vmm.c b/src/arch/x86/vmm.c index ec75821c..3dc78770 100644 --- a/src/arch/x86/vmm.c +++ b/src/arch/x86/vmm.c @@ -9,6 +9,7 @@ #include "vmm.h" #include "pmm.h" +#include "heap.h" #include "uart_console.h" #include "utils.h" #include "hal/cpu.h" @@ -122,6 +123,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; @@ -157,18 +164,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 af4a210c..de38203c 100644 --- a/src/mm/heap.c +++ b/src/mm/heap.c @@ -12,6 +12,7 @@ #include "pmm.h" #include "vmm.h" #include "spinlock.h" +#include "utils.h" #include "hal/cpu.h" #include #include @@ -102,6 +103,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(); } @@ -153,11 +163,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; @@ -172,6 +200,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;