summaryrefslogtreecommitdiff
path: root/Kernel/VM/MemoryManager.cpp
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-01-28 20:48:07 +0100
committerAndreas Kling <kling@serenityos.org>2020-01-28 20:48:07 +0100
commitc17f80e720b269e88700af4ea13f877b6d72303b (patch)
treeac5327d746b197c0d2c10015d302964bd09e89d2 /Kernel/VM/MemoryManager.cpp
parentbd059e32e14fa4ee6b498be4cc50ae678040d1d4 (diff)
downloadserenity-c17f80e720b269e88700af4ea13f877b6d72303b.zip
Kernel: AnonymousVMObject::create_for_physical_range() should fail more
Previously it was not possible for this function to fail. You could exploit this by triggering the creation of a VMObject whose physical memory range would wrap around the 32-bit limit. It was quite easy to map kernel memory into userspace and read/write whatever you wanted in it. Test: Kernel/bxvga-mmap-kernel-into-userspace.cpp
Diffstat (limited to 'Kernel/VM/MemoryManager.cpp')
-rw-r--r--Kernel/VM/MemoryManager.cpp7
1 files changed, 5 insertions, 2 deletions
diff --git a/Kernel/VM/MemoryManager.cpp b/Kernel/VM/MemoryManager.cpp
index db877a128e..9053f201f3 100644
--- a/Kernel/VM/MemoryManager.cpp
+++ b/Kernel/VM/MemoryManager.cpp
@@ -313,11 +313,14 @@ OwnPtr<Region> MemoryManager::allocate_kernel_region(PhysicalAddress paddr, size
ASSERT(!(size % PAGE_SIZE));
auto range = kernel_page_directory().range_allocator().allocate_anywhere(size);
ASSERT(range.is_valid());
+ auto vmobject = AnonymousVMObject::create_for_physical_range(paddr, size);
+ if (!vmobject)
+ return nullptr;
OwnPtr<Region> region;
if (user_accessible)
- region = Region::create_user_accessible(range, AnonymousVMObject::create_for_physical_range(paddr, size), 0, name, access, cacheable);
+ region = Region::create_user_accessible(range, vmobject.release_nonnull(), 0, name, access, cacheable);
else
- region = Region::create_kernel_only(range, AnonymousVMObject::create_for_physical_range(paddr, size), 0, name, access, cacheable);
+ region = Region::create_kernel_only(range, vmobject.release_nonnull(), 0, name, access, cacheable);
region->map(kernel_page_directory());
return region;
}