]> Projects (at) Tadryanom (dot) Me - AdrOS.git/commitdiff
feat: ASLR — TSC-seeded xorshift32 PRNG randomizes user stack base by up to 1MB per...
authorTulio A M Mendes <[email protected]>
Thu, 12 Feb 2026 04:47:34 +0000 (01:47 -0300)
committerTulio A M Mendes <[email protected]>
Fri, 13 Feb 2026 02:44:55 +0000 (23:44 -0300)
include/kaslr.h [new file with mode: 0644]
src/arch/x86/elf.c
src/kernel/kaslr.c [new file with mode: 0644]
src/kernel/main.c

diff --git a/include/kaslr.h b/include/kaslr.h
new file mode 100644 (file)
index 0000000..db2a470
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef KASLR_H
+#define KASLR_H
+
+#include <stdint.h>
+
+void kaslr_init(void);
+uint32_t kaslr_rand(void);
+
+/* Returns a page-aligned random offset in [0, max_pages * PAGE_SIZE). */
+uint32_t kaslr_offset(uint32_t max_pages);
+
+#endif
index 9eacc646a3b16012c89eaccdd626592c545681d6..c6972d638c2b87e1b0d12ccdafd3b127c2f6917b 100644 (file)
@@ -278,9 +278,12 @@ int elf32_load_user_from_initrd(const char* filename, uintptr_t* entry_out, uint
     (void)has_interp;
 
     /* 32 KB user stack with a 4 KB guard page below (unmapped).
-     * Guard page at 0x007FF000 is left unmapped so stack overflow
-     * triggers a page fault → SIGSEGV instead of silent corruption. */
-    const uintptr_t user_stack_base = 0x00800000U;
+     * Guard page at stack_base - 0x1000 is left unmapped so stack overflow
+     * triggers a page fault → SIGSEGV instead of silent corruption.
+     * ASLR: randomize stack base by up to 256 pages (1 MB). */
+    extern uint32_t kaslr_offset(uint32_t max_pages);
+    const uintptr_t aslr_stack_slide = kaslr_offset(256);
+    const uintptr_t user_stack_base = 0x00800000U + aslr_stack_slide;
     const size_t user_stack_size = 0x8000;       /* 8 pages = 32 KB */
 
     int src2 = elf32_map_user_range(new_as, user_stack_base, user_stack_size, VMM_FLAG_RW);
diff --git a/src/kernel/kaslr.c b/src/kernel/kaslr.c
new file mode 100644 (file)
index 0000000..86f65fd
--- /dev/null
@@ -0,0 +1,32 @@
+#include "kaslr.h"
+#include "uart_console.h"
+
+static uint32_t prng_state;
+
+static inline uint64_t rdtsc(void) {
+    uint32_t lo, hi;
+    __asm__ volatile("rdtsc" : "=a"(lo), "=d"(hi));
+    return ((uint64_t)hi << 32) | lo;
+}
+
+void kaslr_init(void) {
+    uint64_t tsc = rdtsc();
+    prng_state = (uint32_t)(tsc ^ (tsc >> 32));
+    if (prng_state == 0) prng_state = 0xDEADBEEF;
+    uart_print("[KASLR] PRNG seeded from TSC\n");
+}
+
+uint32_t kaslr_rand(void) {
+    /* xorshift32 */
+    uint32_t x = prng_state;
+    x ^= x << 13;
+    x ^= x >> 17;
+    x ^= x << 5;
+    prng_state = x;
+    return x;
+}
+
+uint32_t kaslr_offset(uint32_t max_pages) {
+    if (max_pages == 0) return 0;
+    return (kaslr_rand() % max_pages) * 0x1000U;
+}
index b0f5dd0ba6492456a44e7a6fd069ca2f9966a318..2950c40ab0e73335fb7fafba3f318f7edf44a2f0 100644 (file)
@@ -59,6 +59,12 @@ void kernel_main(const struct boot_info* bi) {
     // 5. Initialize Shared Memory IPC
     shm_init();
     
+    // 6b. Initialize KASLR PRNG
+    {
+        extern void kaslr_init(void);
+        kaslr_init();
+    }
+
     // 7. Initialize Multitasking
     kprintf("[AdrOS] Initializing Scheduler...\n");
     process_init();