MemoryManager: Add helper functions to validate arbitrary ranges of userspace memory
This commit is contained in:
parent
7fb2807d0c
commit
29bd8a69fa
@ -347,23 +347,74 @@ namespace MemoryManager
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Replace this with some kind of strdup_from_user() function.
|
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)
|
bool validate_userspace_string(u64 address)
|
||||||
{
|
{
|
||||||
if (!validate_readable_page(address)) return false;
|
if (!validate_user_readable_page(address)) return false;
|
||||||
|
|
||||||
while (*(char*)address != 0)
|
while (*(char*)address != 0)
|
||||||
{
|
{
|
||||||
address++;
|
address++;
|
||||||
if (address % ARCH_PAGE_SIZE)
|
if (address % ARCH_PAGE_SIZE)
|
||||||
{
|
{
|
||||||
if (!validate_readable_page(address)) return false;
|
if (!validate_user_readable_page(address)) return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool validate_user_write(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_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool copy_to_user(void* user, const void* kernel, usize size)
|
bool copy_to_user(void* user, const void* kernel, usize size)
|
||||||
{
|
{
|
||||||
uintptr_t user_ptr = (uintptr_t)user;
|
uintptr_t user_ptr = (uintptr_t)user;
|
||||||
@ -375,7 +426,7 @@ namespace MemoryManager
|
|||||||
if (user_ptr != user_page)
|
if (user_ptr != user_page)
|
||||||
{
|
{
|
||||||
// FIXME: Validate that this page is writable by the user, not just the kernel.
|
// FIXME: Validate that this page is writable by the user, not just the kernel.
|
||||||
if (!validate_writable_page(user_page)) return false;
|
if (!validate_user_writable_page(user_page)) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (size--)
|
while (size--)
|
||||||
@ -383,7 +434,7 @@ namespace MemoryManager
|
|||||||
// Crossed a page boundary, gotta check the page tables again before touching any memory!!
|
// Crossed a page boundary, gotta check the page tables again before touching any memory!!
|
||||||
if (user_ptr % ARCH_PAGE_SIZE)
|
if (user_ptr % ARCH_PAGE_SIZE)
|
||||||
{
|
{
|
||||||
if (!validate_writable_page(user_ptr)) return false;
|
if (!validate_user_writable_page(user_ptr)) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
*(char*)user_ptr = *kernel_ptr++;
|
*(char*)user_ptr = *kernel_ptr++;
|
||||||
|
@ -20,8 +20,24 @@ namespace MemoryManager
|
|||||||
bool validate_readable_page(u64 address);
|
bool validate_readable_page(u64 address);
|
||||||
bool validate_writable_page(u64 address);
|
bool validate_writable_page(u64 address);
|
||||||
|
|
||||||
|
bool validate_user_readable_page(u64 address);
|
||||||
|
bool validate_user_writable_page(u64 address);
|
||||||
|
|
||||||
bool validate_userspace_string(u64 address);
|
bool validate_userspace_string(u64 address);
|
||||||
|
|
||||||
|
bool validate_user_write(void* user, usize size);
|
||||||
|
bool validate_user_read(const void* user, usize size);
|
||||||
|
|
||||||
|
template <typename T> bool validate_user_write_typed(T* user)
|
||||||
|
{
|
||||||
|
return validate_user_write(user, sizeof(T));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> bool validate_user_read_typed(const T* user)
|
||||||
|
{
|
||||||
|
return validate_user_read(user, sizeof(T));
|
||||||
|
}
|
||||||
|
|
||||||
bool copy_to_user(void* user, const void* kernel, usize size);
|
bool copy_to_user(void* user, const void* kernel, usize size);
|
||||||
|
|
||||||
template <typename T> bool copy_to_user_typed(T* user, const T* kernel)
|
template <typename T> bool copy_to_user_typed(T* user, const T* kernel)
|
||||||
|
Loading…
Reference in New Issue
Block a user