From: Tulio A M Mendes Date: Sun, 8 Feb 2026 03:01:39 +0000 (-0300) Subject: posix: tighten uaccess + errno helpers X-Git-Url: https://projects.tadryanom.me/?a=commitdiff_plain;h=159c1a447bcb02ddf00dbc34bf42a7a00595084b;p=AdrOS.git posix: tighten uaccess + errno helpers 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. --- diff --git a/src/kernel/syscall.c b/src/kernel/syscall.c index 9176f7a..510c7ab 100644 --- a/src/kernel/syscall.c +++ b/src/kernel/syscall.c @@ -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) { diff --git a/src/kernel/uaccess.c b/src/kernel/uaccess.c index ef6642f..d7b578f 100644 --- a/src/kernel/uaccess.c +++ b/src/kernel/uaccess.c @@ -1,5 +1,7 @@ #include "uaccess.h" +#include "errno.h" + #include #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++) {