]> Projects (at) Tadryanom (dot) Me - AdrOS.git/commitdiff
kernel: centralize user pointer access (uaccess)
authorTulio A M Mendes <[email protected]>
Fri, 6 Feb 2026 14:08:03 +0000 (11:08 -0300)
committerTulio A M Mendes <[email protected]>
Fri, 6 Feb 2026 14:08:03 +0000 (11:08 -0300)
Makefile
include/uaccess.h [new file with mode: 0644]
src/kernel/syscall.c
src/kernel/uaccess.c [new file with mode: 0644]

index 2a2f7a7d5c1323abc00264fe76506695411a713b..878c26d761d818a2d9f0f0167fcf059e28d450d7 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -104,7 +104,7 @@ run: iso
        @rm -f serial.log qemu.log
        @qemu-system-i386 -boot d -cdrom adros-$(ARCH).iso -m 128M -display none \
                -serial file:serial.log -monitor none -no-reboot -no-shutdown \
-               -d int,cpu_reset,guest_errors -D qemu.log
+               $(if $(QEMU_DEBUG),-d guest_errors -D qemu.log,)
 
 $(BUILD_DIR)/%.o: $(SRC_DIR)/%.c
        @mkdir -p $(dir $@)
diff --git a/include/uaccess.h b/include/uaccess.h
new file mode 100644 (file)
index 0000000..99016dd
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef UACCESS_H
+#define UACCESS_H
+
+#include <stddef.h>
+
+int user_range_ok(const void* user_ptr, size_t len);
+int copy_from_user(void* dst, const void* src_user, size_t len);
+int copy_to_user(void* dst_user, const void* src, size_t len);
+
+#endif
index 61ba78b5c4496ebdd5ad14330c0d1776bc884d1a..4d094fefb68d030a2cdeb3d40a26b9714dd37ef3 100644 (file)
@@ -1,52 +1,10 @@
 #include "syscall.h"
 #include "idt.h"
 #include "uart_console.h"
+#include "uaccess.h"
 
 #include <stddef.h>
 
