mirror of
https://github.com/RGBCube/serenity
synced 2025-05-28 17:55:09 +00:00
Kernel: Validate the full range of user memory passed to syscalls
We now validate the full range of userspace memory passed into syscalls instead of just checking that the first and last byte of the memory are in process-owned regions. This fixes an issue where it was possible to avoid rejection of invalid addresses that sat between two valid ones, simply by passing a valid address and a size large enough to put the end of the range at another valid address. I added a little test utility that tries to provoke EFAULT in various ways to help verify this. I'm sure we can think of more ways to test this but it's at least a start. :^) Thanks to mozjag for pointing out that this code was still lacking! Incidentally this also makes backtraces work again. Fixes #989.
This commit is contained in:
parent
e5ffa960d7
commit
3dcec260ed
4 changed files with 121 additions and 25 deletions
|
@ -1958,7 +1958,7 @@ bool Process::validate_read_from_kernel(VirtualAddress vaddr, ssize_t size) cons
|
|||
return false;
|
||||
if (is_kmalloc_address(vaddr.as_ptr()))
|
||||
return true;
|
||||
return validate_read(vaddr.as_ptr(), size);
|
||||
return MM.validate_kernel_read(*this, vaddr, size);
|
||||
}
|
||||
|
||||
bool Process::validate_read_str(const char* str)
|
||||
|
@ -1984,23 +1984,15 @@ bool Process::validate_read(const void* address, ssize_t size) const
|
|||
if (is_kmalloc_address(address))
|
||||
return true;
|
||||
}
|
||||
ASSERT(size);
|
||||
if (!size)
|
||||
return false;
|
||||
if (first_address.page_base() != last_address.page_base()) {
|
||||
if (!MM.validate_user_read(*this, last_address))
|
||||
return false;
|
||||
}
|
||||
return MM.validate_user_read(*this, first_address);
|
||||
return MM.validate_user_read(*this, first_address, size);
|
||||
}
|
||||
|
||||
bool Process::validate_write(void* address, ssize_t size) const
|
||||
{
|
||||
ASSERT(size >= 0);
|
||||
VirtualAddress first_address((u32)address);
|
||||
VirtualAddress last_address = first_address.offset(size - 1);
|
||||
if (last_address < first_address)
|
||||
return false;
|
||||
if (is_ring0()) {
|
||||
if (is_kmalloc_address(address))
|
||||
return true;
|
||||
|
@ -2012,11 +2004,7 @@ bool Process::validate_write(void* address, ssize_t size) const
|
|||
}
|
||||
if (!size)
|
||||
return false;
|
||||
if (first_address.page_base() != last_address.page_base()) {
|
||||
if (!MM.validate_user_write(*this, last_address))
|
||||
return false;
|
||||
}
|
||||
return MM.validate_user_write(*this, first_address);
|
||||
return MM.validate_user_write(*this, first_address, size);
|
||||
}
|
||||
|
||||
pid_t Process::sys$getsid(pid_t pid)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue