summaryrefslogtreecommitdiffstats
path: root/common/tlsf.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/tlsf.c')
-rw-r--r--common/tlsf.c29
1 files changed, 23 insertions, 6 deletions
diff --git a/common/tlsf.c b/common/tlsf.c
index 86cc684ab6..4247a9d3c7 100644
--- a/common/tlsf.c
+++ b/common/tlsf.c
@@ -3,9 +3,14 @@
#include <string.h>
#include <tlsf.h>
#include "tlsfbits.h"
+#include <linux/kasan.h>
#define CHAR_BIT 8
+#ifndef CONFIG_KASAN
+#define __memcpy memcpy
+#endif
+
/*
** Constants.
*/
@@ -529,7 +534,7 @@ static void block_trim_free(control_t* control, block_header_t* block, size_t si
}
/* Trim any trailing block space off the end of a used block, return to pool. */
-static void block_trim_used(control_t* control, block_header_t* block, size_t size)
+static void block_trim_used(control_t* control, block_header_t* block, size_t size, size_t used)
{
tlsf_assert(!block_is_free(block) && "block must be used");
if (block_can_split(block, size))
@@ -541,6 +546,10 @@ static void block_trim_used(control_t* control, block_header_t* block, size_t si
remaining_block = block_merge_next(control, remaining_block);
block_insert(control, remaining_block);
}
+
+ kasan_poison_shadow(&block->size, size + 2 * sizeof(size_t),
+ KASAN_KMALLOC_REDZONE);
+ kasan_unpoison_shadow(block_to_ptr(block), used);
}
static block_header_t* block_trim_free_leading(control_t* control, block_header_t* block, size_t size)
@@ -589,7 +598,8 @@ static block_header_t* block_locate_free(control_t* control, size_t size)
return block;
}
-static void* block_prepare_used(control_t* control, block_header_t* block, size_t size)
+static void* block_prepare_used(control_t* control, block_header_t* block,
+ size_t size, size_t used)
{
void* p = 0;
if (block)
@@ -598,6 +608,10 @@ static void* block_prepare_used(control_t* control, block_header_t* block, size_
block_trim_free(control, block, size);
block_mark_as_used(block);
p = block_to_ptr(block);
+
+ kasan_poison_shadow(&block->size, size + 2 * sizeof(size_t),
+ KASAN_KMALLOC_REDZONE);
+ kasan_unpoison_shadow(p, used);
}
return p;
}
@@ -907,6 +921,7 @@ tlsf_t tlsf_create_with_pool(void* mem, size_t bytes)
{
tlsf_t tlsf = tlsf_create(mem);
tlsf_add_pool(tlsf, (char*)mem + tlsf_size(), bytes - tlsf_size());
+ kasan_poison_shadow(mem, bytes, KASAN_TAG_INVALID);
return tlsf;
}
@@ -926,7 +941,8 @@ void* tlsf_malloc(tlsf_t tlsf, size_t size)
control_t* control = tlsf_cast(control_t*, tlsf);
const size_t adjust = adjust_request_size(size, ALIGN_SIZE);
block_header_t* block = block_locate_free(control, adjust);
- return block_prepare_used(control, block, adjust);
+
+ return block_prepare_used(control, block, adjust, size);
}
void* tlsf_memalign(tlsf_t tlsf, size_t align, size_t size)
@@ -983,7 +999,7 @@ void* tlsf_memalign(tlsf_t tlsf, size_t align, size_t size)
}
}
- return block_prepare_used(control, block, adjust);
+ return block_prepare_used(control, block, adjust, size);
}
void tlsf_free(tlsf_t tlsf, void* ptr)
@@ -994,6 +1010,7 @@ void tlsf_free(tlsf_t tlsf, void* ptr)
control_t* control = tlsf_cast(control_t*, tlsf);
block_header_t* block = block_from_ptr(ptr);
tlsf_assert(!block_is_free(block) && "block already marked as free");
+ kasan_poison_shadow(ptr, block_size(block), 0xff);
block_mark_as_free(block);
block = block_merge_prev(control, block);
block = block_merge_next(control, block);
@@ -1050,7 +1067,7 @@ void* tlsf_realloc(tlsf_t tlsf, void* ptr, size_t size)
if (p)
{
const size_t minsize = tlsf_min(cursize, size);
- memcpy(p, ptr, minsize);
+ __memcpy(p, ptr, minsize);
tlsf_free(tlsf, ptr);
}
}
@@ -1064,7 +1081,7 @@ void* tlsf_realloc(tlsf_t tlsf, void* ptr, size_t size)
}
/* Trim the resulting block and return the original pointer. */
- block_trim_used(control, block, adjust);
+ block_trim_used(control, block, adjust, size);
p = ptr;
}
}