From 89edb1e821a3e7224729a65c0df6d465d03b6b6c Mon Sep 17 00:00:00 2001 From: Dimitris Oikonomou Date: Wed, 14 May 2025 02:00:19 +0300 Subject: [PATCH 1/6] dlmalloc --- .gitignore | 2 + .vscode/c_cpp_properties.json | 18 ++ .vscode/launch.json | 24 ++ .vscode/settings.json | 68 ++++++ Makefile | 7 +- heap.c | 46 ++-- heap.h | 9 +- kasan.h | 18 -- kasan.c => kasan_common.c | 70 +----- kasan_common.h | 41 ++++ kasan_dlmalloc.c | 443 ++++++++++++++++++++++++++++++++++ kasan_dlmalloc.h | 334 +++++++++++++++++++++++++ kasan_simple_malloc.c | 52 ++++ kasan_simple_malloc.h | 12 + kasan_test | Bin 0 -> 54856 bytes kasan_test.c | 4 +- kasan_test.lds | 27 +++ sanitized_lib.c | 9 + sanitized_lib.h | 1 + 19 files changed, 1076 insertions(+), 109 deletions(-) create mode 100644 .gitignore create mode 100644 .vscode/c_cpp_properties.json create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json delete mode 100644 kasan.h rename kasan.c => kasan_common.c (79%) create mode 100644 kasan_common.h create mode 100644 kasan_dlmalloc.c create mode 100644 kasan_dlmalloc.h create mode 100644 kasan_simple_malloc.c create mode 100644 kasan_simple_malloc.h create mode 100755 kasan_test create mode 100644 kasan_test.lds diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2c352e5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.o +*.su \ No newline at end of file diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..c2098a2 --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,18 @@ +{ + "configurations": [ + { + "name": "linux-gcc-x64", + "includePath": [ + "${workspaceFolder}/**" + ], + "compilerPath": "/usr/bin/gcc", + "cStandard": "${default}", + "cppStandard": "${default}", + "intelliSenseMode": "linux-gcc-x64", + "compilerArgs": [ + "" + ] + } + ], + "version": 4 +} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..79e3643 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,24 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "C/C++ Runner: Debug Session", + "type": "cppdbg", + "request": "launch", + "args": [], + "stopAtEntry": false, + "externalConsole": false, + "cwd": "/home/dimeko/dev/brm_kasan", + "program": "/home/dimeko/dev/brm_kasan/build/Debug/outDebug", + "MIMode": "gdb", + "miDebuggerPath": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ] + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..a98c014 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,68 @@ +{ + "C_Cpp_Runner.cCompilerPath": "gcc", + "C_Cpp_Runner.cppCompilerPath": "g++", + "C_Cpp_Runner.debuggerPath": "gdb", + "C_Cpp_Runner.cStandard": "", + "C_Cpp_Runner.cppStandard": "", + "C_Cpp_Runner.msvcBatchPath": "", + "C_Cpp_Runner.useMsvc": false, + "C_Cpp_Runner.warnings": [ + "-Wall", + "-Wextra", + "-Wpedantic", + "-Wshadow", + "-Wformat=2", + "-Wcast-align", + "-Wconversion", + "-Wsign-conversion", + "-Wnull-dereference" + ], + "C_Cpp_Runner.msvcWarnings": [ + "/W4", + "/permissive-", + "/w14242", + "/w14287", + "/w14296", + "/w14311", + "/w14826", + "/w44062", + "/w44242", + "/w14905", + "/w14906", + "/w14263", + "/w44265", + "/w14928" + ], + "C_Cpp_Runner.enableWarnings": true, + "C_Cpp_Runner.warningsAsError": false, + "C_Cpp_Runner.compilerArgs": [], + "C_Cpp_Runner.linkerArgs": [], + "C_Cpp_Runner.includePaths": [], + "C_Cpp_Runner.includeSearch": [ + "*", + "**/*" + ], + "C_Cpp_Runner.excludeSearch": [ + "**/build", + "**/build/**", + "**/.*", + "**/.*/**", + "**/.vscode", + "**/.vscode/**" + ], + "C_Cpp_Runner.useAddressSanitizer": false, + "C_Cpp_Runner.useUndefinedSanitizer": false, + "C_Cpp_Runner.useLeakSanitizer": false, + "C_Cpp_Runner.showCompilationTime": false, + "C_Cpp_Runner.useLinkTimeOptimization": false, + "C_Cpp_Runner.msvcSecureNoWarnings": false, + "files.associations": { + "dlmalloc.h": "c", + "kasan.h": "c", + "common.h": "c", + "heap.h": "c", + "kasan_dlmalloc.h": "c", + "kasan_common.h": "c", + "stdint.h": "c" + } +} \ No newline at end of file diff --git a/Makefile b/Makefile index 48aea9a..a98e6d7 100644 --- a/Makefile +++ b/Makefile @@ -35,6 +35,7 @@ CFLAGS += -DPRINTF_DISABLE_SUPPORT_FLOAT CFLAGS += -DPRINTF_DISABLE_SUPPORT_EXPONENTIAL CFLAGS += -DPRINTF_DISABLE_SUPPORT_PTRDIFF_T CFLAGS += -DPRINTF_DISABLE_SUPPORT_LONG_LONG +CFLAGS += -DDLMALLOC_ENABLED CFLAGS += -Wno-incompatible-library-redeclaration @@ -54,8 +55,10 @@ KASAN_CC_FLAGS += -mllvm -asan-stack=$(KASAN_SANITIZE_STACK) KASAN_CC_FLAGS += -mllvm -asan-globals=$(KASAN_SANITIZE_GLOBALS) KASAN_CC_FLAGS += -DKASAN_ENABLED -SRCS := kasan.c \ - heap.c \ +SRCS := heap.c \ + kasan_common.c \ + kasan_simple_malloc.c \ + kasan_dlmalloc.c \ kasan_test.c \ sanitized_lib.c \ rt_utils.c \ diff --git a/heap.c b/heap.c index 8e6c67f..44ab3a9 100644 --- a/heap.c +++ b/heap.c @@ -10,34 +10,46 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ +#pragma #include "common.h" -#include "kasan.h" +#include "kasan_common.h" +#include "kasan_simple_malloc.h" +#include "kasan_dlmalloc.h" +#include "heap.h" +#include "printf.h" // These symbols are defined in the linker script. extern char __heap_start; extern char __heap_end; -static void *heap_head; -static size_t heap_size; +size_t mem_malloc_size = 0; +unsigned long mem_malloc_start = 0; +unsigned long mem_malloc_end = 0; +unsigned long mem_malloc_brk = 0; void initialize_heap(void) { - heap_head = (void *)&__heap_start; - heap_size = (void *)&__heap_end - (void *)&__heap_start; -} - -void *allocate_chunk(unsigned long size) { - void *result = heap_head; - if (size > heap_size) return NULL; - - size = (size + 7) & (~7UL); - heap_head += size; - heap_size -= size; - return result; + mem_malloc_start = (unsigned long)&__heap_start; + mem_malloc_end = (unsigned long)&__heap_end; + mem_malloc_size = mem_malloc_end - mem_malloc_start; + mem_malloc_brk = mem_malloc_start; + initialize_kasan(); } void free_chunk(void *ptr) { (void)ptr; } -void *malloc(unsigned long size) { return kasan_malloc_hook(size); } +void *malloc(unsigned long size) { + #ifdef DLMALLOC_ENABLED + return kasan_dlmalloc_hook(size); + #else + return kasan_malloc_hook(size); + #endif // DLMALLOC_ENABLED +} -void free(void *ptr) { return kasan_free_hook(ptr); } \ No newline at end of file +void free(void *ptr) { + #ifdef DLMALLOC_ENABLED + return kasan_dlfree_hook(ptr); + #else + return kasan_free_hook(ptr); + #endif // DLMALLOC_ENABLED +} \ No newline at end of file diff --git a/heap.h b/heap.h index 78ef518..fdf3ee3 100644 --- a/heap.h +++ b/heap.h @@ -10,15 +10,18 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ +#include "common.h" #ifndef __KASAN_HEAP_H__ #define __KASAN_HEAP_H__ -void initialize_heap(void); +extern size_t mem_malloc_size; +extern unsigned long mem_malloc_start; +extern unsigned long mem_malloc_end; +extern unsigned long mem_malloc_brk; -void *allocate_chunk(unsigned long size); +void initialize_heap(void); void free_chunk(void *ptr); - void *malloc(unsigned long size); void free(void *ptr); diff --git a/kasan.h b/kasan.h deleted file mode 100644 index 02f07b7..0000000 --- a/kasan.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright 2024 Google LLC - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -void initialize_kasan(void); - -void *kasan_malloc_hook(unsigned long size); - -void kasan_free_hook(void *ptr); \ No newline at end of file diff --git a/kasan.c b/kasan_common.c similarity index 79% rename from kasan.c rename to kasan_common.c index dd4fa95..999a0c5 100644 --- a/kasan.c +++ b/kasan_common.c @@ -12,27 +12,9 @@ */ #include "common.h" -#include "heap.h" +// #include "heap.h" #include "printf.h" - -#define KASAN_SHADOW_SHIFT 3 -#define KASAN_SHADOW_GRANULE_SIZE (1UL << KASAN_SHADOW_SHIFT) -#define KASAN_SHADOW_MASK (KASAN_SHADOW_GRANULE_SIZE - 1) - -#define ASAN_SHADOW_UNPOISONED_MAGIC 0x00 -#define ASAN_SHADOW_RESERVED_MAGIC 0xff -#define ASAN_SHADOW_GLOBAL_REDZONE_MAGIC 0xf9 -#define ASAN_SHADOW_HEAP_HEAD_REDZONE_MAGIC 0xfa -#define ASAN_SHADOW_HEAP_TAIL_REDZONE_MAGIC 0xfb -#define ASAN_SHADOW_HEAP_FREE_MAGIC 0xfd - -#define KASAN_HEAP_HEAD_REDZONE_SIZE 0x20 -#define KASAN_HEAP_TAIL_REDZONE_SIZE 0x20 - -#define KASAN_MEM_TO_SHADOW(addr) \ - (((addr) >> KASAN_SHADOW_SHIFT) + KASAN_SHADOW_MAPPING_OFFSET) -#define KASAN_SHADOW_TO_MEM(shadow) \ - (((shadow) - KASAN_SHADOW_MAPPING_OFFSET) << KASAN_SHADOW_SHIFT) +#include "kasan_common.h" void kasan_bug_report(unsigned long addr, size_t size, unsigned long buggy_shadow_address, uint8_t is_write, @@ -75,7 +57,7 @@ static inline unsigned long get_poisoned_shadow_address(unsigned long addr, } // Both `address` and `size` must be 8-byte aligned. -static void poison_shadow(unsigned long address, size_t size, uint8_t value) { +void poison_shadow(unsigned long address, size_t size, uint8_t value) { unsigned long shadow_start, shadow_end; size_t shadow_length = 0; @@ -87,7 +69,7 @@ static void poison_shadow(unsigned long address, size_t size, uint8_t value) { } // `address` must be 8-byte aligned -static void unpoison_shadow(unsigned long address, size_t size) { +void unpoison_shadow(unsigned long address, size_t size) { poison_shadow(address, size & (~KASAN_SHADOW_MASK), ASAN_SHADOW_UNPOISONED_MAGIC); @@ -165,50 +147,6 @@ void *__kasan_memset(void *buf, int c, unsigned int size, unsigned long pc) { return memset(buf, c, size); } -// Implement KASan heap management hooks. - -struct KASAN_HEAP_HEADER { - unsigned int aligned_size; -}; - -void *kasan_malloc_hook(unsigned int size) { - struct KASAN_HEAP_HEADER *kasan_heap_hdr = NULL; - unsigned int algined_size = (size + KASAN_SHADOW_MASK) & (~KASAN_SHADOW_MASK); - unsigned int total_size = algined_size + KASAN_HEAP_HEAD_REDZONE_SIZE + - KASAN_HEAP_TAIL_REDZONE_SIZE; - - void *ptr = allocate_chunk(total_size); - if (ptr == NULL) return NULL; - - kasan_heap_hdr = (struct KASAN_HEAP_HEADER *)ptr; - kasan_heap_hdr->aligned_size = algined_size; - - unpoison_shadow((unsigned long)(ptr + KASAN_HEAP_HEAD_REDZONE_SIZE), size); - poison_shadow((unsigned long)ptr, KASAN_HEAP_HEAD_REDZONE_SIZE, - ASAN_SHADOW_HEAP_HEAD_REDZONE_MAGIC); - poison_shadow( - (unsigned long)(ptr + KASAN_HEAP_HEAD_REDZONE_SIZE + algined_size), - KASAN_HEAP_TAIL_REDZONE_SIZE, ASAN_SHADOW_HEAP_TAIL_REDZONE_MAGIC); - - return ptr + KASAN_HEAP_HEAD_REDZONE_SIZE; -} - -void kasan_free_hook(void *ptr) { - struct KASAN_HEAP_HEADER *kasan_heap_hdr = NULL; - unsigned int aligned_size = 0; - - if (ptr == NULL) return; - - kasan_heap_hdr = - (struct KASAN_HEAP_HEADER *)(ptr - KASAN_HEAP_HEAD_REDZONE_SIZE); - aligned_size = kasan_heap_hdr->aligned_size; - - free_chunk(kasan_heap_hdr); - poison_shadow((unsigned long)ptr, aligned_size, ASAN_SHADOW_HEAP_FREE_MAGIC); - - return; -} - // Implement KAsan error reporting routines. static void kasan_print_16_bytes_no_bug(const char *prefix, diff --git a/kasan_common.h b/kasan_common.h new file mode 100644 index 0000000..a3d7d02 --- /dev/null +++ b/kasan_common.h @@ -0,0 +1,41 @@ +/* + * Copyright 2024 Google LLC + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "common.h" +#ifndef __KASAN_COMMON__ +#define __KASAN_COMMON__ + +#define KASAN_SHADOW_SHIFT 3 +#define KASAN_SHADOW_GRANULE_SIZE (1UL << KASAN_SHADOW_SHIFT) +#define KASAN_SHADOW_MASK (KASAN_SHADOW_GRANULE_SIZE - 1) + +#define ASAN_SHADOW_UNPOISONED_MAGIC 0x00 +#define ASAN_SHADOW_RESERVED_MAGIC 0xff +#define ASAN_SHADOW_GLOBAL_REDZONE_MAGIC 0xf9 +#define ASAN_SHADOW_HEAP_HEAD_REDZONE_MAGIC 0xfa +#define ASAN_SHADOW_HEAP_TAIL_REDZONE_MAGIC 0xfb +#define ASAN_SHADOW_HEAP_FREE_MAGIC 0xfd + +#define KASAN_HEAP_HEAD_REDZONE_SIZE 0x20 +#define KASAN_HEAP_TAIL_REDZONE_SIZE 0x20 + +#define KASAN_MEM_TO_SHADOW(addr) \ + (((addr) >> KASAN_SHADOW_SHIFT) + KASAN_SHADOW_MAPPING_OFFSET) +#define KASAN_SHADOW_TO_MEM(shadow) \ + (((shadow) - KASAN_SHADOW_MAPPING_OFFSET) << KASAN_SHADOW_SHIFT) + +void initialize_kasan(void); +void poison_shadow(unsigned long address, size_t size, uint8_t value); +void unpoison_shadow(unsigned long address, size_t size); + +#endif \ No newline at end of file diff --git a/kasan_dlmalloc.c b/kasan_dlmalloc.c new file mode 100644 index 0000000..c8944ab --- /dev/null +++ b/kasan_dlmalloc.c @@ -0,0 +1,443 @@ +#include "heap.h" +#include "kasan_dlmalloc.h" +#include "kasan_common.h" + +static void poison_mem(void *address, size_t size, size_t aligned_size) { + unpoison_shadow((unsigned long)(address + KASAN_HEAP_HEAD_REDZONE_SIZE), size); + poison_shadow((unsigned long)address, KASAN_HEAP_HEAD_REDZONE_SIZE, + ASAN_SHADOW_HEAP_HEAD_REDZONE_MAGIC); + poison_shadow( + (unsigned long)(address + KASAN_HEAP_HEAD_REDZONE_SIZE + aligned_size), + KASAN_HEAP_TAIL_REDZONE_SIZE, ASAN_SHADOW_HEAP_TAIL_REDZONE_MAGIC); +} + +void *sbrk(ptrdiff_t increment) +{ + unsigned long old = mem_malloc_brk; + unsigned long new = old + increment; + + if ((new < mem_malloc_start) || (new > mem_malloc_end)) + return (void *)MORECORE_FAILURE; + + /* + * if we are giving memory back make sure we clear it out since + * we set MORECORE_CLEARS to 1 + */ + if (increment < 0) + memset((void *)new, 0, -increment); + + mem_malloc_brk = new; + + return (void *)old; +} + +// ------------------------------------------------------------------------------------------------------------ +// ---------------------------------------------------------dlmalloc_trim-------------------------------------- +// ------------------------------------------------------------------------------------------------------------ + +int dlmalloc_trim(size_t pad) { + long top_size; /* Amount of top-most memory */ + long extra; /* Amount to release */ + char* current_brk; /* address returned by pre-check sbrk call */ + char* new_brk; /* address returned by negative sbrk call */ + + unsigned long pagesz = malloc_getpagesize; + + top_size = chunksize(top); + extra = ((top_size - pad - MINSIZE + (pagesz-1)) / pagesz - 1) * pagesz; + + if (extra < (long)pagesz) /* Not enough memory to release */ + return 0; + + else { + /* Test to make sure no one else called sbrk */ + current_brk = (char*)(MORECORE (0)); + if (current_brk != (char*)(top) + top_size) + return 0; /* Apparently we don't own memory; must fail */ + else { + new_brk = (char*)(MORECORE (-extra)); + + if (new_brk == (char*)(MORECORE_FAILURE)) /* sbrk failed? */ + { + /* Try to figure out what we have */ + current_brk = (char*)(MORECORE (0)); + top_size = current_brk - (char*)top; + if (top_size >= (long)MINSIZE) /* if not, we are very very dead! */ + { + sbrked_mem = current_brk - sbrk_base; + set_head(top, top_size | PREV_INUSE); + } + return 0; + } else + { + /* Success. Adjust top accordingly. */ + set_head(top, (top_size - extra) | PREV_INUSE); + sbrked_mem -= extra; + return 1; + } + } + } +} + + +// ------------------------------------------------------------------------------------------------------------ +// ------------------------------------------------kasan_dlfree_hook------------------------------------------- +// ------------------------------------------------------------------------------------------------------------ + +void kasan_dlfree_hook(void* mem) { + mchunkptr p; /* chunk corresponding to mem */ + INTERNAL_SIZE_T hd; /* its head field */ + INTERNAL_SIZE_T sz; /* its size */ + int idx; /* its bin index */ + mchunkptr next; /* next contiguous chunk */ + INTERNAL_SIZE_T nextsz; /* its size */ + INTERNAL_SIZE_T prevsz; /* size of previous contiguous chunk */ + mchunkptr bck; /* misc temp for linking */ + mchunkptr fwd; /* misc temp for linking */ + int islr; /* track whether merging with last_remainder */ + + if (mem == NULL) /* free(0) has no effect */ + return; + + p = mem2chunkBeforeRedzone(mem); + hd = p->size; + + sz = hd & ~PREV_INUSE; + next = chunk_at_offset(p, sz); + nextsz = chunksize(next); + if (next == top) /* merge with top */ + { + sz += nextsz; + + if (!(hd & PREV_INUSE)) /* consolidate backward */ + { + prevsz = p->prev_size; + p = chunk_at_offset(p, -((long) prevsz)); + sz += prevsz; + unlink(p, bck, fwd); + } + + set_head(p, sz | PREV_INUSE); + top = p; + if ((unsigned long)(sz) >= (unsigned long)trim_threshold) + dlmalloc_trim(top_pad); + + poison_shadow((unsigned long)chunk2mem(p), chunkUserSize(p), ASAN_SHADOW_HEAP_FREE_MAGIC); + return; + } + + set_head(next, nextsz); /* clear inuse bit */ + + islr = 0; + + if (!(hd & PREV_INUSE)) /* consolidate backward */ + { + prevsz = p->prev_size; + p = chunk_at_offset(p, -((long) prevsz)); + sz += prevsz; + + if (p->fd == last_remainder) /* keep as last_remainder */ + islr = 1; + else + unlink(p, bck, fwd); + } + + if (!(inuse_bit_at_offset(next, nextsz))) { + sz += nextsz; + + if (!islr && next->fd == last_remainder) /* re-insert last_remainder */ + { + islr = 1; + link_last_remainder(p); + } + else + unlink(next, bck, fwd); + } + + set_head(p, sz | PREV_INUSE); + set_foot(p, sz); + if (!islr) + frontlink(p, sz, idx, bck, fwd); + poison_shadow((unsigned long)chunk2mem(p), chunkUserSize(p), ASAN_SHADOW_HEAP_FREE_MAGIC); + +} +// ------------------------------------------------------------------------------------------------------------ +// ----------------------------------------------malloc_extend_top--------------------------------------------- +// ------------------------------------------------------------------------------------------------------------ + +static void malloc_extend_top(INTERNAL_SIZE_T nb) { + char* brk; /* return value from sbrk */ + INTERNAL_SIZE_T front_misalign; /* unusable bytes at front of sbrked space */ + INTERNAL_SIZE_T correction; /* bytes for 2nd sbrk call */ + char* new_brk; /* return of 2nd sbrk call */ + INTERNAL_SIZE_T top_size; /* new size of top chunk */ + + mchunkptr old_top = top; /* Record state of old top */ + INTERNAL_SIZE_T old_top_size = chunksize(old_top); + char* old_end = (char*)(chunk_at_offset(old_top, old_top_size)); + + /* Pad request with top_pad plus minimal overhead */ + + INTERNAL_SIZE_T sbrk_size = nb + top_pad + MINSIZE; + unsigned long pagesz = malloc_getpagesize; + + /* If not the first time through, round to preserve page boundary */ + /* Otherwise, we need to correct to a page size below anyway. */ + /* (We also correct below if an intervening foreign sbrk call.) */ + + if (sbrk_base != (char*)(-1)) + sbrk_size = (sbrk_size + (pagesz - 1)) & ~(pagesz - 1); + + brk = (char*)(MORECORE (sbrk_size)); + + /* Fail if sbrk failed or if a foreign sbrk call killed our space */ + if (brk == (char*)(MORECORE_FAILURE) || (brk < old_end && old_top != initial_top)) return; + + sbrked_mem += sbrk_size; + + if (brk == old_end) { + top_size = sbrk_size + old_top_size; + set_head(top, top_size | PREV_INUSE); + } + else { + if (sbrk_base == (char*)(-1)) sbrk_base = brk; + else sbrked_mem += brk - (char*)old_end; + + front_misalign = (unsigned long)chunk2mem(brk) & MALLOC_ALIGN_MASK; + if (front_misalign > 0) { + correction = (MALLOC_ALIGNMENT) - front_misalign; + brk += correction; + } + else correction = 0; + correction += ((((unsigned long)(brk + sbrk_size))+(pagesz-1)) & + ~(pagesz - 1)) - ((unsigned long)(brk + sbrk_size)); + + /* Allocate correction */ + new_brk = (char*)(MORECORE (correction)); + if (new_brk == (char*)(MORECORE_FAILURE)) return; + + sbrked_mem += correction; + + top = (mchunkptr)brk; + top_size = new_brk - brk + correction; + set_head(top, top_size | PREV_INUSE); + + if (old_top != initial_top) + { + + /* There must have been an intervening foreign sbrk call. */ + /* A double fencepost is necessary to prevent consolidation */ + + /* If not enough space to do this, then user did something very wrong */ + if (old_top_size < MINSIZE) + { + set_head(top, PREV_INUSE); /* will force null return from malloc */ + return; + } + + /* Also keep size a multiple of MALLOC_ALIGNMENT */ + old_top_size = (old_top_size - 3*SIZE_SZ) & ~MALLOC_ALIGN_MASK; + set_head_size(old_top, old_top_size); + chunk_at_offset(old_top, old_top_size)->size = SIZE_SZ|PREV_INUSE; + chunk_at_offset(old_top, old_top_size + SIZE_SZ)->size =SIZE_SZ|PREV_INUSE; + /* If possible, release the rest. */ + if (old_top_size >= MINSIZE) kasan_dlfree_hook(chunk2memAfterRedzone(old_top)); + } + } + + if ((unsigned long)sbrked_mem > (unsigned long)max_sbrked_mem) + max_sbrked_mem = sbrked_mem; + if ((unsigned long)(mmapped_mem + sbrked_mem) > (unsigned long)max_total_mem) + max_total_mem = mmapped_mem + sbrked_mem; + + /* We always land on a page boundary */ +} + +// ------------------------------------------------------------------------------------------------------------ +// -------------------------------------------------------dlmalloc--------------------------------------------- +// ------------------------------------------------------------------------------------------------------------ + +void *kasan_dlmalloc_hook(size_t bytes) { + mchunkptr victim; /* inspected/selected chunk */ + INTERNAL_SIZE_T victim_size; /* its size */ + int idx; /* index for bin traversal */ + mbinptr bin; /* associated bin */ + mchunkptr remainder; /* remainder from a split */ + long remainder_size; /* its size */ + int remainder_index; /* its bin index */ + unsigned long block; /* block traverser bit */ + int startidx; /* first bin of a traversed block */ + mchunkptr fwd; /* misc temp for linking */ + mchunkptr bck; /* misc temp for linking */ + mbinptr q; /* misc temp */ + + INTERNAL_SIZE_T nb; + /* check if initialize_dlmalloc_heap() was run */ + + if ((mem_malloc_start == 0) && (mem_malloc_end == 0)) { + return NULL; + } + + if (bytes > HEAP_SIZE || (long)bytes < 0) return NULL; + + nb = request2size(bytes); /* padded request size; */ + unsigned int total_kasan_size = nb + \ + KASAN_HEAP_HEAD_REDZONE_SIZE + \ + KASAN_HEAP_TAIL_REDZONE_SIZE; + + if (is_small_request(total_kasan_size)) /* Faster version for small requests */ { + idx = smallbin_index(total_kasan_size); + /* No traversal or size check necessary for small bins. */ + + q = bin_at(idx); + victim = last(q); + + if (victim == q) { + q = next_bin(q); + victim = last(q); + } + if (victim != q) { + victim_size = chunksize(victim); // here we have to find the KASAN chunk size adding REDZONES back and forth + unlink(victim, bck, fwd); // KASAN does not need to do anything + set_inuse_bit_at_offset(victim, victim_size); // ??? probably not anything to do here + + poison_mem(chunk2mem(victim), bytes, nb); + return chunk2memAfterRedzone(victim); + } + + idx += 2; + } + else { + idx = bin_index(total_kasan_size); + bin = bin_at(idx); + + for (victim = last(bin); victim != bin; victim = victim->bk) + { + victim_size = chunksize(victim); + + remainder_size = victim_size - total_kasan_size; + + if (remainder_size >= (long)MINSIZE) { + --idx; + break; + } else if (remainder_size >= 0) { + + unlink(victim, bck, fwd); + set_inuse_bit_at_offset(victim, victim_size); + poison_mem(chunk2mem(victim), bytes, nb); + return chunk2memAfterRedzone(victim); + } + } + ++idx; + } + + if ( (victim = last_remainder->fd) != last_remainder) + { + victim_size = chunksize(victim); + + remainder_size = victim_size - total_kasan_size; + + if (remainder_size >= (long)MINSIZE){ + remainder = chunk_at_offset(victim, total_kasan_size); + set_head(victim, total_kasan_size | PREV_INUSE); + link_last_remainder(remainder); + set_head(remainder, remainder_size | PREV_INUSE); + set_foot(remainder, remainder_size); + + poison_mem(chunk2mem(victim), bytes, nb); + return chunk2memAfterRedzone(victim); + } + + clear_last_remainder; + + if (remainder_size >= 0) { + set_inuse_bit_at_offset(victim, victim_size); + + poison_mem(chunk2mem(victim), bytes, nb); + return chunk2memAfterRedzone(victim); + } + + frontlink(victim, victim_size, remainder_index, bck, fwd); + } + + + if ( (block = idx2binblock(idx)) <= binblocks_r) { + + if ( (block & binblocks_r) == 0){ + idx = (idx & ~(BINBLOCKWIDTH - 1)) + BINBLOCKWIDTH; + block <<= 1; + while ((block & binblocks_r) == 0) + { + idx += BINBLOCKWIDTH; + block <<= 1; + } + } + + for (;;) { + startidx = idx; + q = bin = bin_at(idx); + + /* For each bin in this block ... */ + do { + for (victim = last(bin); victim != bin; victim = victim->bk) { + victim_size = chunksize(victim); + + remainder_size = victim_size - total_kasan_size; + + if (remainder_size >= (long)MINSIZE) { + remainder = chunk_at_offset(victim, total_kasan_size); + set_head(victim, total_kasan_size | PREV_INUSE); + unlink(victim, bck, fwd); + link_last_remainder(remainder); + set_head(remainder, remainder_size | PREV_INUSE); + set_foot(remainder, remainder_size); + + poison_mem(chunk2mem(victim), bytes, nb); + return chunk2memAfterRedzone(victim); + } else if (remainder_size >= 0) { + set_inuse_bit_at_offset(victim, victim_size); + unlink(victim, bck, fwd); + + poison_mem(chunk2mem(victim), bytes, nb); + return chunk2memAfterRedzone(victim); + } + } + + bin = next_bin(bin); + + } while ((++idx & (BINBLOCKWIDTH - 1)) != 0); + + do { + if ((startidx & (BINBLOCKWIDTH - 1)) == 0) { + av_[1] = (mbinptr)(binblocks_r & ~block); + break; + } + --startidx; + q = prev_bin(q); + } while (first(q) == q); + if ( (block <<= 1) <= binblocks_r && (block != 0) ) { + while ((block & binblocks_r) == 0) { + idx += BINBLOCKWIDTH; + block <<= 1; + } + } + else break; + } + } + + /* Require that there be a remainder, ensuring top always exists */ + if ( (remainder_size = chunksize(top) - total_kasan_size) < (long)MINSIZE) { + + malloc_extend_top(total_kasan_size); + if ( (remainder_size = chunksize(top) - total_kasan_size) < (long)MINSIZE) + return NULL; /* propagate failure */ + } + victim = top; + set_head(victim, total_kasan_size | PREV_INUSE); + top = chunk_at_offset(victim, total_kasan_size); + set_head(top, remainder_size | PREV_INUSE); + poison_mem(chunk2mem(victim), bytes, nb); + + return chunk2memAfterRedzone(victim); +} + diff --git a/kasan_dlmalloc.h b/kasan_dlmalloc.h new file mode 100644 index 0000000..6b84746 --- /dev/null +++ b/kasan_dlmalloc.h @@ -0,0 +1,334 @@ +#include "kasan_common.h" +#include "heap.h" +#include "common.h" + +#ifndef __KASAN_DLMALLOC_H__ +#define __KASAN_DLMALLOC_H__ + +#define INTERNAL_SIZE_T size_t + +struct malloc_chunk +{ + INTERNAL_SIZE_T prev_size; /* Size of previous chunk (if free). */ + INTERNAL_SIZE_T size; /* Size in bytes, including overhead. */ + struct malloc_chunk* fd; /* double links -- used only if free. */ + struct malloc_chunk* bk; +} __attribute__((__may_alias__)) ; + +#define HEAP_SIZE 0x10000 + +typedef struct malloc_chunk* mchunkptr; +typedef struct malloc_chunk* mbinptr; + +#define SIZE_SZ (sizeof(INTERNAL_SIZE_T)) +#define MALLOC_ALIGNMENT (SIZE_SZ + SIZE_SZ) +#define MALLOC_ALIGN_MASK (MALLOC_ALIGNMENT - 1) +#define MINSIZE (sizeof(struct malloc_chunk)) + +/* conversion from malloc headers to user pointers, and back */ +#define chunk2mem(p) ((void*)((char*)(p) + 2*SIZE_SZ)) +#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - 2*SIZE_SZ)) + +#define chunk2memAfterRedzone(p) ((void*)((char*)(p) + 2*SIZE_SZ + KASAN_HEAP_HEAD_REDZONE_SIZE)) +#define mem2chunkBeforeRedzone(mem) ((mchunkptr)((char*)(mem) - 2*SIZE_SZ - KASAN_HEAP_HEAD_REDZONE_SIZE)) + +/* pad request bytes into a usable size */ + +#define request2size(req) \ + ((((req) + (SIZE_SZ + MALLOC_ALIGN_MASK)) < \ + (MINSIZE + MALLOC_ALIGN_MASK)) ? MINSIZE : \ + (((req) + (SIZE_SZ + MALLOC_ALIGN_MASK)) & ~(MALLOC_ALIGN_MASK))) + +/* Check if m has acceptable alignment */ + +#define aligned_OK(m) (((unsigned long)((m)) & (MALLOC_ALIGN_MASK)) == 0) + +/* + Physical chunk operations +*/ + +/* size field is or'ed with PREV_INUSE when previous adjacent chunk in use */ + +#define PREV_INUSE 0x1 + +/* size field is or'ed with IS_MMAPPED if the chunk was obtained with mmap() */ + +#define IS_MMAPPED 0x2 + +/* Bits to mask off when extracting size */ + +#define SIZE_BITS (PREV_INUSE|IS_MMAPPED) + +/* Ptr to next physical malloc_chunk. */ + +#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->size & ~PREV_INUSE) )) + +/* Ptr to previous physical malloc_chunk */ + +#define prev_chunk(p)\ + ((mchunkptr)( ((char*)(p)) - ((p)->prev_size) )) + +/* Treat space at ptr + offset as a chunk */ + +#define chunk_at_offset(p, s) ((mchunkptr)(((char*)(p)) + (s))) + +/* + Dealing with use bits +*/ + +/* extract p's inuse bit */ + +#define inuse(p)\ +((((mchunkptr)(((char*)(p))+((p)->size & ~PREV_INUSE)))->size) & PREV_INUSE) + +/* extract inuse bit of previous chunk */ + +#define prev_inuse(p) ((p)->size & PREV_INUSE) + +/* check for mmap()'ed chunk */ + +#define chunk_is_mmapped(p) ((p)->size & IS_MMAPPED) + +/* set/clear chunk as in use without otherwise disturbing */ + +#define set_inuse(p)\ +((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size |= PREV_INUSE + +#define clear_inuse(p)\ +((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size &= ~(PREV_INUSE) + +/* check/set/clear inuse bits in known places */ + +#define inuse_bit_at_offset(p, s)\ + (((mchunkptr)(((char*)(p)) + (s)))->size & PREV_INUSE) + +#define set_inuse_bit_at_offset(p, s)\ + (((mchunkptr)(((char*)(p)) + (s)))->size |= PREV_INUSE) + +#define clear_inuse_bit_at_offset(p, s)\ + (((mchunkptr)(((char*)(p)) + (s)))->size &= ~(PREV_INUSE)) + +/* + Dealing with size fields +*/ + +/* Get size of usable space*/ + +#define chunkUserSize(p) ((p)->size - 2*SIZE_SZ) + +/* Get size, ignoring use bits */ + +#define chunksize(p) ((p)->size & ~(SIZE_BITS)) + +/* Set size at head, without disturbing its use bit */ + +#define set_head_size(p, s) ((p)->size = (((p)->size & PREV_INUSE) | (s))) + +/* Set size/use ignoring previous bits in header */ + +#define set_head(p, s) ((p)->size = (s)) + +/* Set size at footer (only when chunk is not in use) */ + +#define set_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_size = (s)) + +/* + Bins + + The bins, `av_' are an array of pairs of pointers serving as the + heads of (initially empty) doubly-linked lists of chunks, laid out + in a way so that each pair can be treated as if it were in a + malloc_chunk. (This way, the fd/bk offsets for linking bin heads + and chunks are the same). + + Bins for sizes < 512 bytes contain chunks of all the same size, spaced + 8 bytes apart. Larger bins are approximately logarithmically + spaced. (See the table below.) The `av_' array is never mentioned + directly in the code, but instead via bin access macros. + + Bin layout: + + 64 bins of size 8 + 32 bins of size 64 + 16 bins of size 512 + 8 bins of size 4096 + 4 bins of size 32768 + 2 bins of size 262144 + 1 bin of size what's left + + There is actually a little bit of slop in the numbers in bin_index + for the sake of speed. This makes no difference elsewhere. + + The special chunks `top' and `last_remainder' get their own bins, + (this is implemented via yet more trickery with the av_ array), + although `top' is never properly linked to its bin since it is + always handled specially. + +*/ + +#define NAV 128 /* number of bins */ + +typedef struct malloc_chunk* mbinptr; + +/* access macros */ + +#define bin_at(i) ((mbinptr)((char*)&(av_[2*(i) + 2]) - 2*SIZE_SZ)) +#define next_bin(b) ((mbinptr)((char*)(b) + 2 * sizeof(mbinptr))) +#define prev_bin(b) ((mbinptr)((char*)(b) - 2 * sizeof(mbinptr))) + +/* + The first 2 bins are never indexed. The corresponding av_ cells are instead + used for bookkeeping. This is not to save space, but to simplify + indexing, maintain locality, and avoid some initialization tests. +*/ + +#define top (av_[2]) /* The topmost chunk */ +#define last_remainder (bin_at(1)) /* remainder from last split */ + +/* + Because top initially points to its own bin with initial + zero size, thus forcing extension on the first malloc request, + we avoid having any special code in malloc to check whether + it even exists yet. But we still need to in malloc_extend_top. +*/ + +#define initial_top ((mchunkptr)(bin_at(0))) + +/* Helper macro to initialize bins */ + +#define IAV(i) bin_at(i), bin_at(i) + +static mbinptr av_[NAV * 2 + 2] = { + NULL, NULL, + IAV(0), IAV(1), IAV(2), IAV(3), IAV(4), IAV(5), IAV(6), IAV(7), + IAV(8), IAV(9), IAV(10), IAV(11), IAV(12), IAV(13), IAV(14), IAV(15), + IAV(16), IAV(17), IAV(18), IAV(19), IAV(20), IAV(21), IAV(22), IAV(23), + IAV(24), IAV(25), IAV(26), IAV(27), IAV(28), IAV(29), IAV(30), IAV(31), + IAV(32), IAV(33), IAV(34), IAV(35), IAV(36), IAV(37), IAV(38), IAV(39), + IAV(40), IAV(41), IAV(42), IAV(43), IAV(44), IAV(45), IAV(46), IAV(47), + IAV(48), IAV(49), IAV(50), IAV(51), IAV(52), IAV(53), IAV(54), IAV(55), + IAV(56), IAV(57), IAV(58), IAV(59), IAV(60), IAV(61), IAV(62), IAV(63), + IAV(64), IAV(65), IAV(66), IAV(67), IAV(68), IAV(69), IAV(70), IAV(71), + IAV(72), IAV(73), IAV(74), IAV(75), IAV(76), IAV(77), IAV(78), IAV(79), + IAV(80), IAV(81), IAV(82), IAV(83), IAV(84), IAV(85), IAV(86), IAV(87), + IAV(88), IAV(89), IAV(90), IAV(91), IAV(92), IAV(93), IAV(94), IAV(95), + IAV(96), IAV(97), IAV(98), IAV(99), IAV(100), IAV(101), IAV(102), IAV(103), + IAV(104), IAV(105), IAV(106), IAV(107), IAV(108), IAV(109), IAV(110), IAV(111), + IAV(112), IAV(113), IAV(114), IAV(115), IAV(116), IAV(117), IAV(118), IAV(119), + IAV(120), IAV(121), IAV(122), IAV(123), IAV(124), IAV(125), IAV(126), IAV(127) +}; + +/* field-extraction macros */ + +#define first(b) ((b)->fd) +#define last(b) ((b)->bk) + +/* + Indexing into bins +*/ + +#define bin_index(sz) \ +(((((unsigned long)(sz)) >> 9) == 0) ? (((unsigned long)(sz)) >> 3): \ + ((((unsigned long)(sz)) >> 9) <= 4) ? 56 + (((unsigned long)(sz)) >> 6): \ + ((((unsigned long)(sz)) >> 9) <= 20) ? 91 + (((unsigned long)(sz)) >> 9): \ + ((((unsigned long)(sz)) >> 9) <= 84) ? 110 + (((unsigned long)(sz)) >> 12): \ + ((((unsigned long)(sz)) >> 9) <= 340) ? 119 + (((unsigned long)(sz)) >> 15): \ + ((((unsigned long)(sz)) >> 9) <= 1364) ? 124 + (((unsigned long)(sz)) >> 18): \ + 126) + +#define MAX_SMALLBIN 63 +#define MAX_SMALLBIN_SIZE 512 +#define SMALLBIN_WIDTH 8 +#define smallbin_index(sz) (((unsigned long)(sz)) >> 3) +#define is_small_request(nb) (nb < MAX_SMALLBIN_SIZE - SMALLBIN_WIDTH) + +#define frontlink(P, S, IDX, BK, FD) \ +{ \ + if (S < MAX_SMALLBIN_SIZE) \ + { \ + IDX = smallbin_index(S); \ + mark_binblock(IDX); \ + BK = bin_at(IDX); \ + FD = BK->fd; \ + P->bk = BK; \ + P->fd = FD; \ + FD->bk = BK->fd = P; \ + } \ + else \ + { \ + IDX = bin_index(S); \ + BK = bin_at(IDX); \ + FD = BK->fd; \ + if (FD == BK) mark_binblock(IDX); \ + else \ + { \ + while (FD != BK && S < chunksize(FD)) FD = FD->fd; \ + BK = FD->bk; \ + } \ + P->bk = BK; \ + P->fd = FD; \ + FD->bk = BK->fd = P; \ + } \ +} + +#define link_last_remainder(P) \ +{ \ + last_remainder->fd = last_remainder->bk = P; \ + P->fd = P->bk = last_remainder; \ +} + +#define unlink(P, BK, FD) \ +{ \ + BK = P->bk; \ + FD = P->fd; \ + FD->bk = BK; \ + BK->fd = FD; \ +} + +#define aligned_OK(m) (((unsigned long)((m)) & (MALLOC_ALIGN_MASK)) == 0) +#define clear_last_remainder \ + (last_remainder->fd = last_remainder->bk = last_remainder) + +#define BINBLOCKWIDTH 4 /* bins per block */ +#define binblocks_r ((INTERNAL_SIZE_T)av_[1]) /* bitvector of nonempty blocks */ +#define binblocks_w (av_[1]) +#define idx2binblock(ix) ((unsigned)1 << (ix / BINBLOCKWIDTH)) +#define mark_binblock(ii) (binblocks_w = (mbinptr)(binblocks_r | idx2binblock(ii))) +#define clear_binblock(ii) (binblocks_w = (mbinptr)(binblocks_r & ~(idx2binblock(ii)))) + +#define DEFAULT_TRIM_THRESHOLD (128 * 1024) +#define DEFAULT_TOP_PAD (0) + +static unsigned long trim_threshold = DEFAULT_TRIM_THRESHOLD; +static unsigned long top_pad = DEFAULT_TOP_PAD; + + +#define malloc_getpagesize 4096 +#define MORECORE sbrk +#define MORECORE_FAILURE 0 +#define MORECORE_CLEARS 1 + +struct mallinfo { + int arena; /* total space allocated from system */ + int ordblks; /* number of non-inuse chunks */ + int smblks; /* unused -- always zero */ + int hblks; /* number of mmapped regions */ + int hblkhd; /* total space in mmapped regions */ + int usmblks; /* unused -- always zero */ + int fsmblks; /* unused -- always zero */ + int uordblks; /* total allocated space */ + int fordblks; /* total non-inuse space */ + int keepcost; /* top-most, releasable (via malloc_trim) space */ +}; + +static struct mallinfo current_mallinfo = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +static char* sbrk_base = (char*)(-1); + +#define sbrked_mem (current_mallinfo.arena) +static unsigned long max_sbrked_mem = 0; +static unsigned long mmapped_mem = 0; +static unsigned long max_total_mem = 0; + +void kasan_dlfree_hook(void* mem); +void *kasan_dlmalloc_hook(size_t bytes); +#endif // __KASAN_HEAP_H__ \ No newline at end of file diff --git a/kasan_simple_malloc.c b/kasan_simple_malloc.c new file mode 100644 index 0000000..d7a5dfa --- /dev/null +++ b/kasan_simple_malloc.c @@ -0,0 +1,52 @@ +#include "heap.h" +#include "common.h" +#include "kasan_common.h" +#include "kasan_simple_malloc.h" + +void *allocate_chunk(unsigned long size) { + void *result = (void *)mem_malloc_start; + if (size > mem_malloc_size) return NULL; + + size = (size + 7) & (~7UL); + mem_malloc_start += size; + mem_malloc_size -= size; + return result; +} + +void *kasan_malloc_hook(unsigned int size) { + struct KASAN_HEAP_HEADER *kasan_heap_hdr = NULL; + unsigned int algined_size = (size + KASAN_SHADOW_MASK) & (~KASAN_SHADOW_MASK); + unsigned int total_size = algined_size + KASAN_HEAP_HEAD_REDZONE_SIZE + + KASAN_HEAP_TAIL_REDZONE_SIZE; + + void *ptr = allocate_chunk(total_size); + if (ptr == NULL) return NULL; + + kasan_heap_hdr = (struct KASAN_HEAP_HEADER *)ptr; + kasan_heap_hdr->aligned_size = algined_size; + + unpoison_shadow((unsigned long)(ptr + KASAN_HEAP_HEAD_REDZONE_SIZE), size); + poison_shadow((unsigned long)ptr, KASAN_HEAP_HEAD_REDZONE_SIZE, + ASAN_SHADOW_HEAP_HEAD_REDZONE_MAGIC); + poison_shadow( + (unsigned long)(ptr + KASAN_HEAP_HEAD_REDZONE_SIZE + algined_size), + KASAN_HEAP_TAIL_REDZONE_SIZE, ASAN_SHADOW_HEAP_TAIL_REDZONE_MAGIC); + + return ptr + KASAN_HEAP_HEAD_REDZONE_SIZE; +} + +void kasan_free_hook(void *ptr) { + struct KASAN_HEAP_HEADER *kasan_heap_hdr = NULL; + unsigned int aligned_size = 0; + + if (ptr == NULL) return; + + kasan_heap_hdr = + (struct KASAN_HEAP_HEADER *)(ptr - KASAN_HEAP_HEAD_REDZONE_SIZE); + aligned_size = kasan_heap_hdr->aligned_size; + + free_chunk(kasan_heap_hdr); + poison_shadow((unsigned long)ptr, aligned_size, ASAN_SHADOW_HEAP_FREE_MAGIC); + + return; +} \ No newline at end of file diff --git a/kasan_simple_malloc.h b/kasan_simple_malloc.h new file mode 100644 index 0000000..67deae9 --- /dev/null +++ b/kasan_simple_malloc.h @@ -0,0 +1,12 @@ + +#ifndef __KASAN_SIMPLE_MALLOC__ +#define __KASAN_SIMPLE_MALLOC__ + +struct KASAN_HEAP_HEADER { + unsigned int aligned_size; +}; + +void *kasan_malloc_hook(unsigned int size); +void kasan_free_hook(void *ptr); + +#endif // __KASAN_SIMPLE_MALLOC__ \ No newline at end of file diff --git a/kasan_test b/kasan_test new file mode 100755 index 0000000000000000000000000000000000000000..1de5dd34eb5bbe4d306b5dc1364b7de7b5aaef00 GIT binary patch literal 54856 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
  • w`>j!0*ruW_LSa*fJ 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 z Date: Wed, 14 May 2025 02:04:16 +0300 Subject: [PATCH 2/6] add docs --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 567d872..f73239d 100644 --- a/README.md +++ b/README.md @@ -26,14 +26,13 @@ sudo apt-get install build-essential gcc-multilib llvm clang lld \ qemu-system-arm qemu-system-misc qemu-system-x86 ``` -## Project layout +## Project layout (with dlmalloc) The project constists of the following components: * `kasan_test.c` -- main test driver which runs KASan test cases * `sanitized_lib.c` -- this module implements the test cases and is built with the KASan instrumentation -* `kasan.c` -- implementation of runtime routines needed for KASan sanitizer * `heap.c` -- simple implementation of heap management routines for testing KASan * `third_party/printf.c` -- a compact implementation of `printf` function @@ -48,6 +47,11 @@ The project constists of the following components: * `Makefile.arch` -- Makefile fragments whith architecture-specific parameters for building and running the project in the emulator +New files for `dlmalloc`: +* `kasan_common.c` -- implementation of common runtime routines needed for KASan sanitizer +* `kasan_simple_malloc.c` -- implementation of KASan runtime routines for simple malloc +* `kasan_common.c` -- implementation of KASan runtime routines for dlmalloc + ## Running From 719ecdcce97cc8d9524d2fa82944d6fb617870ff Mon Sep 17 00:00:00 2001 From: Dimitris Oikonomou Date: Wed, 14 May 2025 02:18:05 +0300 Subject: [PATCH 3/6] credits to original author --- README.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index f73239d..3de9f4e 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,9 @@ -# Bare-metal KASan implementation +# Bare-metal KASan implementation with dlmalloc + +This fork of [baremetal_kasan](https://github.com/androidoffsec/baremetal_kasan), originally created by Google Project Zero member [Eugene Rodionov](https://github.com/rodionov), adds a simple implementation of the [Doug Lea malloc allocator](https://gee.cs.oswego.edu/dl/html/malloc.html) with KASan support. +This is an experimental project that I implemented while working on integrating KASan into U-Boot. + +## Bare-metal KASan implementation *This is not an officially supported Google product.* @@ -12,7 +17,7 @@ the corresponding implementation of [KASan](https://www.kernel.org/doc/html/v4.14/dev-tools/kasan.html) in Linux kernel. -## Prerequisites +### Prerequisites To build and run the program you would need to use LLVM toolchain (`clang` and `ld.lld`) for cross complitation and QEMU system emulator for supported @@ -26,7 +31,7 @@ sudo apt-get install build-essential gcc-multilib llvm clang lld \ qemu-system-arm qemu-system-misc qemu-system-x86 ``` -## Project layout (with dlmalloc) +### Project layout (with dlmalloc) The project constists of the following components: @@ -53,7 +58,7 @@ New files for `dlmalloc`: * `kasan_common.c` -- implementation of KASan runtime routines for dlmalloc -## Running +### Running To build and execute the test suite run `ARCH=target_arch make clean run` where `target_arch` is one of the supported architectures: `arm`, `aarch64`, From e856c97a0b23302ee7ca3529a8b16f125418dd2b Mon Sep 17 00:00:00 2001 From: Dimitris Oikonomou Date: Wed, 14 May 2025 02:24:54 +0300 Subject: [PATCH 4/6] remove .vscode --- .gitignore | 3 +- .vscode/c_cpp_properties.json | 18 ---------- .vscode/launch.json | 24 ------------- .vscode/settings.json | 68 ----------------------------------- 4 files changed, 2 insertions(+), 111 deletions(-) delete mode 100644 .vscode/c_cpp_properties.json delete mode 100644 .vscode/launch.json delete mode 100644 .vscode/settings.json diff --git a/.gitignore b/.gitignore index 2c352e5..ce9cf3e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ *.o -*.su \ No newline at end of file +*.su +.vscode/ \ No newline at end of file diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json deleted file mode 100644 index c2098a2..0000000 --- a/.vscode/c_cpp_properties.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "configurations": [ - { - "name": "linux-gcc-x64", - "includePath": [ - "${workspaceFolder}/**" - ], - "compilerPath": "/usr/bin/gcc", - "cStandard": "${default}", - "cppStandard": "${default}", - "intelliSenseMode": "linux-gcc-x64", - "compilerArgs": [ - "" - ] - } - ], - "version": 4 -} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 79e3643..0000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "version": "0.2.0", - "configurations": [ - { - "name": "C/C++ Runner: Debug Session", - "type": "cppdbg", - "request": "launch", - "args": [], - "stopAtEntry": false, - "externalConsole": false, - "cwd": "/home/dimeko/dev/brm_kasan", - "program": "/home/dimeko/dev/brm_kasan/build/Debug/outDebug", - "MIMode": "gdb", - "miDebuggerPath": "gdb", - "setupCommands": [ - { - "description": "Enable pretty-printing for gdb", - "text": "-enable-pretty-printing", - "ignoreFailures": true - } - ] - } - ] -} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index a98c014..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "C_Cpp_Runner.cCompilerPath": "gcc", - "C_Cpp_Runner.cppCompilerPath": "g++", - "C_Cpp_Runner.debuggerPath": "gdb", - "C_Cpp_Runner.cStandard": "", - "C_Cpp_Runner.cppStandard": "", - "C_Cpp_Runner.msvcBatchPath": "", - "C_Cpp_Runner.useMsvc": false, - "C_Cpp_Runner.warnings": [ - "-Wall", - "-Wextra", - "-Wpedantic", - "-Wshadow", - "-Wformat=2", - "-Wcast-align", - "-Wconversion", - "-Wsign-conversion", - "-Wnull-dereference" - ], - "C_Cpp_Runner.msvcWarnings": [ - "/W4", - "/permissive-", - "/w14242", - "/w14287", - "/w14296", - "/w14311", - "/w14826", - "/w44062", - "/w44242", - "/w14905", - "/w14906", - "/w14263", - "/w44265", - "/w14928" - ], - "C_Cpp_Runner.enableWarnings": true, - "C_Cpp_Runner.warningsAsError": false, - "C_Cpp_Runner.compilerArgs": [], - "C_Cpp_Runner.linkerArgs": [], - "C_Cpp_Runner.includePaths": [], - "C_Cpp_Runner.includeSearch": [ - "*", - "**/*" - ], - "C_Cpp_Runner.excludeSearch": [ - "**/build", - "**/build/**", - "**/.*", - "**/.*/**", - "**/.vscode", - "**/.vscode/**" - ], - "C_Cpp_Runner.useAddressSanitizer": false, - "C_Cpp_Runner.useUndefinedSanitizer": false, - "C_Cpp_Runner.useLeakSanitizer": false, - "C_Cpp_Runner.showCompilationTime": false, - "C_Cpp_Runner.useLinkTimeOptimization": false, - "C_Cpp_Runner.msvcSecureNoWarnings": false, - "files.associations": { - "dlmalloc.h": "c", - "kasan.h": "c", - "common.h": "c", - "heap.h": "c", - "kasan_dlmalloc.h": "c", - "kasan_common.h": "c", - "stdint.h": "c" - } -} \ No newline at end of file From 8d70e0f5bcaa1a3c1be90cde5550906a2df0a5db Mon Sep 17 00:00:00 2001 From: Dimitris Oikonomou Date: Wed, 14 May 2025 02:26:39 +0300 Subject: [PATCH 5/6] remove kasan_test.lds --- .gitignore | 3 ++- kasan_test.lds | 27 --------------------------- 2 files changed, 2 insertions(+), 28 deletions(-) delete mode 100644 kasan_test.lds diff --git a/.gitignore b/.gitignore index ce9cf3e..fb48e8b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *.o *.su -.vscode/ \ No newline at end of file +.vscode/ +kasan_test.lds \ No newline at end of file diff --git a/kasan_test.lds b/kasan_test.lds deleted file mode 100644 index 1b11f54..0000000 --- a/kasan_test.lds +++ /dev/null @@ -1,27 +0,0 @@ -OUTPUT_FORMAT("elf64-littleriscv", "elf64-littleriscv", "elf64-littleriscv") -OUTPUT_ARCH(riscv) -ENTRY(reset_handler) -SECTIONS -{ - . = 0x80000000; - .start : { *(.reset) } - .text : { *(.text) } - .rodata : { *(.rodata*) } - .init_array : { - __global_ctors_start = .; - *(.init_array*) - __global_ctors_end = .; - } - .data : { *(.data) } - .bss : { *(.bss COMMON) } - . = ALIGN(0x1000); - __heap_start = .; - . = . + 0x10000; - __heap_end = .; - . = . + 0x1000; - __stack_top = .; - . = 0x87000000; - __kasan_shadow_memory_start = .; - . = . + 0x2000000; - __kasan_shadow_memory_end = .; -} From 37bb8f70cb1f0fa027c6cfd5e1493d146b8adbcc Mon Sep 17 00:00:00 2001 From: Dimitris Oikonomou Date: Wed, 14 May 2025 02:38:28 +0300 Subject: [PATCH 6/6] revert readme --- README.md | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 3de9f4e..28685e1 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,4 @@ -# Bare-metal KASan implementation with dlmalloc - -This fork of [baremetal_kasan](https://github.com/androidoffsec/baremetal_kasan), originally created by Google Project Zero member [Eugene Rodionov](https://github.com/rodionov), adds a simple implementation of the [Doug Lea malloc allocator](https://gee.cs.oswego.edu/dl/html/malloc.html) with KASan support. -This is an experimental project that I implemented while working on integrating KASan into U-Boot. - -## Bare-metal KASan implementation +# Bare-metal KASan implementation *This is not an officially supported Google product.* @@ -17,7 +12,7 @@ the corresponding implementation of [KASan](https://www.kernel.org/doc/html/v4.14/dev-tools/kasan.html) in Linux kernel. -### Prerequisites +## Prerequisites To build and run the program you would need to use LLVM toolchain (`clang` and `ld.lld`) for cross complitation and QEMU system emulator for supported @@ -31,7 +26,7 @@ sudo apt-get install build-essential gcc-multilib llvm clang lld \ qemu-system-arm qemu-system-misc qemu-system-x86 ``` -### Project layout (with dlmalloc) +## Project layout (with dlmalloc) The project constists of the following components: @@ -52,13 +47,13 @@ The project constists of the following components: * `Makefile.arch` -- Makefile fragments whith architecture-specific parameters for building and running the project in the emulator -New files for `dlmalloc`: +Files for `malloc`: * `kasan_common.c` -- implementation of common runtime routines needed for KASan sanitizer * `kasan_simple_malloc.c` -- implementation of KASan runtime routines for simple malloc * `kasan_common.c` -- implementation of KASan runtime routines for dlmalloc -### Running +## Running To build and execute the test suite run `ARCH=target_arch make clean run` where `target_arch` is one of the supported architectures: `arm`, `aarch64`,