From b25e21288090cd42dc5dc47d730d18f2f6ee61ef Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 7 May 2023 21:37:01 +0200 Subject: [PATCH] kernel: Make a generic function for checking memory flags --- kernel/src/arch/x86_64/CPU.cpp | 4 +- kernel/src/memory/MemoryManager.cpp | 87 ++++++++--------------------- kernel/src/memory/MemoryManager.h | 22 +++++--- 3 files changed, 38 insertions(+), 75 deletions(-) diff --git a/kernel/src/arch/x86_64/CPU.cpp b/kernel/src/arch/x86_64/CPU.cpp index 19901b5e..0b02c78e 100644 --- a/kernel/src/arch/x86_64/CPU.cpp +++ b/kernel/src/arch/x86_64/CPU.cpp @@ -276,8 +276,8 @@ namespace CPU static void backtrace_impl(u64 base_pointer, void (*callback)(u64, void*), void* arg) { StackFrame* current_frame = (StackFrame*)base_pointer; - // FIXME: Validate that the frame itself is readable, might span across multiple pages - while (current_frame && MemoryManager::validate_readable_page((u64)current_frame) && current_frame->instruction) + while (current_frame && MemoryManager::validate_access(current_frame, sizeof(*current_frame), 0) && + current_frame->instruction) { callback(current_frame->instruction, arg); current_frame = current_frame->next; diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index 8017277c..4c165120 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -396,57 +396,25 @@ namespace MemoryManager return {}; } - bool validate_readable_page(u64 address) + bool validate_page_default_access(u64 address) { auto rc = MMU::get_flags(address); if (rc.has_error()) return false; return true; } - bool validate_writable_page(u64 address) + bool validate_page_access(u64 address, int flags) { auto rc = MMU::get_flags(address); if (rc.has_error()) return false; - if (rc.value() & MMU::ReadWrite) return true; + if (rc.value() & flags) return true; return false; } - bool validate_user_readable_page(u64 address) - { - auto rc = MMU::get_flags(address); - if (rc.has_error()) return false; - if (rc.value() & MMU::User) return true; - return false; - } - - bool validate_user_writable_page(u64 address) - { - auto rc = MMU::get_flags(address); - if (rc.has_error()) return false; - if ((rc.value() & MMU::User) && (rc.value() && MMU::ReadWrite)) return true; - return false; - } - - bool validate_userspace_string(u64 address) - { - if (!validate_user_readable_page(address)) return false; - - while (*(char*)address != 0) - { - address++; - if (address % ARCH_PAGE_SIZE) - { - if (!validate_user_readable_page(address)) return false; - } - } - - return true; - } - // FIXME: Make this more efficient. Result strdup_from_user(u64 address) { - if (!validate_user_readable_page(address)) return err(EFAULT); + if (!validate_page_access(address, MMU::User)) return err(EFAULT); Vector result; @@ -456,7 +424,7 @@ namespace MemoryManager address++; if (address % ARCH_PAGE_SIZE) { - if (!validate_user_readable_page(address)) return err(EFAULT); + if (!validate_page_access(address, MMU::User)) return err(EFAULT); } } @@ -465,37 +433,26 @@ namespace MemoryManager return String::from_cstring(result.data()); } - bool validate_user_write(void* user, usize size) + bool validate_access(void* mem, usize size, int flags) { - uintptr_t user_ptr = (uintptr_t)user; - uintptr_t user_page = align_down(user_ptr); + uintptr_t address = (uintptr_t)mem; + uintptr_t page = align_down(address); - uintptr_t diff = user_ptr - user_page; + uintptr_t diff = address - page; usize pages = get_blocks_from_size(size + diff, ARCH_PAGE_SIZE); while (pages--) { - if (!validate_user_writable_page(user_page)) return false; - user_page += ARCH_PAGE_SIZE; - } - - return true; - } - - bool validate_user_read(const void* user, usize size) - { - uintptr_t user_ptr = (uintptr_t)user; - uintptr_t user_page = align_down(user_ptr); - - uintptr_t diff = user_ptr - user_page; - - usize pages = get_blocks_from_size(size + diff, ARCH_PAGE_SIZE); - - while (pages--) - { - if (!validate_user_readable_page(user_page)) return false; - user_page += ARCH_PAGE_SIZE; + if (flags > 0) + { + if (!validate_page_access(page, flags)) return false; + } + else + { + if (!validate_page_default_access(page)) return false; + } + page += ARCH_PAGE_SIZE; } return true; @@ -513,7 +470,7 @@ namespace MemoryManager // Userspace pointer not aligned on page boundary if (user_ptr != user_page) { - if (!validate_user_writable_page(user_page)) return false; + if (!validate_page_access(user_page, MMU::ReadWrite | MMU::User)) return false; } while (size--) @@ -521,7 +478,7 @@ namespace MemoryManager // 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; + if (!validate_page_access(user_ptr, MMU::ReadWrite | MMU::User)) return false; } *(u8*)user_ptr = *kernel_ptr++; @@ -541,7 +498,7 @@ namespace MemoryManager // Userspace pointer not aligned on page boundary if (user_ptr != user_page) { - if (!validate_user_readable_page(user_page)) return false; + if (!validate_page_access(user_page, MMU::User)) return false; } while (size--) @@ -549,7 +506,7 @@ namespace MemoryManager // Crossed a page boundary, gotta check the page tables again before touching any memory!! if (user_ptr % ARCH_PAGE_SIZE) { - if (!validate_user_readable_page(user_ptr)) return false; + if (!validate_page_access(user_ptr, MMU::User)) return false; } *kernel_ptr++ = *(const u8*)user_ptr; diff --git a/kernel/src/memory/MemoryManager.h b/kernel/src/memory/MemoryManager.h index 673f4e1c..14201d70 100644 --- a/kernel/src/memory/MemoryManager.h +++ b/kernel/src/memory/MemoryManager.h @@ -1,4 +1,5 @@ #pragma once +#include "arch/MMU.h" #include #include #include @@ -19,17 +20,22 @@ namespace MemoryManager Result remap(u64 address, usize count, int flags); Result remap_unaligned(u64 address, usize count, int flags); - bool validate_readable_page(u64 address); - bool validate_writable_page(u64 address); + bool validate_page_access(u64 address, int flags); + bool validate_page_default_access(u64 address); - bool validate_user_readable_page(u64 address); - bool validate_user_writable_page(u64 address); - - bool validate_userspace_string(u64 address); Result strdup_from_user(u64 address); - bool validate_user_write(void* user, usize size); - bool validate_user_read(const void* user, usize size); + bool validate_access(const void* mem, usize size, int flags); + + bool validate_user_write(void* user, usize size) + { + return validate_access(user, size, MMU::ReadWrite | MMU::User); + } + + bool validate_user_read(const void* user, usize size) + { + return validate_access(user, size, MMU::User); + } template bool validate_user_write_typed(T* user) {