kernel: Make a generic function for checking memory flags
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
This commit is contained in:
parent
88180b34bd
commit
b25e212880
@ -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;
|
||||
|
@ -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<String> 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<char> 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<ARCH_PAGE_SIZE>(user_ptr);
|
||||
uintptr_t address = (uintptr_t)mem;
|
||||
uintptr_t page = align_down<ARCH_PAGE_SIZE>(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<ARCH_PAGE_SIZE>(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;
|
||||
|
@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
#include "arch/MMU.h"
|
||||
#include <luna/Result.h>
|
||||
#include <luna/String.h>
|
||||
#include <luna/Types.h>
|
||||
@ -19,17 +20,22 @@ namespace MemoryManager
|
||||
Result<void> remap(u64 address, usize count, int flags);
|
||||
Result<void> 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<String> 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 <typename T> bool validate_user_write_typed(T* user)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user