[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Lost] [Patch] kernel2: Userspace-Stackoverflows abfangen



+ kernel2: Userspace-Stackoverflows abfangen und Stack vergroessern
! kernel2: increase_user_stack_size sollte auch mit dem Userstack und nicht 
mit dem Kernelstack arbeiten
Index: trunk/src/kernel2/src/interrupts/im.c
===================================================================
--- trunk.orig/src/kernel2/src/interrupts/im.c
+++ trunk/src/kernel2/src/interrupts/im.c
@@ -57,6 +57,59 @@ void im_send_interrupts(void);
 bool fastrpc_irq(pm_process_t* callee, size_t metadata_size, void* metadata,
     size_t data_size, void* data, uint8_t irq);
 
+extern void increase_user_stack_size(pm_thread_t* task_ptr, int pages);
+
+/**
+ * Verarbeitet eine CPU-Exception
+ */
+static void handle_exception(interrupt_stack_frame_t* isf, uint8_t int_num)
+{
+    uintptr_t cr2;
+    asm("mov %%cr2, %0" : "=r" (cr2));
+
+//    kprintf("user_stack_bottom = %x\n",
+//        cpu_get_current()->thread->user_stack_bottom);
+
+    if (int_num == 0x0e) {
+        // Ueberprüfen ob der Pagefault durch einen Stackoverflow
+        // hervorgerufen wurde. Falls ja: Stack vergroessern und weitermachen
+        if ((cr2 <= isf->esp + 0x800) && (cr2 >= isf->esp - 0x20)
+            && (cpu_get_current()->thread != NULL)
+            && ((void*) cr2 >= cpu_get_current()->thread->user_stack_bottom - 0x1000000)
+            && ((void*) cr2 <  cpu_get_current()->thread->user_stack_bottom))
+        {
+            increase_user_stack_size(cpu_get_current()->thread, 1);
+            return;
+        }
+    }
+
+    // Exception
+    kprintf("\033[1;41m");
+    kprintf("[CPU%d] Exception %d; Error Code = 0x%x\n",
+        cpu_get_current()->id, int_num, isf->error_code);
+
+    kprintf("PID %d: %s\n",
+        cpu_get_current()->thread->process->pid,
+        cpu_get_current()->thread->process->cmdline);
+    cpu_dump(isf);
+    kprintf("\033[0;40m");
+
+    // Ein Stacktrace duerfen wir nur ausgeben, wenn kein Pagefault wegen
+    // dem Stack aufgetreten ist!
+    if (!((cr2 < isf->esp + 800) && (cr2 >= isf->esp -0x20))) {
+        stack_backtrace(isf->ebp, isf->eip);
+    }
+
+    // Hier werden alle Prozessoren zum halten gebracht
+    if (cpu_count > 1) {
+        apic_ipi_broadcast(0xF0, TRUE);
+    }
+
+    // Aber da das ohne APIC nicht so funktioniert, wird das noch
+    // abgefangen.
+    asm("cli; hlt");
+}
+
 /**
  * Behandelt alle Interrupts. Wird aus den Interrupt-Stubs aufgerufen.
  * 
@@ -71,34 +124,7 @@ interrupt_stack_frame_t* im_handler(inte
     byte int_num = isf->interrupt_number;
     
     if (int_num < 20) {
-        asm("cli");
-        // Exception
-        kprintf("\033[1;41m");
-        kprintf("[CPU%d] Exception %d; Error Code = 0x%x\n", 
-            cpu_get_current()->id, int_num, isf->error_code);
-
-        kprintf("PID %d: %s\n",
-            cpu_get_current()->thread->process->pid,
-            cpu_get_current()->thread->process->cmdline);
-        cpu_dump(isf);
-        kprintf("\033[0;40m");
-
-        // Ein Stacktrace duerfen wir nur ausgeben, wenn kein Pagefault wegen
-        // dem Stack aufgetreten ist!
-        uintptr_t cr2;
-        asm("mov %%cr2, %0" : "=r" (cr2));
-        if (!((cr2 < isf->esp + 800) && (cr2 >= isf->esp -0x20))) {
-            stack_backtrace(isf->ebp, isf->eip);
-        }
-
-        // Hier werden alle Prozessoren zum halten gebracht
-        if (cpu_count > 1) {
-            apic_ipi_broadcast(0xF0, TRUE);
-        }
-
-        // Aber da das ohne APIC nicht so funktioniert, wird das noch
-        // abgefangen.
-        asm("cli; hlt");
+        handle_exception(isf, int_num);
     } else if ((int_num >= 20) && (int_num < 32)){
         // Reservierter Interrupt
         kprintf("Reserved Interrupt %d\n", int_num);
Index: trunk/src/kernel2/include/tasks.h
===================================================================
--- trunk.orig/src/kernel2/include/tasks.h
+++ trunk/src/kernel2/include/tasks.h
@@ -101,6 +101,9 @@ typedef struct {
     /// Groesse des Kernelstacks
     size_t kernel_stack_size;
 
+    /// Anfang des Usermode-Stacks
+    vaddr_t user_stack_bottom;
+
     /// Der Prozess, dem der Thread gehoert
     pm_process_t* process;
 
Index: trunk/src/kernel2/src/arch/i386/mm/virt.c
===================================================================
--- trunk.orig/src/kernel2/src/arch/i386/mm/virt.c
+++ trunk/src/kernel2/src/arch/i386/mm/virt.c
@@ -158,9 +158,9 @@ void increase_user_stack_size(pm_thread_
 	int i;
 	for(i = 0; i < pages; i++)
 	{
-		thread->kernel_stack_bottom -= PAGE_SIZE;
+		thread->user_stack_bottom -= PAGE_SIZE;
 		if(mmc_resolve(&thread->process->context,
-            (vaddr_t) thread->kernel_stack_bottom) != NULL)
+            (vaddr_t) thread->user_stack_bottom) != NULL)
 		{
             /*
 			kprintf("\n"
@@ -172,7 +172,7 @@ void increase_user_stack_size(pm_thread_
 		}
 
         mmc_map(&thread->process->context,
-            thread->kernel_stack_bottom,
+            thread->user_stack_bottom,
             pmm_alloc(1), MM_FLAGS_USER_DATA, 1);
 	}
 }
Index: trunk/src/kernel2/src/tasks/thread.c
===================================================================
--- trunk.orig/src/kernel2/src/tasks/thread.c
+++ trunk/src/kernel2/src/tasks/thread.c
@@ -106,9 +106,12 @@ pm_thread_t* pm_thread_create(pm_process
     
     // Page fuer den Userspace-Stack allozieren
     paddr_t stack_phys = pmm_alloc(NUM_PAGES(USER_STACK_SIZE));
-    mmc_map(&process->context, (vaddr_t) (isf->esp - USER_STACK_SIZE),
+
+    thread->user_stack_bottom = (vaddr_t) (isf->esp - USER_STACK_SIZE);
+    mmc_map(&process->context, thread->user_stack_bottom,
         stack_phys, MM_FLAGS_USER_DATA, NUM_PAGES(USER_STACK_SIZE));
 
+
     // Thread in die Liste aufnehmen, und beim Scheduler regisrieren
     list_push(process->threads, thread);