1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 03:47:35 +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:
Andreas Kling 2020-01-02 02:09:25 +01:00
parent e5ffa960d7
commit 3dcec260ed
4 changed files with 121 additions and 25 deletions

View file

@ -45,8 +45,10 @@ public:
void enter_process_paging_scope(Process&);
bool validate_user_stack(const Process&, VirtualAddress) const;
bool validate_user_read(const Process&, VirtualAddress) const;
bool validate_user_write(const Process&, VirtualAddress) const;
bool validate_user_read(const Process&, VirtualAddress, size_t) const;
bool validate_user_write(const Process&, VirtualAddress, size_t) const;
bool validate_kernel_read(const Process&, VirtualAddress, size_t) const;
enum class ShouldZeroFill {
No,
@ -85,6 +87,11 @@ private:
MemoryManager(u32 physical_address_for_kernel_page_tables);
~MemoryManager();
enum class AccessSpace { Kernel, User };
enum class AccessType { Read, Write };
template<AccessSpace, AccessType>
bool validate_range(const Process&, VirtualAddress, size_t) const;
void register_vmobject(VMObject&);
void unregister_vmobject(VMObject&);
void register_region(Region&);