mprotect(): Validate the entire range to protect is in userspace memory

Before this patch, sys_mprotect() only validated the starting address.
This was as bad as it sounds, in fact it let me write a fun exploit
using it.
Now, this exploit is no longer possible.

This patch is probably not relevant, since this branch will be gone in
the future, as soon as restart gets merged into main.
I made it anyways :^)
This commit is contained in:
apio 2023-01-02 11:51:08 +01:00
parent 1f4c4f1a0c
commit 4ef764e62e
Signed by: apio
GPG Key ID: B8A7D06E42258954
2 changed files with 17 additions and 10 deletions

View File

@ -45,10 +45,10 @@ uint64_t Memory::get_usable()
bool Memory::is_kernel_address(uintptr_t address)
{
return address >= 0xfffffffff8000000;
return address >= 0xffff800000000000;
}
bool Memory::is_user_address(uintptr_t address)
{
return address && address < 0xfffffffff8000000;
return address && address < 0x00007fffffffffff;
}

View File

@ -55,9 +55,9 @@ void sys_mmap(Context* context, void* address, size_t size, int prot, int fd, of
if (address)
{
kdbgln("mmap(): %ld pages at address %p, %s, fd %d", size / PAGE_SIZE, address, format_prot(prot), fd);
if (Memory::is_kernel_address((uintptr_t)address))
if (!Memory::is_user_address((uintptr_t)address))
{
kwarnln("munmap() failed: attempted to unmap a kernel page");
kwarnln("mmap() failed: attempted to map a non-user page");
context->rax = MAP_FAIL(ENOMEM);
return;
}
@ -153,9 +153,9 @@ void sys_munmap(Context* context, void* address, size_t size)
context->rax = -EINVAL;
return;
}
if (Memory::is_kernel_address((uintptr_t)address))
if (!Memory::is_user_address((uintptr_t)address))
{
kwarnln("munmap() failed: attempted to unmap a kernel page");
kwarnln("munmap() failed: attempted to unmap a non-user page");
context->rax = -EINVAL;
return;
}
@ -202,9 +202,16 @@ void sys_mprotect(Context* context, void* address, size_t size, int prot)
context->rax = -EINVAL;
return;
}
if (Memory::is_kernel_address((uintptr_t)address))
if (!Memory::is_user_address((uintptr_t)address))
{
kwarnln("mprotect() failed: attempted to protect a kernel page");
kwarnln("mprotect() failed: attempted to protect a non-user page");
context->rax = -EINVAL;
return;
}
// FIXME: Check for overflow when adding address + size.
if (!Memory::is_user_address((uintptr_t)address + size))
{
kwarnln("mprotect() failed: end of given range is out of user memory");
context->rax = -EINVAL;
return;
}