From ba9fa00947392432ba2b7d11fb1b0d4314173725 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Wed, 19 Jul 2023 23:17:39 +0300 Subject: [PATCH] Kernel: fix memory leak in PageTable PageTable used to leak 2 pages on creation and other two on deletion --- kernel/arch/x86_64/PageTable.cpp | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/kernel/arch/x86_64/PageTable.cpp b/kernel/arch/x86_64/PageTable.cpp index 3b1e86e2d..c596d9f09 100644 --- a/kernel/arch/x86_64/PageTable.cpp +++ b/kernel/arch/x86_64/PageTable.cpp @@ -140,18 +140,20 @@ namespace Kernel uint64_t* pml4 = (uint64_t*)P2V(m_highest_paging_struct); pml4[pml4e] = V2P(allocate_zeroed_page_aligned_page()); - pml4[pml4e] = (pml4[pml4e] & PAGE_ADDR_MASK) | (Flags::ReadWrite | Flags::Present); + pml4[pml4e] |= Flags::ReadWrite | Flags::Present; uint64_t* pdpt = (uint64_t*)P2V(pml4[pml4e] & PAGE_ADDR_MASK); for (uint64_t i = 0; pdpte + i < 512; i++) - { - pdpt[pdpte + i] = V2P(allocate_zeroed_page_aligned_page()); pdpt[pdpte + i] = s_global[i] | (Flags::ReadWrite | Flags::Present); - } } PageTable::~PageTable() { + // Verify that kernel memory fits to single page directory pointer table + static_assert(0xFFFFFFFFFFFFFFFF - KERNEL_OFFSET < 4096ull * 512ull * 512ull * 512ull); + constexpr uint64_t kernel_pml4e = (KERNEL_OFFSET >> 39) & 0x1FF; + constexpr uint64_t kernel_pdpte = (KERNEL_OFFSET >> 30) & 0x1FF; + uint64_t* pml4 = (uint64_t*)P2V(m_highest_paging_struct); for (uint64_t pml4e = 0; pml4e < 512; pml4e++) { @@ -162,21 +164,13 @@ namespace Kernel { if (!(pdpt[pdpte] & Flags::Present)) continue; + if (pml4e >= kernel_pml4e && pdpte >= kernel_pdpte) + break; uint64_t* pd = (uint64_t*)P2V(pdpt[pdpte] & PAGE_ADDR_MASK); for (uint64_t pde = 0; pde < 512; pde++) { if (!(pd[pde] & Flags::Present)) continue; - - vaddr_t vaddr = 0; - vaddr |= pml4e << 39; - vaddr |= pdpte << 30; - vaddr |= pde << 21; - vaddr = canonicalize(vaddr); - - if (vaddr >= KERNEL_OFFSET) - return; - kfree((void*)P2V(pd[pde] & PAGE_ADDR_MASK)); } kfree(pd);