From 4f3a7230b022181451c514690627884b0fd5e1ef Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Sun, 27 Nov 2011 12:02:34 +0100 Subject: [PATCH] Destroying the addressspace after exit prevents leak of at least 16 KiB. --- libmaxsi/memory.cpp | 2 +- sortix/memorymanagement.h | 1 + sortix/process.cpp | 7 ++++- sortix/x86/memorymanagement.cpp | 52 ++++++++++++++++++++++++++++++++- 4 files changed, 59 insertions(+), 3 deletions(-) diff --git a/libmaxsi/memory.cpp b/libmaxsi/memory.cpp index 7bdaa809..4bcc76a3 100644 --- a/libmaxsi/memory.cpp +++ b/libmaxsi/memory.cpp @@ -267,7 +267,7 @@ namespace Maxsi Sortix::Page::Put(OldPage); } return false; - } + } } #endif diff --git a/sortix/memorymanagement.h b/sortix/memorymanagement.h index 35dbfcdb..86d0371c 100644 --- a/sortix/memorymanagement.h +++ b/sortix/memorymanagement.h @@ -49,6 +49,7 @@ namespace Sortix void Flush(); addr_t Fork(); addr_t SwitchAddressSpace(addr_t addrspace); + void DestroyAddressSpace(); bool MapRangeKernel(addr_t where, size_t bytes); void UnmapRangeKernel(addr_t where, size_t bytes); bool MapRangeUser(addr_t where, size_t bytes); diff --git a/sortix/process.cpp b/sortix/process.cpp index fa1c0112..c2f774fd 100644 --- a/sortix/process.cpp +++ b/sortix/process.cpp @@ -515,7 +515,7 @@ namespace Sortix void Process::Exit(int status) { - // Status codes can only contain 8 bits according to ISO C and POSIX. + // Status codes can only contain 8 bits according to ISO C and POSIX. status %= 256; ASSERT(this == CurrentProcess()); @@ -594,6 +594,11 @@ namespace Sortix // Notify the parent process that the child has become a zombie. parent->OnChildProcessExit(this); + + // Now, as a final operation, get rid of the address space. This should + // return us to the original kernel address space containing nothing + // but the kernel. + Memory::DestroyAddressSpace(); } void SysExit(int status) diff --git a/sortix/x86/memorymanagement.cpp b/sortix/x86/memorymanagement.cpp index 1ff2f40a..a185512f 100644 --- a/sortix/x86/memorymanagement.cpp +++ b/sortix/x86/memorymanagement.cpp @@ -35,6 +35,7 @@ namespace Sortix { extern size_t stackused; extern size_t stacklength; + void ExtendStack(); } namespace Memory @@ -72,7 +73,7 @@ namespace Sortix BOOTPML1->entry[1023] = (addr_t) BOOTPML2 | flags; // Add some predefined room for forking address spaces. - BOOTPML1->entry[0] = (addr_t) FORKPML1 | flags | PML_FORK; + BOOTPML1->entry[0] = 0; // (addr_t) FORKPML1 | flags | PML_FORK; // The virtual memory structures are now available on the predefined // locations. This means the virtual memory code is bootstrapped. Of @@ -100,5 +101,54 @@ namespace Sortix // up, the calling function will fill up the physical allocator with // plenty of nice physical pages. (see Page::InitPushRegion) } + + // Please note that even if this function exists, you should still clean + // up the address space of a process _before_ calling + // DestroyAddressSpace. This is just a hack because it currently is + // impossible to clean up PLM1's using the MM api! + void RecursiveFreeUserspacePages(size_t level, size_t offset) + { + PML* pml = PMLS[level] + offset; + for ( size_t i = 0; i < ENTRIES; i++ ) + { + if ( !(pml->entry[i] & PML_PRESENT) ) { continue; } + if ( !(pml->entry[i] & PML_USERSPACE) ) { continue; } + if ( !(pml->entry[i] & PML_FORK) ) { continue; } + if ( level > 1 ) { RecursiveFreeUserspacePages(level-1, offset * ENTRIES + i); } + addr_t addr = pml->entry[i] & PML_ADDRESS; + pml->entry[i] = 0; + Page::Put(addr); + } + } + + void DestroyAddressSpace() + { + // First let's do the safe part. Garbage collect any PML1/0's left + // behind by user-space. These are completely safe to delete. + RecursiveFreeUserspacePages(TOPPMLLEVEL, 0); + + // Let's destroy the current address space! Oh wait. If we do that, + // hell will break loose half-way when we start unmapping this piece + // of code. + // Instead, let's just mark the relevant pages as unused and switch + // to another address space as fast as humanely possible. Any memory + // allocation could potentially modify the current paging structures + // and overwrite their contents causing a tripple-fault! + + // Make sure Page::Put does NOT cause any Page::Get's internally! + const size_t NUM_PAGES = 2; + if ( Page::stacklength - Page::stackused < NUM_PAGES ) { Page::ExtendStack(); } + + addr_t fractal1 = PMLS[2]->entry[1022]; + + Page::Put(fractal1); + Page::Put(currentdir); + + // Switch to the address space from when the world was originally + // created. It should contain the kernel, the whole kernel, and + // nothing but the kernel. + PML* const BOOTPML2 = (PML* const) 0x01000UL; + SwitchAddressSpace((addr_t) BOOTPML2); + } } }