From 326c6130a5dcc12dab281eaedd4dbc6e90f4cfe4 Mon Sep 17 00:00:00 2001 From: creator1creeper1 Date: Sun, 16 Jan 2022 17:03:06 +0100 Subject: [PATCH] Kernel: Don't access directory table of uninitialized PageDirectory PageDirectory gets initialized step-by-step in PageDirectory::try_create_for_userspace(). This initialization may fail anywhere in this function - for example, we may not be able to allocate a directory table, in which case PageDirectory::try_create_for_userspace() will return a null pointer. We recognize this condition and early-return ENOMEM. However, at this point, we need to correctly destruct the only partially initialized PageDirectory. Previously, PageDirectory::~PageDirectory() would assume that the object it was destructing was always fully initialized. It now uses the new helper PageDirectory::is_cr3_initialized() to correctly recognize when the directory table was not yet initialized. This helper checks if the pointer to the directory table is null. Only if it is not null does the destructor try to fetch the directory table using PageDirectory::cr3(). --- Kernel/Memory/PageDirectory.cpp | 6 ++++-- Kernel/Memory/PageDirectory.h | 9 +++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Kernel/Memory/PageDirectory.cpp b/Kernel/Memory/PageDirectory.cpp index c54b95d3c7..1398343b23 100644 --- a/Kernel/Memory/PageDirectory.cpp +++ b/Kernel/Memory/PageDirectory.cpp @@ -150,8 +150,10 @@ UNMAP_AFTER_INIT void PageDirectory::allocate_kernel_directory() PageDirectory::~PageDirectory() { - SpinlockLocker lock(s_mm_lock); - cr3_map().remove(cr3()); + if (is_cr3_initialized()) { + SpinlockLocker lock(s_mm_lock); + cr3_map().remove(cr3()); + } } } diff --git a/Kernel/Memory/PageDirectory.h b/Kernel/Memory/PageDirectory.h index 9a7e564ca7..eaabce7dcc 100644 --- a/Kernel/Memory/PageDirectory.h +++ b/Kernel/Memory/PageDirectory.h @@ -37,6 +37,15 @@ public: #endif } + bool is_cr3_initialized() const + { +#if ARCH(X86_64) + return m_pml4t; +#else + return m_directory_table; +#endif + } + VirtualRangeAllocator& range_allocator() { return m_range_allocator; } VirtualRangeAllocator const& range_allocator() const { return m_range_allocator; }