From 6e4cd6300da32545ec755ec5d8d1c19bee1a70f5 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 11 Jan 2023 19:25:28 +0100 Subject: [PATCH] Kernel: Add copy_from_user() and copy_from_user_typed() --- kernel/src/memory/MemoryManager.cpp | 29 ++++++++++++++++++++++++++++- kernel/src/memory/MemoryManager.h | 7 +++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index 28e155bd..4e39e146 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -438,7 +438,6 @@ namespace MemoryManager // Userspace pointer not aligned on page boundary if (user_ptr != user_page) { - // FIXME: Validate that this page is writable by the user, not just the kernel. if (!validate_user_writable_page(user_page)) return false; } @@ -457,6 +456,34 @@ namespace MemoryManager return true; } + bool copy_from_user(const void* user, void* kernel, usize size) + { + uintptr_t user_ptr = (uintptr_t)user; + uintptr_t user_page = align_down(user_ptr); + + char* kernel_ptr = (char*)kernel; + + // Userspace pointer not aligned on page boundary + if (user_ptr != user_page) + { + if (!validate_user_writable_page(user_page)) return false; + } + + while (size--) + { + // Crossed a page boundary, gotta check the page tables again before touching any memory!! + if (user_ptr % ARCH_PAGE_SIZE) + { + if (!validate_user_writable_page(user_ptr)) return false; + } + + *kernel_ptr++ = *(char*)user_ptr; + user_ptr++; + } + + return true; + } + usize free() { return free_mem; diff --git a/kernel/src/memory/MemoryManager.h b/kernel/src/memory/MemoryManager.h index 76bcf9e4..8f2b9bbc 100644 --- a/kernel/src/memory/MemoryManager.h +++ b/kernel/src/memory/MemoryManager.h @@ -45,6 +45,13 @@ namespace MemoryManager return copy_to_user(user, kernel, sizeof(T)); } + bool copy_from_user(const void* user, void* kernel, usize size); + + template bool copy_from_user_typed(const T* user, T* kernel) + { + return copy_from_user(user, kernel, sizeof(T)); + } + Result map_frames_at(u64 virt, u64 phys, usize count, int flags); Result alloc_at(u64 virt, usize count, int flags);