From 7a7ddc2d73b3171c8b3ab1168a906ed8b5018f5a Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Fri, 9 Oct 2015 15:28:16 +0200 Subject: [PATCH] Add guard page debug malloc. --- libc/include/malloc.h | 23 +++++++++++++++- libc/stdlib/free.cpp | 38 ++++++++++++++++++++++---- libc/stdlib/malloc.cpp | 60 +++++++++++++++++++++++++++++++++++++---- libc/stdlib/realloc.cpp | 46 +++++++++++++++++++++++++++---- 4 files changed, 151 insertions(+), 16 deletions(-) diff --git a/libc/include/malloc.h b/libc/include/malloc.h index 852a228b..f2409736 100644 --- a/libc/include/malloc.h +++ b/libc/include/malloc.h @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014. + Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014, 2015. This file is part of the Sortix C Library. @@ -79,6 +79,27 @@ int heap_get_paranoia(void); #endif #endif +#if !defined(HEAP_GUARD_DEBUG) && \ + defined(__is_sortix_kernel) && defined(HEAP_GUARD_DEBUG_KERNEL) +#define HEAP_GUARD_DEBUG +#endif + +#if !defined(MALLOC_GUARD_DEBUG) && \ + __STDC_HOSTED__ && defined(HEAP_GUARD_DEBUG_USERLAND) +#define HEAP_GUARD_DEBUG +#endif + +#if defined(HEAP_GUARD_DEBUG) && !defined(__is_sortix_kernel) +struct heap_alloc +{ + uintptr_t from; + size_t size; +}; +#define HEAP_PAGE_SIZE 4096UL +#define HEAP_ALIGN_PAGEDOWN(x) ((x) & ~(HEAP_PAGE_SIZE - 1)) +#define HEAP_ALIGN_PAGEUP(x) (-(-(x) & ~(HEAP_PAGE_SIZE - 1))) +#endif + /* A magic value to identify a heap part edge. The value is selected such that it is not appropriately aligned like a real heap chunk pointer, such that there are no ambiguous cases. */ diff --git a/libc/stdlib/free.cpp b/libc/stdlib/free.cpp index f1ecbdac..ddcbc463 100644 --- a/libc/stdlib/free.cpp +++ b/libc/stdlib/free.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014, 2015. This file is part of the Sortix C Library. @@ -25,16 +25,14 @@ #include #include -#if __is_sortix_kernel -#include -#endif - #if defined(HEAP_NO_ASSERT) #define __heap_verify() ((void) 0) #undef assert #define assert(x) do { ((void) 0); } while ( 0 ) #endif +#if !defined(HEAP_GUARD_DEBUG) + extern "C" void free(void* addr) { if ( !addr ) @@ -55,3 +53,33 @@ extern "C" void free(void* addr) __heap_verify(); __heap_unlock(); } + +#else + +#if defined(__is_sortix_kernel) +#include +#include +#else +#include +#endif + +extern "C" void free(void* addr) +{ + if ( !addr ) + return; + +#if defined(__is_sortix_kernel) + using namespace Sortix; + addralloc_t* alloc_ptr = (addralloc_t*) Page::AlignDown((uintptr_t) addr - 16); + assert(alloc_ptr->from == (uintptr_t) alloc_ptr); + addralloc_t alloc = *alloc_ptr; + Memory::UnmapRange(alloc.from, alloc.size - Page::Size(), PAGE_USAGE_KERNEL_HEAP); + FreeKernelAddress(&alloc); +#else + struct heap_alloc* alloc_ptr = + (struct heap_alloc*) HEAP_ALIGN_PAGEDOWN((uintptr_t) addr - 16); + munmap((void*) alloc_ptr->from, alloc_ptr->size); +#endif +} + +#endif diff --git a/libc/stdlib/malloc.cpp b/libc/stdlib/malloc.cpp index 91d04aa0..8e687b6c 100644 --- a/libc/stdlib/malloc.cpp +++ b/libc/stdlib/malloc.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014, 2015. This file is part of the Sortix C Library. @@ -28,16 +28,14 @@ #include #include -#if __is_sortix_kernel -#include -#endif - #if defined(HEAP_NO_ASSERT) #define __heap_verify() ((void) 0) #undef assert #define assert(x) do { ((void) 0); } while ( 0 ) #endif +#if !defined(HEAP_GUARD_DEBUG) + extern "C" void* malloc(size_t original_size) { if ( !heap_size_has_bin(original_size) ) @@ -102,3 +100,55 @@ extern "C" void* malloc(size_t original_size) // Return the inner data associated with the chunk to the caller. return heap_chunk_to_data(result_chunk); } + +#else + +#if defined(__is_sortix_kernel) +#include +#include +#include +#else +#include +#endif + +extern "C" void* malloc(size_t original_size) +{ + if ( !original_size ) + original_size = 1; + size_t size = -(-original_size & ~15UL); + size_t needed = 16 + size; +#if defined(__is_sortix_kernel) + using namespace Sortix; + needed = Page::AlignUp(needed); + size_t virtsize = needed + Page::Size(); + addralloc_t addralloc; + if ( !AllocateKernelAddress(&addralloc, virtsize) ) + return NULL; + if ( !Memory::MapRange(addralloc.from, addralloc.size - Page::Size(), + PROT_KREAD | PROT_KWRITE, PAGE_USAGE_KERNEL_HEAP) ) + { + FreeKernelAddress(&addralloc); + return NULL; + } + Memory::Flush(); + addralloc_t* addralloc_ptr = (addralloc_t*) (addralloc.from); + *addralloc_ptr = addralloc; +#else + needed = HEAP_ALIGN_PAGEUP(needed); + size_t virtsize = needed + HEAP_PAGE_SIZE; + void* from = mmap(NULL, virtsize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if ( from == MAP_FAILED ) + return NULL; + void* guard = (char*) from + needed; + if ( mprotect(guard, HEAP_PAGE_SIZE, PROT_NONE) < 0 ) + return munmap(from, virtsize), (void*) NULL; + struct heap_alloc* addralloc_ptr = (struct heap_alloc*) from; + addralloc_ptr->from = (uintptr_t) from; + addralloc_ptr->size = virtsize; +#endif + size_t offset = needed - size; + return (void*) (addralloc_ptr->from + offset); +} + +#endif diff --git a/libc/stdlib/realloc.cpp b/libc/stdlib/realloc.cpp index 5d657896..4af689d1 100644 --- a/libc/stdlib/realloc.cpp +++ b/libc/stdlib/realloc.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014, 2015. This file is part of the Sortix C Library. @@ -28,16 +28,14 @@ #include #include -#if __is_sortix_kernel -#include -#endif - #if defined(HEAP_NO_ASSERT) #define __heap_verify() ((void) 0) #undef assert #define assert(x) do { ((void) 0); } while ( 0 ) #endif +#if !defined(HEAP_GUARD_DEBUG) + extern "C" void* realloc(void* ptr, size_t requested_size) { if ( !ptr ) @@ -125,3 +123,41 @@ extern "C" void* realloc(void* ptr, size_t requested_size) return result; } + +#else + +#if defined(__is_sortix_kernel) +#include +#include +#endif + +extern "C" void* realloc(void* ptr, size_t requested_size) +{ + if ( !ptr ) + return malloc(requested_size); + +#if defined(__is_sortix_kernel) + using namespace Sortix; + addralloc_t* alloc_ptr = + (addralloc_t*) Page::AlignDown((uintptr_t) ptr - 16); + assert(alloc_ptr->from == (uintptr_t) alloc_ptr); + addralloc_t alloc = *alloc_ptr; + size_t size = (alloc.from + alloc.size - Page::Size()) - (uintptr_t) ptr; +#else + struct heap_alloc* alloc_ptr = + (struct heap_alloc*) HEAP_ALIGN_PAGEDOWN((uintptr_t) ptr - 16); + assert(alloc_ptr->from == (uintptr_t) alloc_ptr); + struct heap_alloc alloc = *alloc_ptr; + size_t size = (alloc.from + alloc.size - HEAP_PAGE_SIZE) - (uintptr_t) ptr; +#endif + if ( requested_size <= size ) + return ptr; + void* replacement = malloc(requested_size); + if ( !replacement ) + return NULL; + memcpy(replacement, ptr, size); + free(ptr); + return replacement; +} + +#endif