-#if defined(__i386__)
-#define X86_KERNEL_VIRT_BASE 0xC0000000U
-
-static int x86_user_range_basic_ok(uintptr_t uaddr, size_t len) {
-    if (len == 0) return 1;
-    if (uaddr == 0) return 0;
-    if (uaddr >= X86_KERNEL_VIRT_BASE) return 0;
-    uintptr_t end = uaddr + len - 1;
-    if (end < uaddr) return 0;
-    if (end >= X86_KERNEL_VIRT_BASE) return 0;
-    return 1;
-}
-
-static int x86_user_page_present_and_user(uintptr_t vaddr) {
-    volatile uint32_t* pd = (volatile uint32_t*)0xFFFFF000U;
-    volatile uint32_t* pt_base = (volatile uint32_t*)0xFFC00000U;
-
-    uint32_t pde = pd[vaddr >> 22];
-    if (!(pde & 0x1)) return 0;
-    if (!(pde & 0x4)) return 0;
-
-    volatile uint32_t* pt = pt_base + ((vaddr >> 22) << 10);
-    uint32_t pte = pt[(vaddr >> 12) & 0x3FF];
-    if (!(pte & 0x1)) return 0;
-    if (!(pte & 0x4)) return 0;
-
-    return 1;
-}
-
-static int x86_user_range_mapped_and_user(uintptr_t uaddr, size_t len) {
-    if (!x86_user_range_basic_ok(uaddr, len)) return 0;
-    if (len == 0) return 1;
-
-    uintptr_t start = uaddr & ~(uintptr_t)0xFFF;
-    uintptr_t end = (uaddr + len - 1) & ~(uintptr_t)0xFFF;
-    for (uintptr_t va = start;; va += 0x1000) {
-        if (!x86_user_page_present_and_user(va)) return 0;
-        if (va == end) break;
-    }
-    return 1;
-}
-#endif
-
 static void syscall_handler(struct registers* regs) {
     uint32_t syscall_no = regs->eax;
 
@@ -65,12 +23,10 @@ static void syscall_handler(struct registers* regs) {
             return;
         }
 
-#if defined(__i386__)
-        if (!x86_user_range_mapped_and_user((uintptr_t)buf, (size_t)len)) {
+        if (user_range_ok(buf, (size_t)len) == 0) {
             regs->eax = (uint32_t)-1;
             return;
         }
-#endif
 
         char kbuf[256];
         uint32_t remaining = len;
@@ -80,16 +36,10 @@ static void syscall_handler(struct registers* regs) {
             uint32_t chunk = remaining;
             if (chunk > sizeof(kbuf)) chunk = (uint32_t)sizeof(kbuf);
 
-#if defined(__i386__)
-            if (!x86_user_range_mapped_and_user(up, (size_t)chunk)) {
+            if (copy_from_user(kbuf, (const void*)up, (size_t)chunk) < 0) {
                 regs->eax = (uint32_t)-1;
                 return;
             }
-#endif
-
-            for (uint32_t i = 0; i < chunk; i++) {
-                kbuf[i] = ((const volatile char*)up)[i];
-            }
 
             for (uint32_t i = 0; i < chunk; i++) {
                 uart_put_char(kbuf[i]);
diff --git a/src/kernel/uaccess.c b/src/kernel/uaccess.c
new file mode 100644 (file)
index 0000000..ef6642f
--- /dev/null
@@ -0,0 +1,82 @@
+#include "uaccess.h"
+
+#include <stdint.h>
+
+#if defined(__i386__)
+#define X86_KERNEL_VIRT_BASE 0xC0000000U
+
+static int x86_user_range_basic_ok(uintptr_t uaddr, size_t len) {
+    if (len == 0) return 1;
+    if (uaddr == 0) return 0;
+    if (uaddr >= X86_KERNEL_VIRT_BASE) return 0;
+    uintptr_t end = uaddr + len - 1;
+    if (end < uaddr) return 0;
+    if (end >= X86_KERNEL_VIRT_BASE) return 0;
+    return 1;
+}
+
+static int x86_user_page_present_and_user(uintptr_t vaddr) {
+    volatile uint32_t* pd = (volatile uint32_t*)0xFFFFF000U;
+    volatile uint32_t* pt_base = (volatile uint32_t*)0xFFC00000U;
+
+    uint32_t pde = pd[vaddr >> 22];
+    if (!(pde & 0x1)) return 0;
+    if (!(pde & 0x4)) return 0;
+
+    volatile uint32_t* pt = pt_base + ((vaddr >> 22) << 10);
+    uint32_t pte = pt[(vaddr >> 12) & 0x3FF];
+    if (!(pte & 0x1)) return 0;
+    if (!(pte & 0x4)) return 0;
+
+    return 1;
+}
+
+static int x86_user_range_mapped_and_user(uintptr_t uaddr, size_t len) {
+    if (!x86_user_range_basic_ok(uaddr, len)) return 0;
+    if (len == 0) return 1;
+
+    uintptr_t start = uaddr & ~(uintptr_t)0xFFF;
+    uintptr_t end = (uaddr + len - 1) & ~(uintptr_t)0xFFF;
+    for (uintptr_t va = start;; va += 0x1000) {
+        if (!x86_user_page_present_and_user(va)) return 0;
+        if (va == end) break;
+    }
+    return 1;
+}
+#endif
+
+int user_range_ok(const void* user_ptr, size_t len) {
+    uintptr_t uaddr = (uintptr_t)user_ptr;
+
+#if defined(__i386__)
+    return x86_user_range_mapped_and_user(uaddr, len);
+#else
+    if (len == 0) return 1;
+    if (uaddr == 0) return 0;
+    uintptr_t end = uaddr + len - 1;
+    if (end < uaddr) return 0;
+    return 1;
+#endif
+}
+
+int copy_from_user(void* dst, const void* src_user, size_t len) {
+    if (len == 0) return 0;
+    if (!user_range_ok(src_user, len)) return -1;
+
+    uintptr_t up = (uintptr_t)src_user;
+    for (size_t i = 0; i < len; i++) {
+        ((uint8_t*)dst)[i] = ((const volatile uint8_t*)up)[i];
+    }
+    return 0;
+}
+
+int copy_to_user(void* dst_user, const void* src, size_t len) {
+    if (len == 0) return 0;
+    if (!user_range_ok(dst_user, len)) return -1;
+
+    uintptr_t up = (uintptr_t)dst_user;
+    for (size_t i = 0; i < len; i++) {
+        ((volatile uint8_t*)up)[i] = ((const uint8_t*)src)[i];
+    }
+    return 0;
+}