]> Projects (at) Tadryanom (dot) Me - AdrOS.git/commitdiff
posix: tighten uaccess + errno helpers
authorTulio A M Mendes <[email protected]>
Sun, 8 Feb 2026 03:01:39 +0000 (00:01 -0300)
committerTulio A M Mendes <[email protected]>
Sun, 8 Feb 2026 03:01:39 +0000 (00:01 -0300)
Return proper -errno from remaining syscall helpers (pipe/fd allocation) and harden copy_to_user to require writable user mappings on x86. copy_{to,from}_user now return -EFAULT on invalid ranges.

src/kernel/syscall.c
src/kernel/uaccess.c

index 9176f7ad1849e1c4170f1c119e15158c20d1a607..510c7abf410c63829e1a81df478bbca5b44db7b0 100644 (file)
@@ -151,9 +151,9 @@ static void pipe_close(fs_node_t* n) {
 }
 
 static int pipe_node_create(struct pipe_state* ps, int is_read_end, fs_node_t** out_node) {
-    if (!ps || !out_node) return -1;
+    if (!ps || !out_node) return -EINVAL;
     struct pipe_node* pn = (struct pipe_node*)kmalloc(sizeof(*pn));
-    if (!pn) return -1;
+    if (!pn) return -ENOMEM;
     memset(pn, 0, sizeof(*pn));
 
     pn->ps = ps;
@@ -264,9 +264,9 @@ static int stat_from_node(const fs_node_t* node, struct stat* st) {
 }
 
 static int fd_alloc_from(int start_fd, struct file* f) {
-    if (!current_process || !f) return -1;
+    if (!current_process || !f) return -EINVAL;
     if (start_fd < 0) start_fd = 0;
-    if (start_fd >= PROCESS_MAX_FILES) return -1;
+    if (start_fd >= PROCESS_MAX_FILES) return -EINVAL;
 
     for (int fd = start_fd; fd < PROCESS_MAX_FILES; fd++) {
         if (current_process->files[fd] == NULL) {
@@ -274,11 +274,11 @@ static int fd_alloc_from(int start_fd, struct file* f) {
             return fd;
         }
     }
-    return -1;
+    return -EMFILE;
 }
 
 static int fd_alloc(struct file* f) {
-    if (!current_process || !f) return -1;
+    if (!current_process || !f) return -EINVAL;
 
     for (int fd = 3; fd < PROCESS_MAX_FILES; fd++) {
         if (current_process->files[fd] == NULL) {
@@ -286,7 +286,7 @@ static int fd_alloc(struct file* f) {
             return fd;
         }
     }
-    return -1;
+    return -EMFILE;
 }
 
 static struct file* fd_get(int fd) {
index ef6642fe0ff9c2bb51f0ed6e995fe1a8fa6c7563..d7b578ffd47b696665f18bae4602aa9b4b5f6025 100644 (file)
@@ -1,5 +1,7 @@
 #include "uaccess.h"
 
+#include "errno.h"
+
 #include <stdint.h>
 
 #if defined(__i386__)
@@ -15,6 +17,22 @@ static int x86_user_range_basic_ok(uintptr_t uaddr, size_t len) {
     return 1;
 }
 
+static int x86_user_page_writable_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;
+    if (!(pte & 0x2)) 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;
@@ -43,6 +61,19 @@ static int x86_user_range_mapped_and_user(uintptr_t uaddr, size_t len) {
     }
     return 1;
 }
+
+static int x86_user_range_writable_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_writable_user(va)) return 0;
+        if (va == end) break;
+    }
+    return 1;
+}
 #endif
 
 int user_range_ok(const void* user_ptr, size_t len) {
@@ -61,7 +92,7 @@ int user_range_ok(const void* user_ptr, size_t len) {
 
 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;
+    if (!user_range_ok(src_user, len)) return -EFAULT;
 
     uintptr_t up = (uintptr_t)src_user;
     for (size_t i = 0; i < len; i++) {
@@ -72,7 +103,12 @@ 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) {
     if (len == 0) return 0;
-    if (!user_range_ok(dst_user, len)) return -1;
+
+#if defined(__i386__)
+    if (!x86_user_range_writable_user((uintptr_t)dst_user, len)) return -EFAULT;
+#else
+    if (!user_range_ok(dst_user, len)) return -EFAULT;
+#endif
 
     uintptr_t up = (uintptr_t)dst_user;
     for (size_t i = 0; i < len; i++) {