From e2bc524328140303405213e554a37dc46cca4316 Mon Sep 17 00:00:00 2001 From: Ryad Benadjila Date: Sun, 12 Jan 2020 12:02:17 +0100 Subject: [PATCH 1/2] [enhancement/fix] Begin to properly intergrate the hardened allocator to the WooKey project in the std lib. The compatibility was previously broken, and this commit is a first attempt to migrate/integrate the code. The hardened allocator (contrary to the previously used "light" one) embeds mitigations such as randomized allocation, canaries, heap consistency checks, ... This is still in "beta test and review" and is a work in progress. When everything is tested to be OK, the hardened allocator will be made as the "default" one in the project configuration files. --- Kconfig | 8 +++ alloc/malloc_ewok.c | 138 ++++++++++++++++++++++++++++--------------- alloc/malloc_ewok.h | 16 +++-- alloc/malloc_init.c | 86 ++++++++++++++++++++++----- alloc/malloc_init.h | 4 +- alloc/malloc_light.c | 53 +++++++++++------ alloc/malloc_priv.h | 3 +- alloc/std_config.h | 2 +- embed/queue.c | 19 +++--- 9 files changed, 232 insertions(+), 97 deletions(-) diff --git a/Kconfig b/Kconfig index 7a31d45..1d6cfc1 100644 --- a/Kconfig +++ b/Kconfig @@ -107,6 +107,14 @@ config STD_MALLOC_RANDOM ---help--- TODO: Christophe +config STD_MALLOC_CANARIS_INTEGRITY + int "allocator canaries integrity check" + range 0 2 + depends on STD_MALLOC_STD || STD_MALLOC_BINS + default 1 + ---help--- + TODO: Christophe + endif endmenu diff --git a/alloc/malloc_ewok.c b/alloc/malloc_ewok.c index dd000e7..3233e2a 100644 --- a/alloc/malloc_ewok.c +++ b/alloc/malloc_ewok.c @@ -9,9 +9,13 @@ #include "malloc_priv.h" -//#include "../inc/memfct.h" +#if CONFIG_STD_MALLOC_MUTEX == 1 +extern void _set_wmalloc_semaphore(volatile uint32_t **ptr_semaphore); +#endif +extern void _set_wmalloc_heap(physaddr_t *start_heap, physaddr_t *end_heap, u__sz_t *heap_size); +extern volatile unsigned char allocator_initialized; /* Global variables */ @@ -21,12 +25,15 @@ static physaddr_t _end_heap; static u__sz_t _heap_size; /* Canaries (random or not) */ +#if (CONFIG_STD_MALLOC_INTEGRITY >= 1) && (CONFIG_STD_MALLOC_CANARIS_INTEGRITY == 1) static u_can_t _can_sz; static u_can_t _can_free; +extern void _set_wmalloc_canaries(u_can_t *can_sz, u_can_t *can_free); +#endif -#ifdef CONFIG_STD_MALLOC_MUTEX +#if CONFIG_STD_MALLOC_MUTEX == 1 /* Semaphore */ -static uint32_t _ptr_semaphore; +static volatile uint32_t *_ptr_semaphore; #endif @@ -65,6 +72,23 @@ static int check_free(struct block *b, uint16_t flag); static int check_consistency(struct block * b, uint16_t flag); #endif +/* + * This function should be called by malloc_init() to + * initialize local heap informations + */ +void malloc_ewok_init(physaddr_t start_heap, + physaddr_t end_heap, + u__sz_t heap_size) +{ + _start_heap = start_heap; + _end_heap = end_heap; + _heap_size = heap_size; + +#if CONFIG_STD_MALLOC_MUTEX == 1 + _set_wmalloc_semaphore(&_ptr_semaphore); +#endif +} + /*********************************************************************************************/ /* Malloc() function */ @@ -75,6 +99,11 @@ int wmalloc(void **ptr_to_alloc, const uint16_t len, const int flag) int wmalloc(void **ptr_to_alloc, const uint32_t len, const int flag) #endif { + if(allocator_initialized != 1){ + malloc_errno = EHEAPNODEF; + return -1; + } + void *ptr = NULL; u__sz_t len_bis = (u__sz_t) len; @@ -91,12 +120,17 @@ int wmalloc(void **ptr_to_alloc, const uint32_t len, const int flag) uint8_t insered_block = 0; -#if STD_FREEMEM_CHECK >= 1 +#if CONFIG_STD_FREEMEM_CHECK >= 1 u__sz_t memory_available = 0; #endif -#ifdef CONFIG_STD_MALLOC_RANDOM - int32_t random = (NB_FREE() ? (int32_t) (- ((uint8_t) ((uint32_t)rand() % NB_FREE()))) : 0); +#if CONFIG_STD_MALLOC_RANDOM == 1 + uint32_t tmp; + if(get_random((unsigned char*) &tmp, sizeof(tmp)) != MBED_ERROR_NONE){ + malloc_errno = EHEAPNODEF; + return -1; + } + int32_t random = (NB_FREE() ? (int32_t) (- ((uint8_t) (tmp % NB_FREE()))) : 0); #else int32_t random = 0; #endif @@ -104,11 +138,11 @@ int wmalloc(void **ptr_to_alloc, const uint32_t len, const int flag) /* Errno is initialized to zero */ malloc_errno = 0; -#ifdef CONFIG_STD_MALLOC_MUTEX - _set_wmalloc_semaphore((uint32_t *) _ptr_semaphore); +#if CONFIG_STD_MALLOC_MUTEX == 1 + _set_wmalloc_semaphore(&_ptr_semaphore); /* Trying to lock of wmalloc usage */ - if (!semaphore_trylock(&semaphore)) { + if (!semaphore_trylock(_ptr_semaphore)) { malloc_errno = EHEAPLOCKED; return -1; } @@ -116,7 +150,7 @@ int wmalloc(void **ptr_to_alloc, const uint32_t len, const int flag) /* Getting of heap specification values */ _set_wmalloc_heap(&_start_heap, &_end_heap, &_heap_size); -#if (CONFIG_STD_MALLOC_INTEGRITY == 1) && (CANARIS_INTEGRITY == 1) +#if (CONFIG_STD_MALLOC_INTEGRITY >= 1) && (CONFIG_STD_MALLOC_CANARIS_INTEGRITY == 1) _set_wmalloc_canaries(&_can_sz, &_can_free); #endif @@ -143,7 +177,7 @@ int wmalloc(void **ptr_to_alloc, const uint32_t len, const int flag) #elif CONFIG_STD_MALLOC_BASIC_CHECKS == 1 /* We check b_cur (and eventually b_cur_bis) are not out of range */ # if CONFIG_STD_MALLOC_DBLE_WAY_SEARCH == 1 - if ((OFFSET(b_cur) > OFFSET_MAX) || (OFFSET(_cur_bis) > OFFSET_MAX)) { + if ((OFFSET(b_cur) > OFFSET_MAX) || (OFFSET(b_cur_bis) > OFFSET_MAX)) { # elif CONFIG_STD_MALLOC_DBLE_WAY_SEARCH == 0 if ((OFFSET(b_cur) > OFFSET_MAX)) { # endif @@ -171,7 +205,7 @@ int wmalloc(void **ptr_to_alloc, const uint32_t len, const int flag) /* Block size is calculated */ sz = (u__sz_t) (len_bis + HDR_SZ); -#if STD_FREEMEM_CHECK >= 1 +#if CONFIG_STD_FREEMEM_CHECK >= 1 /* We check if there is definitively not enough memory for block */ memory_available = (u__sz_t) (SZ_FREE() - (u__sz_t)(HDR_FREE_SZ * (NB_FREE() - 1))); if (sz > memory_available) { @@ -211,7 +245,7 @@ int wmalloc(void **ptr_to_alloc, const uint32_t len, const int flag) } #endif -#if CONFIG_STD_MALLOC_INTEGRITY == 1 +#if CONFIG_STD_MALLOC_INTEGRITY >= 1 /* We check the integrity of the header (if no heap integrity checking) */ if (check_hdr(b_cur, CHECK_ALL_FREE)) { malloc_errno = EHEAPINTEGRITY; @@ -236,7 +270,7 @@ int wmalloc(void **ptr_to_alloc, const uint32_t len, const int flag) /* Current free block is updated and changed to allocated block */ b_cur->sz = sz; MAKE_ALLOC(b_cur); -#if CANARIS_INTEGRITY == 1 +#if CONFIG_STD_MALLOC_CANARIS_INTEGRITY == 1 UPDATE_CANARI_SZ(b_cur); #endif @@ -259,7 +293,7 @@ int wmalloc(void **ptr_to_alloc, const uint32_t len, const int flag) * next block's "prv_sz" is completed with the current block's size */ if ((physaddr_t) b_nxt_now != _end_heap) { b_nxt_now->prv_sz = (insered_block ? SIZE(b_nxt_int) : sz); -#if CANARIS_INTEGRITY == 1 +#if CONFIG_STD_MALLOC_CANARIS_INTEGRITY == 1 UPDATE_CANARI_GENE(b_nxt_now); #endif } @@ -271,7 +305,7 @@ int wmalloc(void **ptr_to_alloc, const uint32_t len, const int flag) } else { b_cur->prv_free = 0; b_cur->nxt_free = 0; -#if CANARIS_INTEGRITY == 1 +#if CONFIG_STD_MALLOC_CANARIS_INTEGRITY == 1 b_cur->can_free = 0; #endif } @@ -279,7 +313,7 @@ int wmalloc(void **ptr_to_alloc, const uint32_t len, const int flag) /* Increase the field "prv_free" of b_0 (total size of allocated memory) */ DECREASE_SZ_FREE(sz); -#if CANARIS_INTEGRITY == 1 +#if CONFIG_STD_MALLOC_CANARIS_INTEGRITY == 1 /* b_0 first canari are updated for taking into account the modification of * b_0->prv_sz = NB_FREE() and b_0->sz = SZ_FREE() */ UPDATE_CANARI_SZ(b_0); @@ -291,9 +325,9 @@ int wmalloc(void **ptr_to_alloc, const uint32_t len, const int flag) /**********************************************************/ *ptr_to_alloc = ptr; -#ifdef CONFIG_STD_MALLOC_MUTEX +#if CONFIG_STD_MALLOC_MUTEX == 1 /* Unlocking of wmalloc usage */ - if (!semaphore_release((uint32_t *) _ptr_semaphore)) { + if (!semaphore_release(_ptr_semaphore)) { malloc_errno = EHEAPSEMAPHORE; return -1; } @@ -304,7 +338,7 @@ int wmalloc(void **ptr_to_alloc, const uint32_t len, const int flag) /**********************************************************/ } -#if STD_FREEMEM_CHECK == 2 +#if CONFIG_STD_FREEMEM_CHECK == 2 /* We check if there is definitively not enough memory for block */ # if CONFIG_STD_MALLOC_DBLE_WAY_SEARCH == 0 memory_available -= (u__sz_t)(b_cur->sz - HDR_FREE_SZ); @@ -360,10 +394,10 @@ int wmalloc(void **ptr_to_alloc, const uint32_t len, const int flag) end_error: -#ifdef CONFIG_STD_MALLOC_MUTEX +#if CONFIG_STD_MALLOC_MUTEX == 1 /* Unlocking of wmalloc usage (malloc_errno is not modified in order to keep the value * of the initial error) */ - semaphore_release((uint32_t *) _ptr_semaphore); + semaphore_release(_ptr_semaphore); #endif return -1; @@ -380,7 +414,7 @@ static int _update_inter_free(struct block *b_cur, struct block *b_nxt_int, u__s b_nxt_int->prv_free = b_cur->prv_free; b_nxt_int->nxt_free = b_cur->nxt_free; -#if CANARIS_INTEGRITY == 1 +#if CONFIG_STD_MALLOC_CANARIS_INTEGRITY == 1 UPDATE_CANARI_BOTH(b_nxt_int); #endif @@ -388,7 +422,7 @@ static int _update_inter_free(struct block *b_cur, struct block *b_nxt_int, u__s BLOCK(b_cur->prv_free)->nxt_free = OFFSET(b_nxt_int); BLOCK(b_cur->nxt_free)->prv_free = OFFSET(b_nxt_int); -#if CANARIS_INTEGRITY == 1 +#if CONFIG_STD_MALLOC_CANARIS_INTEGRITY == 1 UPDATE_CANARI_FREE(PRV_FREE(b_nxt_int)); UPDATE_CANARI_FREE(NXT_FREE(b_nxt_int)); #endif @@ -404,7 +438,7 @@ static int _unlink(struct block *b_cur) BLOCK(b_cur->prv_free)->nxt_free = b_cur->nxt_free; BLOCK(b_cur->nxt_free)->prv_free = b_cur->prv_free; -#if CANARIS_INTEGRITY == 1 +#if CONFIG_STD_MALLOC_CANARIS_INTEGRITY == 1 UPDATE_CANARI_FREE(PRV_FREE(b_cur)); UPDATE_CANARI_FREE(NXT_FREE(b_cur)); #endif @@ -427,6 +461,11 @@ static int _unlink(struct block *b_cur) /****************************************************************************************/ int wfree(void **ptr_to_free) { + if(allocator_initialized != 1){ + malloc_errno = EHEAPNODEF; + return -1; + } + struct block *b_0 = (struct block *) _start_heap; struct block *b_1 = b_0 + 1; @@ -439,11 +478,11 @@ int wfree(void **ptr_to_free) /* Errno is initialized to zero */ malloc_errno = 0; -#ifdef CONFIG_STD_MALLOC_MUTEX - _set_wmalloc_semaphore((uint32_t *) _ptr_semaphore); +#if CONFIG_STD_MALLOC_MUTEX == 1 + _set_wmalloc_semaphore(&_ptr_semaphore); /* Locking of wmalloc usage */ - if (!semaphore_trylock(&semaphore)) { + if (!semaphore_trylock(_ptr_semaphore)) { malloc_errno = EHEAPLOCKED; return -1; } @@ -451,7 +490,7 @@ int wfree(void **ptr_to_free) /* Getting of heap specification values */ _set_wmalloc_heap(&_start_heap, &_end_heap, &_heap_size); -#if (CONFIG_STD_MALLOC_INTEGRITY == 1) && (CANARIS_INTEGRITY == 1) +#if (CONFIG_STD_MALLOC_INTEGRITY >= 1) && (CONFIG_STD_MALLOC_CANARIS_INTEGRITY == 1) _set_wmalloc_canaries(&_can_sz, &_can_free); #endif @@ -530,7 +569,7 @@ int wfree(void **ptr_to_free) /* Last block updated (size increased) */ b_prv->sz = (u__sz_t) (SIZE(b_prv) + SIZE(b_cur)); -#if CANARIS_INTEGRITY == 1 +#if CONFIG_STD_MALLOC_CANARIS_INTEGRITY == 1 UPDATE_CANARI_SZ(b_prv); #endif @@ -570,14 +609,14 @@ int wfree(void **ptr_to_free) if (!(merged & MERGED_WITH_PRV)) { b_cur->prv_free = b_nxt->prv_free; PRV_FREE(b_cur)->nxt_free = OFFSET(b_cur); -#if CANARIS_INTEGRITY == 1 +#if CONFIG_STD_MALLOC_CANARIS_INTEGRITY == 1 UPDATE_CANARI_FREE(PRV_FREE(b_cur)); #endif } b_cur->nxt_free = b_nxt->nxt_free; NXT_FREE(b_cur)->prv_free = OFFSET(b_cur); -#if CANARIS_INTEGRITY == 1 +#if CONFIG_STD_MALLOC_CANARIS_INTEGRITY == 1 UPDATE_CANARI_FREE(NXT_FREE(b_cur)); #endif @@ -587,14 +626,14 @@ int wfree(void **ptr_to_free) } /* Canari_1 is updated */ -#if CANARIS_INTEGRITY == 1 +#if CONFIG_STD_MALLOC_CANARIS_INTEGRITY == 1 UPDATE_CANARI_BOTH(b_cur); #endif /* If the updated block is not the final one, the next block is updated (prv_sz) */ if (NOT_LAST_BLOCK(b_cur)) { ((struct block *) ((physaddr_t) b_cur + b_cur->sz))->prv_sz = b_cur->sz; -#if CANARIS_INTEGRITY == 1 +#if CONFIG_STD_MALLOC_CANARIS_INTEGRITY == 1 UPDATE_CANARI_SZ((struct block *)((physaddr_t) b_cur + b_cur->sz)); #endif } @@ -623,15 +662,15 @@ int wfree(void **ptr_to_free) end: -#if CANARIS_INTEGRITY == 1 +#if CONFIG_STD_MALLOC_CANARIS_INTEGRITY == 1 /* b_0 first canari are updated for taking into account the modification of * b_0->prv_sz = NB_FREE() and b_0->sz = SZ_FREE() */ UPDATE_CANARI_SZ(b_0); #endif -#ifdef CONFIG_STD_MALLOC_MUTEX +#if CONFIG_STD_MALLOC_MUTEX == 1 /* Unlocking of wmalloc usage */ - if (!semaphore_release((uint32_t *) _ptr_semaphore)) { + if (!semaphore_release(_ptr_semaphore)) { malloc_errno = EHEAPSEMAPHORE; return -1; } @@ -641,10 +680,10 @@ int wfree(void **ptr_to_free) end_error: -#ifdef CONFIG_STD_MALLOC_MUTEX +#if CONFIG_STD_MALLOC_MUTEX == 1 /* Unlocking of wmalloc usage (malloc_errno is not modified in order to keep the value * of the initial error) */ - semaphore_release((uint32_t *) _ptr_semaphore); + semaphore_release(_ptr_semaphore); #endif return -1; @@ -697,7 +736,7 @@ static int _link(struct block *b_cur, struct block *b_0) b_prv->nxt_free = o_cur; b_nxt->prv_free = o_cur; -#if CANARIS_INTEGRITY != 0 +#if CONFIG_STD_MALLOC_CANARIS_INTEGRITY != 0 /* Canaris are updated */ UPDATE_CANARI_FREE(b_cur); UPDATE_CANARI_FREE(b_prv); @@ -737,7 +776,7 @@ static void __attribute__((optimize("O0"))) *_safe_flood_char(void *dest, const /* Checking of the heap's integrity */ /****************************************************************************************/ #if CONFIG_STD_MALLOC_INTEGRITY >= 2 -int _heap_integrity(void) +static int _heap_integrity(void) { struct block *b_0 = (struct block *) _start_heap; struct block *b_cur = b_0 + 1; @@ -872,7 +911,7 @@ static inline int check_alloc_headers(void) } } -#if (CANARIS_INTEGRITY + SZ_VAL_INTEGRITY) == 0 +#if (CONFIG_STD_MALLOC_CANARIS_INTEGRITY + SZ_VAL_INTEGRITY) == 0 if (SIZE_SECU(b_cur) == 0) { error = INTEGRITY_SZ; goto out; @@ -905,7 +944,7 @@ static int check_hdr(struct block *b, u__sz_t flag) return INTEGRITY_FLAG; } -#if CANARIS_INTEGRITY == 1 +#if CONFIG_STD_MALLOC_CANARIS_INTEGRITY == 1 if (flag & CHECK_CANARI) { if (BAD_CANARI(b)) { return INTEGRITY_CANARI; @@ -1004,7 +1043,7 @@ static int check_consistency(struct block * b, u__sz_t flag) { if (flag & CHECK_SZ_EQ_PRV) { if (NOT_FIRST_BLOCK(b)) { -# if CANARIS_INTEGRITY == 0 +# if CONFIG_STD_MALLOC_CANARIS_INTEGRITY == 0 if (b->prv_sz != SIZE(PREV_SECU(b))) { # else if (b->prv_sz != SIZE(PREV(b))) { @@ -1016,7 +1055,7 @@ static int check_consistency(struct block * b, u__sz_t flag) if (flag & CHECK_SZ_EQ_NXT) { if (NOT_LAST_BLOCK(b)) { -# if CANARIS_INTEGRITY == 0 +# if CONFIG_STD_MALLOC_CANARIS_INTEGRITY == 0 if (SIZE(b) != NEXT_SECU(b)->prv_sz) { # else if (SIZE(b) != NEXT(b)->prv_sz) { @@ -1031,7 +1070,7 @@ static int check_consistency(struct block * b, u__sz_t flag) } if (flag & CHECK_FREE_EQ_PRV) { -# if CANARIS_INTEGRITY == 0 +# if CONFIG_STD_MALLOC_CANARIS_INTEGRITY == 0 if (NXT_FREE_SECU((PRV_FREE_SECU(b))) != b) { # else if (NXT_FREE(PRV_FREE(b)) != b) { @@ -1041,7 +1080,7 @@ static int check_consistency(struct block * b, u__sz_t flag) } if (flag & CHECK_FREE_EQ_NXT) { -# if CANARIS_INTEGRITY == 0 +# if CONFIG_STD_MALLOC_CANARIS_INTEGRITY == 0 if (PRV_FREE_SECU(NXT_FREE_SECU(b)) != b) { # else if (PRV_FREE(NXT_FREE(b)) != b) { @@ -1063,6 +1102,11 @@ static int check_consistency(struct block * b, u__sz_t flag) #ifdef PRINT_HEAP int print_heap(void) { + if(allocator_initialized != 1){ + malloc_errno = EHEAPNODEF; + return -1; + } + struct block *b_0 = (struct block *) _start_heap; struct block *b_cur = NULL; diff --git a/alloc/malloc_ewok.h b/alloc/malloc_ewok.h index 15c26bb..494d889 100644 --- a/alloc/malloc_ewok.h +++ b/alloc/malloc_ewok.h @@ -12,7 +12,8 @@ #include "malloc_priv.h" - +#define SUM_VERSION 2 +#define HEAP_SIZE_LEN CONFIG_STD_MALLOC_SIZE_LEN /* Chunk structure : * - size and and previous chunk's size @@ -21,7 +22,7 @@ */ /*#pragma pack (1)*/ struct __attribute__((packed)) block { -#if CANARIS_INTEGRITY == 1 +#if CONFIG_STD_MALLOC_CANARIS_INTEGRITY == 1 u_can_t can_sz; #endif u_flg_t flag; @@ -29,13 +30,13 @@ struct __attribute__((packed)) block { u__sz_t sz; u_off_t prv_free; /* Only for free blocks: relative address */ u_off_t nxt_free; /* Only for free blocks: relative address */ -#if CANARIS_INTEGRITY == 1 +#if CONFIG_STD_MALLOC_CANARIS_INTEGRITY == 1 u_can_t can_free; #endif }; struct __attribute__((packed)) alloc_block { -#if CANARIS_INTEGRITY == 1 +#if CONFIG_STD_MALLOC_CANARIS_INTEGRITY == 1 u_can_t can_sz; #endif u_flg_t flag; @@ -109,7 +110,7 @@ struct __attribute__((packed)) alloc_block { /* Canaries mamangement */ -#if CANARIS_INTEGRITY == 1 +#if CONFIG_STD_MALLOC_CANARIS_INTEGRITY == 1 #define CAN_SHIFT HEAP_SIZE_LEN @@ -173,7 +174,7 @@ struct __attribute__((packed)) alloc_block { # define INCREASE_SZ_FREE(l) SZ_FREE() = (u__sz_t)(SZ_FREE() + (l)) # define DECREASE_SZ_FREE(l) SZ_FREE() = (u__sz_t)(SZ_FREE() - (l)) -#if CANARIS_INTEGRITY == 1 +#if CONFIG_STD_MALLOC_CANARIS_INTEGRITY == 1 # define INC_NB_SZ_FREE(l) INCREASE_SZ_FREE(l); \ INCREASE_NB_FREE(); \ @@ -186,6 +187,9 @@ struct __attribute__((packed)) alloc_block { #endif +void malloc_ewok_init(physaddr_t start_heap, + physaddr_t end_heap, + u__sz_t heap_size); #endif #endif diff --git a/alloc/malloc_init.c b/alloc/malloc_init.c index 80c3920..d1744f1 100644 --- a/alloc/malloc_init.c +++ b/alloc/malloc_init.c @@ -2,10 +2,13 @@ #ifdef CONFIG_STD_MALLOC -#include "malloc_priv.h" +#define RANDOM_CANARIS +#if (CONFIG_STD_MALLOC_INTEGRITY == 1) && (CONFIG_STD_MALLOC_CANARIS_INTEGRITY == 1) +#include "malloc_ewok.h" +#endif -//#include "../inc/memfct.h" +#include "malloc_priv.h" /* Global variables */ @@ -30,7 +33,7 @@ static u_can_t _can_sz; static u_can_t _can_free; #endif -#ifdef CONFIG_STD_MALLOC_MUTEX +#if CONFIG_STD_MALLOC_MUTEX == 1 /* Semaphore */ static volatile uint32_t _semaphore; #endif @@ -68,11 +71,11 @@ void _set_wmalloc_canaries(u_can_t *can_sz, u_can_t *can_free) #endif -#ifdef CONFIG_STD_MALLOC_MUTEX +#if CONFIG_STD_MALLOC_MUTEX == 1 /* Set semaphore for allocator functions */ -void _set_wmalloc_semaphore(volatile uint32_t *ptr_semaphore) +void _set_wmalloc_semaphore(volatile uint32_t **ptr_semaphore) { - *ptr_semaphore = (physaddr_t) (&_semaphore); + *ptr_semaphore = (uint32_t*) (&_semaphore); return; } @@ -82,11 +85,17 @@ void _set_wmalloc_semaphore(volatile uint32_t *ptr_semaphore) /****************************************************************************************/ /* Initialization of heap global variables */ /****************************************************************************************/ +volatile unsigned char allocator_initialized = 0; int wmalloc_init(void) { physaddr_t task_start_heap = 0; uint32_t task_heap_size = 0; + /* If allocator already initialized, this is an error ... */ + if(allocator_initialized == 1){ + return -1; + } + #ifdef CONFIG_KERNEL_EWOK task_start_heap = (physaddr_t) (&_e_bss); @@ -106,8 +115,44 @@ int wmalloc_init(void) printf("stack end: 0x%08x\n", &_e_stack); #endif -#ifdef CONFIG_STD_MALLOC_LIGHT +#if defined(CONFIG_STD_MALLOC_LIGHT) + printf("Light allocator used!\n"); +#elif defined(CONFIG_STD_MALLOC_STD) + printf("EwoK hardened allocator used!\n"); +#endif + +#ifdef CONFIG_STD_MALLOC_INTEGRITY + printf("CONFIG_STD_MALLOC_INTEGRITY = %d\n", CONFIG_STD_MALLOC_INTEGRITY); +#endif +#ifdef CONFIG_STD_MALLOC_MUTEX + printf("CONFIG_STD_MALLOC_MUTEX = %d\n", CONFIG_STD_MALLOC_MUTEX); +#endif +#ifdef CONFIG_STD_MALLOC_CANARIS_INTEGRITY + printf("CONFIG_STD_MALLOC_CANARIS_INTEGRITY = %d\n", CONFIG_STD_MALLOC_CANARIS_INTEGRITY); +#endif +#ifdef CONFIG_STD_MALLOC_CHECK_IF_NULL + printf("CONFIG_STD_MALLOC_CHECK_IF_NULL = %d\n", CONFIG_STD_MALLOC_CHECK_IF_NULL); +#endif +#ifdef CONFIG_STD_MALLOC_BASIC_CHECKS + printf("CONFIG_STD_MALLOC_BASIC_CHECKS = %d\n", CONFIG_STD_MALLOC_BASIC_CHECKS); +#endif +#ifdef CONFIG_STD_MALLOC_DBLE_WAY_SEARCH + printf("CONFIG_STD_MALLOC_DBLE_WAY_SEARCH = %d\n", CONFIG_STD_MALLOC_DBLE_WAY_SEARCH); +#endif +#ifdef CONFIG_STD_MALLOC_ALIGN + printf("CONFIG_STD_MALLOC_ALIGN = %d\n", CONFIG_STD_MALLOC_ALIGN); +#endif +#ifdef CONFIG_STD_FREEMEM_CHECK + printf("CONFIG_STD_FREEMEM_CHECK = %d\n", CONFIG_STD_FREEMEM_CHECK); +#endif +#ifdef CONFIG_STD_MALLOC_RANDOM + printf("CONFIG_STD_MALLOC_RANDOM = %d\n", CONFIG_STD_MALLOC_RANDOM); +#endif + +#if defined(CONFIG_STD_MALLOC_LIGHT) malloc_light_init(task_start_heap, (physaddr_t)task_start_heap + task_heap_size, (u__sz_t)task_heap_size); +#elif defined(CONFIG_STD_MALLOC_STD) + malloc_ewok_init(task_start_heap, (physaddr_t)task_start_heap + task_heap_size, (u__sz_t)task_heap_size); #else # error "init for other malloc not done yet" #endif @@ -121,7 +166,12 @@ int wmalloc_init(void) return -1; } - return _wmalloc_init(task_start_heap, task_heap_size); + if(_wmalloc_init(task_start_heap, task_heap_size)){ + return -1; + } + + allocator_initialized = 1; + return 0; } @@ -159,7 +209,7 @@ static int _wmalloc_init(const physaddr_t task_start_heap, const uint32_t task_h _heap_size = (u__sz_t) task_heap_size; _end_heap = (physaddr_t) (task_start_heap + task_heap_size); -#ifdef CONFIG_STD_MALLOC_MUTEX +#if CONFIG_STD_MALLOC_MUTEX == 1 /* Locking of wmalloc usage */ semaphore_init(1, &_semaphore); @@ -172,10 +222,16 @@ static int _wmalloc_init(const physaddr_t task_start_heap, const uint32_t task_h #endif /* Definition of canaries */ -#if CANARIS_INTEGRITY == 1 +#if CONFIG_STD_MALLOC_CANARIS_INTEGRITY == 1 # ifdef RANDOM_CANARIS - _can_sz = (u_can_t) rand(); - _can_free = (u_can_t) rand(); + if(get_random((unsigned char*) &_can_sz, sizeof(u_can_t)) != MBED_ERROR_NONE){ + malloc_errno = EHEAPNODEF; + return -1; + } + if(get_random((unsigned char*) &_can_free, sizeof(u_can_t)) != MBED_ERROR_NONE){ + malloc_errno = EHEAPNODEF; + return -1; + } # else _can_sz = (u_can_t) 0xF0F0F0F0; _can_free = (u_can_t) 0x0F0F0F0F; @@ -191,7 +247,7 @@ static int _wmalloc_init(const physaddr_t task_start_heap, const uint32_t task_h b_0->flag = 0; b_0->prv_free = HDR_FREE_SZ; b_0->nxt_free = HDR_FREE_SZ; -# if CANARIS_INTEGRITY == 1 +#if (CONFIG_STD_MALLOC_INTEGRITY >= 1) && (CONFIG_STD_MALLOC_CANARIS_INTEGRITY == 1) UPDATE_CANARI_BOTH(b_0); # endif @@ -204,11 +260,11 @@ static int _wmalloc_init(const physaddr_t task_start_heap, const uint32_t task_h b_1->flag = 0; b_1->prv_free = 0; b_1->nxt_free = 0; -# if CANARIS_INTEGRITY == 1 +#if (CONFIG_STD_MALLOC_INTEGRITY >= 1) && (CONFIG_STD_MALLOC_CANARIS_INTEGRITY == 1) UPDATE_CANARI_BOTH(b_1); # endif -#ifdef CONFIG_STD_MALLOC_MUTEX +#if CONFIG_STD_MALLOC_MUTEX == 1 /* Unlocking of wmalloc usage */ if (!semaphore_release(&_semaphore)) { malloc_errno = EHEAPSEMAPHORE; diff --git a/alloc/malloc_init.h b/alloc/malloc_init.h index def13f1..6bab644 100644 --- a/alloc/malloc_init.h +++ b/alloc/malloc_init.h @@ -1,5 +1,5 @@ -#ifndef H_MALLOC_EWOK -#define H_MALLOC_EWOK +#ifndef H_MALLOC_INIT +#define H_MALLOC_INIT #include "autoconf.h" diff --git a/alloc/malloc_light.c b/alloc/malloc_light.c index 41bb05a..2fce756 100644 --- a/alloc/malloc_light.c +++ b/alloc/malloc_light.c @@ -10,8 +10,12 @@ #include "malloc_priv.h" #include "malloc_init.h" -//#include "../inc/memfct.h" +#if CONFIG_STD_MALLOC_MUTEX == 1 +extern void _set_wmalloc_semaphore(volatile uint32_t **ptr_semaphore); +#endif +extern void _set_wmalloc_heap(physaddr_t *start_heap, physaddr_t *end_heap, u__sz_t *heap_size); +extern volatile unsigned char allocator_initialized; /* Global variables */ @@ -20,9 +24,9 @@ static physaddr_t _start_heap; static physaddr_t _end_heap; static u__sz_t _heap_size; -#ifdef CONFIG_STD_MALLOC_MUTEX +#if CONFIG_STD_MALLOC_MUTEX == 1 /* Semaphore */ -volatile uint32_t _ptr_semaphore; +static volatile uint32_t *_ptr_semaphore; #endif @@ -45,8 +49,8 @@ void malloc_light_init(physaddr_t start_heap, _end_heap = end_heap; _heap_size = heap_size; -#ifdef CONFIG_STD_MALLOC_MUTEX - _set_wmalloc_semaphore((uint32_t *) _ptr_semaphore); +#if CONFIG_STD_MALLOC_MUTEX == 1 + _set_wmalloc_semaphore(&_ptr_semaphore); #endif } @@ -59,6 +63,11 @@ int wmalloc(void **ptr_to_alloc, const uint16_t len, const int flag) int wmalloc(void **ptr_to_alloc, const uint32_t len, const int flag) #endif { + if(allocator_initialized != 1){ + malloc_errno = EHEAPNODEF; + return -1; + } + void *ptr = NULL; u__sz_t len_bis = (u__sz_t) len; @@ -77,9 +86,9 @@ int wmalloc(void **ptr_to_alloc, const uint32_t len, const int flag) /* Errno is initialized to zero */ malloc_errno = 0; -#ifdef CONFIG_STD_MALLOC_MUTEX +#if CONFIG_STD_MALLOC_MUTEX == 1 /* Trying to lock of wmalloc usage */ - if (!semaphore_trylock(&_ptr_semaphore)) { + if (!semaphore_trylock(_ptr_semaphore)) { malloc_errno = EHEAPLOCKED; return -1; } @@ -181,9 +190,9 @@ int wmalloc(void **ptr_to_alloc, const uint32_t len, const int flag) /**********************************************************/ *ptr_to_alloc = ptr; -#ifdef CONFIG_STD_MALLOC_MUTEX +#if CONFIG_STD_MALLOC_MUTEX == 1 /* Unlocking of wmalloc usage */ - if (!semaphore_release(&_ptr_semaphore)) { + if (!semaphore_release(_ptr_semaphore)) { malloc_errno = EHEAPSEMAPHORE; return -1; } @@ -211,10 +220,10 @@ int wmalloc(void **ptr_to_alloc, const uint32_t len, const int flag) end_error: -#ifdef CONFIG_STD_MALLOC_MUTEX +#if CONFIG_STD_MALLOC_MUTEX == 1 /* Unlocking of wmalloc usage (malloc_errno is not modified in order to keep the value * of the initial error) */ - semaphore_release(&_ptr_semaphore); + semaphore_release(_ptr_semaphore); #endif return -1; @@ -264,6 +273,11 @@ static int _unlink(struct block *b_cur) /****************************************************************************************/ int wfree(void **ptr_to_free) { + if(allocator_initialized != 1){ + malloc_errno = EHEAPNODEF; + return -1; + } + struct block *b_0 = (struct block *) _start_heap; struct block *b_1 = b_0 + 1; @@ -276,11 +290,11 @@ int wfree(void **ptr_to_free) /* Errno is initialized to zero */ malloc_errno = 0; -#ifdef CONFIG_STD_MALLOC_MUTEX +#if CONFIG_STD_MALLOC_MUTEX == 1 _set_wmalloc_semaphore(&_ptr_semaphore); /* Locking of wmalloc usage */ - if (!semaphore_trylock(&_ptr_semaphore)) { + if (!semaphore_trylock(_ptr_semaphore)) { malloc_errno = EHEAPLOCKED; return -1; } @@ -410,9 +424,9 @@ int wfree(void **ptr_to_free) end: -#ifdef CONFIG_STD_MALLOC_MUTEX +#if CONFIG_STD_MALLOC_MUTEX == 1 /* Unlocking of wmalloc usage */ - if (!semaphore_release(&_ptr_semaphore)) { + if (!semaphore_release(_ptr_semaphore)) { malloc_errno = EHEAPSEMAPHORE; return -1; } @@ -422,10 +436,10 @@ int wfree(void **ptr_to_free) end_error: -#ifdef CONFIG_STD_MALLOC_MUTEX +#if CONFIG_STD_MALLOC_MUTEX == 1 /* Unlocking of wmalloc usage (malloc_errno is not modified in order to keep the value * of the initial error) */ - semaphore_release(&_ptr_semaphore); + semaphore_release(_ptr_semaphore); #endif return -1; @@ -499,6 +513,11 @@ static void *_safe_flood_char(void *dest, const char c, uint32_t n) #ifdef PRINT_HEAP int print_heap(void) { + if(allocator_initialized != 1){ + malloc_errno = EHEAPNODEF; + return -1; + } + struct block *b_0 = (struct block *) _start_heap; struct block *b_cur = NULL; diff --git a/alloc/malloc_priv.h b/alloc/malloc_priv.h index 96edd72..977344f 100644 --- a/alloc/malloc_priv.h +++ b/alloc/malloc_priv.h @@ -10,7 +10,6 @@ #ifdef CONFIG_STD_MALLOC -#include "malloc_priv.h" #include "malloc_errno.h" /* Specific wmalloc errno values */ #include "libc/types.h" #include "libc/malloc.h" @@ -151,6 +150,8 @@ int _heap_integrity(void); #include "malloc_bins.h" #endif +/* For randomness source */ +#include "libc/random.h" #endif #endif diff --git a/alloc/std_config.h b/alloc/std_config.h index 3c1552c..9babaf5 100644 --- a/alloc/std_config.h +++ b/alloc/std_config.h @@ -92,7 +92,7 @@ /* Integrity checking mode */ -#define HEAP_INTEGRITY_CHECKING 1 /* Define the mode of integrity checking: +#define HEAP_INTEGRITY_CHECKING 3 /* Define the mode of integrity checking: 0 - no integrity checking 1 - integrity checking of each header to be read 2 - integrity of all free blocks' headers at each diff --git a/embed/queue.c b/embed/queue.c index 5aed2b1..806b32a 100644 --- a/embed/queue.c +++ b/embed/queue.c @@ -32,6 +32,7 @@ mbed_error_t queue_create(uint32_t capacity, queue_t ** queue) { queue_t *q = 0; + int ret; /* sanitizing */ if (!queue) { @@ -45,8 +46,9 @@ mbed_error_t queue_create(uint32_t capacity, queue_t ** queue) } /* allocating */ - if (wmalloc((void **) &q, sizeof(queue_t), ALLOC_NORMAL) != 0) { - goto nomem; + if ((ret = wmalloc((void **) &q, sizeof(queue_t), ALLOC_NORMAL)) != 0) { + aprintf("[ISR] Error queue_create in malloc: %x\n", ret); + goto unkown; } #if QUEUE_DEBUG aprintf("queue address is %x\n", q); @@ -61,15 +63,15 @@ mbed_error_t queue_create(uint32_t capacity, queue_t ** queue) *queue = q; return MBED_ERROR_NONE; - nomem: - return MBED_ERROR_NOMEM; + unkown: + return MBED_ERROR_UNKNOWN; invparam: return MBED_ERROR_INVPARAM; } mbed_error_t queue_enqueue(queue_t * q, void *data) { - struct node *n; + struct node *n = NULL; int ret; if (!q || !data) { @@ -81,8 +83,8 @@ mbed_error_t queue_enqueue(queue_t * q, void *data) } if ((ret = wmalloc((void **) &n, sizeof(struct node), ALLOC_NORMAL)) != 0) { - aprintf("[ISR] Error in malloc: %d\n", ret); - return MBED_ERROR_NOMEM; + aprintf("[ISR] Error queue_enqueue in malloc: %x\n", ret); + return MBED_ERROR_UNKNOWN; } /* We manipulate the queue: we need to lock it to stay thread-safe */ @@ -169,8 +171,9 @@ mbed_error_t queue_dequeue(queue_t * q, void **data) if (wfree((void **) &last) != 0) { #if QUEUE_DEBUG /* this error should not happend. */ - aprintf("free failed with %x\n", ret); + aprintf("[ISR] free failed in queue_dequeue with %x\n", ret); #endif + ret = MBED_ERROR_UNKNOWN; } nostorage: From b59bc8e3410082695fd591f78de82b1c44213ae8 Mon Sep 17 00:00:00 2001 From: Ryad Benadjila Date: Tue, 14 Jan 2020 09:05:57 +0100 Subject: [PATCH 2/2] [bugfix] Fix a bug where stack canaries are not well managed with syscalls related inline assembly. --- arch/cores/armv7-m/m4_syscall.c | 58 ++++++++++++++++----------------- syscall.c | 7 +++- 2 files changed, 35 insertions(+), 30 deletions(-) diff --git a/arch/cores/armv7-m/m4_syscall.c b/arch/cores/armv7-m/m4_syscall.c index 06b2d3a..40d1f3a 100644 --- a/arch/cores/armv7-m/m4_syscall.c +++ b/arch/cores/armv7-m/m4_syscall.c @@ -71,35 +71,6 @@ void __stack_chk_fail(void) }; } -#if __clang__ -#pragma clang optimize on -#if __clang_major__ > 7 -#pragma clang attribute pop -#endif -#endif - -#if __GNUC__ -#pragma GCC pop_options -#endif - -/** - ** \private - ** ISR handler glue. The kernel must set the real handler @ in the - ** stack frame to make the NVIC reload r0 with its @. - */ -void do_startisr(handler_t handler, uint8_t irq, uint32_t status, uint32_t data) -{ - if (handler) { - handler(irq, status, data); - } - - /* End of ISR */ - asm volatile ("svc %0\n"::"i" (SVC_EXIT):); - - while (1) { - }; -} - /** ** \private ** the argument is used for stack access by kernel @@ -277,3 +248,32 @@ e_syscall_ret do_syscall(e_svc_type svc, __attribute__ ((unused)) return SYS_E_INVAL; } } + +/** + ** \private + ** ISR handler glue. The kernel must set the real handler @ in the + ** stack frame to make the NVIC reload r0 with its @. + */ +void do_startisr(handler_t handler, uint8_t irq, uint32_t status, uint32_t data) +{ + if (handler) { + handler(irq, status, data); + } + + /* End of ISR */ + asm volatile ("svc %0\n"::"i" (SVC_EXIT):); + + while (1) { + }; +} + +#if __clang__ +#pragma clang optimize on +#if __clang_major__ > 7 +#pragma clang attribute pop +#endif +#endif + +#if __GNUC__ +#pragma GCC pop_options +#endif diff --git a/syscall.c b/syscall.c index 2e1baa6..796092c 100644 --- a/syscall.c +++ b/syscall.c @@ -37,7 +37,9 @@ static inline void _memset(void *s, int c, uint32_t n) { char *bytes = s; - + if(s == NULL){ + return; + } while (n) { *bytes = c; bytes++; @@ -51,6 +53,9 @@ static inline void _memcpy(void *dest, const void *src, uint32_t n) char *d_bytes = dest; const char *s_bytes = src; + if((dest == NULL) || (src == NULL)){ + return; + } while (n) { *d_bytes = *s_bytes; d_bytes++;