From a3da864de82ffc2a7f3c932c667c5ce2f1eb7b8a Mon Sep 17 00:00:00 2001 From: Matheus Date: Sun, 23 Jul 2023 01:06:22 -0300 Subject: [PATCH] memory management: add more protection against corruption --- kernel-src/mm/alloc.c | 22 +++++++++++++++++++--- kernel-src/mm/pmm.c | 14 +++++++++++++- kernel-src/mm/slab.c | 4 ++-- 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/kernel-src/mm/alloc.c b/kernel-src/mm/alloc.c index 97620432..81336506 100644 --- a/kernel-src/mm/alloc.c +++ b/kernel-src/mm/alloc.c @@ -7,16 +7,31 @@ // ptr: data capacity (allocsizes size) // ptr + sizeof(size_t): current size // ptr + sizeof(size_t) * 2: data +// ptr + datasize: poison value +#define USE_POISON 0 +#define POISON_VALUE 0xdeadbeefbadc0ffel #define CACHE_COUNT 12 +#define CAPACITY_SIZE(cache) cache->size - sizeof(size_t) * 2 - USE_POISON * sizeof(size_t) + static size_t allocsizes[CACHE_COUNT] = {32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536}; static scache_t *caches[CACHE_COUNT]; static void initarea(scache_t *cache, void *obj) { size_t *ptr = obj; - *ptr = cache->size - sizeof(size_t) * 2; + *ptr = CAPACITY_SIZE(cache); memset(ptr + 2, 0, *ptr); + #if USE_POISON == 1 + *((size_t *)((uintptr_t)obj + cache->size - sizeof(size_t))) = POISON_VALUE; + #endif +} + +static void dtor(scache_t *cache, void *obj) { +#if USE_POISON == 1 + __assert(*(size_t *)((uintptr_t)obj + cache->size - sizeof(size_t)) == POISON_VALUE); +#endif + initarea(cache, obj); } static scache_t *getcachefromsize(size_t size) { @@ -34,9 +49,10 @@ static scache_t *getcachefromsize(size_t size) { void *alloc(size_t size) { scache_t *cache = getcachefromsize(size); size_t *ret = slab_allocate(cache); - *(ret + 1) = size; if (ret == NULL) return NULL; + __assert(*ret == CAPACITY_SIZE(cache)); + *(ret + 1) = size; return ret + 2; } @@ -81,7 +97,7 @@ void *realloc(void *ptr, size_t size) { void alloc_init() { for (int i = 0; i < CACHE_COUNT; ++i) { - caches[i] = slab_newcache(allocsizes[i] + sizeof(size_t) * 2, 0, initarea, initarea); + caches[i] = slab_newcache(allocsizes[i] + sizeof(size_t) * 2 + sizeof(size_t) * USE_POISON, 0, initarea, dtor); __assert(caches[i]); } } diff --git a/kernel-src/mm/pmm.c b/kernel-src/mm/pmm.c index 7f377542..229033a0 100644 --- a/kernel-src/mm/pmm.c +++ b/kernel-src/mm/pmm.c @@ -42,6 +42,16 @@ static inline void bmset(void *addr, uint64_t v) { bitmap[entry] = entryval; } +static inline bool bmget(void *addr) { + uintmax_t page = (uintptr_t)addr / PAGE_SIZE; + uintmax_t entry = page / 64; + uintmax_t offset = page % 64; + + uint64_t entryval = bitmap[entry]; + entryval &= ((uint64_t)1 << offset); + return entryval; +} + static uintmax_t getfreearea(bmsection_t *section, size_t size) { uintmax_t result = 0; uintmax_t found = 0; @@ -112,8 +122,10 @@ void pmm_free(void *addr, size_t size) { if ((uintptr_t)addr / PAGE_SIZE < bmsections[i].searchstart) bmsections[i].searchstart = (uintptr_t)addr / PAGE_SIZE; - for (uintmax_t j = 0; j < size; ++j) + for (uintmax_t j = 0; j < size; ++j) { + __assert(bmget((void *)((page + j) * PAGE_SIZE)) == false); bmset((void *)((page + j) * PAGE_SIZE), 1); + } spinlock_release(&bmsections[i].lock); __atomic_sub_fetch(&used, 1, __ATOMIC_SEQ_CST); diff --git a/kernel-src/mm/slab.c b/kernel-src/mm/slab.c index a3cc3e71..2d8e0170 100644 --- a/kernel-src/mm/slab.c +++ b/kernel-src/mm/slab.c @@ -87,10 +87,10 @@ static void *takeobject(scache_t *cache, slab_t *slab) { if (cache->size < SLAB_INDIRECT_CUTOFF) { void *addr = (void *)objend; void *base = (void *)ROUND_DOWN((uintptr_t)slab, PAGE_SIZE); - __assert(addr > base && addr < (void *)slab); + __assert(addr >= base && addr < (void *)slab); } else { void *addr = slab->base + ((uintptr_t)objend - ROUND_DOWN((uintptr_t)slab, PAGE_SIZE)) / sizeof(void **) * cache->truesize; - __assert(addr > slab->base && (uintptr_t)addr < (uintptr_t)slab->base + cache->slabobjcount * cache->truesize); + __assert(addr >= slab->base && (uintptr_t)addr < (uintptr_t)slab->base + cache->slabobjcount * cache->truesize); } #endif