diff --git a/Kernel/Syscalls/execve.cpp b/Kernel/Syscalls/execve.cpp index 1399f6336f..85c677c9dd 100644 --- a/Kernel/Syscalls/execve.cpp +++ b/Kernel/Syscalls/execve.cpp @@ -284,11 +284,15 @@ KResultOr Process::load(NonnullRefPtr main NonnullOwnPtrVector old_regions; { + auto page_directory = PageDirectory::create_for_userspace(*this); + if (!page_directory) + return KResult(-ENOMEM); + // Need to make sure we don't swap contexts in the middle ScopedCritical critical; old_page_directory = move(m_page_directory); old_regions = move(m_regions); - m_page_directory = PageDirectory::create_for_userspace(*this); + m_page_directory = page_directory.release_nonnull(); } ArmedScopeGuard rollback_regions_guard([&]() { diff --git a/Kernel/VM/PageDirectory.cpp b/Kernel/VM/PageDirectory.cpp index b60a251351..b75d42261f 100644 --- a/Kernel/VM/PageDirectory.cpp +++ b/Kernel/VM/PageDirectory.cpp @@ -74,7 +74,6 @@ PageDirectory::PageDirectory() } PageDirectory::PageDirectory(Process& process, const RangeAllocator* parent_range_allocator) - : m_process(&process) { ScopedSpinLock lock(s_mm_lock); if (parent_range_allocator) { @@ -87,9 +86,17 @@ PageDirectory::PageDirectory(Process& process, const RangeAllocator* parent_rang // Set up a userspace page directory m_directory_table = MM.allocate_user_physical_page(); + if (!m_directory_table) + return; m_directory_pages[0] = MM.allocate_user_physical_page(); + if (!m_directory_pages[0]) + return; m_directory_pages[1] = MM.allocate_user_physical_page(); + if (!m_directory_pages[1]) + return; m_directory_pages[2] = MM.allocate_user_physical_page(); + if (!m_directory_pages[2]) + return; // Share the top 1 GiB of kernel-only mappings (>=3GiB or >=0xc0000000) m_directory_pages[3] = MM.kernel_page_directory().m_directory_pages[3]; @@ -135,6 +142,9 @@ PageDirectory::PageDirectory(Process& process, const RangeAllocator* parent_rang auto* new_pd = MM.quickmap_pd(*this, 0); memcpy(new_pd, &buffer, sizeof(PageDirectoryEntry)); + // If we got here, we successfully created it. Set m_process now + m_process = &process; + cr3_map().set(cr3(), this); } @@ -144,7 +154,8 @@ PageDirectory::~PageDirectory() dbg() << "MM: ~PageDirectory K" << this; #endif ScopedSpinLock lock(s_mm_lock); - cr3_map().remove(cr3()); + if (m_process) + cr3_map().remove(cr3()); } } diff --git a/Kernel/VM/PageDirectory.h b/Kernel/VM/PageDirectory.h index 880524cc78..f4bd7f41ff 100644 --- a/Kernel/VM/PageDirectory.h +++ b/Kernel/VM/PageDirectory.h @@ -40,9 +40,12 @@ class PageDirectory : public RefCounted { friend class MemoryManager; public: - static NonnullRefPtr create_for_userspace(Process& process, const RangeAllocator* parent_range_allocator = nullptr) + static RefPtr create_for_userspace(Process& process, const RangeAllocator* parent_range_allocator = nullptr) { - return adopt(*new PageDirectory(process, parent_range_allocator)); + auto page_directory = adopt(*new PageDirectory(process, parent_range_allocator)); + if (!page_directory->process()) + return {}; + return page_directory; } static NonnullRefPtr create_kernel_page_directory() { return adopt(*new PageDirectory); } static RefPtr find_by_cr3(u32);