]> Projects (at) Tadryanom (dot) Me - AdrOS.git/commitdiff
fix: prevent fork clone stack overflow
authorTulio A M Mendes <[email protected]>
Sun, 8 Feb 2026 02:37:06 +0000 (23:37 -0300)
committerTulio A M Mendes <[email protected]>
Sun, 8 Feb 2026 02:37:06 +0000 (23:37 -0300)
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
src/mm/heap.c

index 3aa1590e0c2ec790c8dde5bf772a75e7f8723408..ba8b73681af75e58ba7e933c2d964c0becb5c9cd 100644 (file)
@@ -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;
 }
 
index d958e9bf4e4cc01b42155045d68940fc356d0bb9..61208ea09a28553e9ff780aff9e1a6b38c71bba1 100644 (file)
@@ -3,6 +3,7 @@
 #include "pmm.h"
 #include "vmm.h"
 #include "spinlock.h"
+#include "utils.h"
 #include "hal/cpu.h"
 #include <stddef.h>
 #include <stdint.h>
@@ -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;