diff --git a/mm/Kconfig b/mm/Kconfig index fa74e0c098..39b8901185 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -293,6 +293,10 @@ config MM_KASAN_ALL to check. Enabling this option will get image size increased and performance decreased significantly. +config MM_KASAN_REGIONS + int "Kasan region count" + default 8 + config MM_KASAN_WATCHPOINT int "Kasan watchpoint maximum number" default 0 diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c index 4f1476ec1b..2a13364f32 100644 --- a/mm/kasan/generic.c +++ b/mm/kasan/generic.c @@ -52,13 +52,7 @@ (sizeof(struct kasan_region_s) + KASAN_SHADOW_SIZE(size)) #ifdef CONFIG_MM_KASAN_GLOBAL - # define KASAN_GLOBAL_SHADOW_SCALE (32) - -# define KASAN_GLOBAL_NEXT_REGION(region) \ - (FAR struct kasan_region_s *) \ - ((FAR char *)region->shadow + (size_t)region->next) - #endif /**************************************************************************** @@ -67,7 +61,6 @@ struct kasan_region_s { - FAR struct kasan_region_s *next; uintptr_t begin; uintptr_t end; uintptr_t shadow[1]; @@ -77,15 +70,16 @@ struct kasan_region_s * Private Data ****************************************************************************/ +static FAR struct kasan_region_s *g_region[CONFIG_MM_KASAN_REGIONS]; +static size_t g_region_count; static spinlock_t g_lock; -static FAR struct kasan_region_s *g_region; /**************************************************************************** * Public Data ****************************************************************************/ #ifdef CONFIG_MM_KASAN_GLOBAL -extern const unsigned char g_globals_region[]; +extern const struct kasan_region_s *g_global_region[]; #endif /**************************************************************************** @@ -96,35 +90,35 @@ static inline_function FAR uintptr_t * kasan_mem_to_shadow(FAR const void *ptr, size_t size, FAR unsigned int *bit, FAR size_t *align) { - FAR struct kasan_region_s *region; uintptr_t addr = (uintptr_t)ptr; + size_t i; - for (region = g_region; region != NULL; region = region->next) + for (i = 0; i < g_region_count; i++) { - if (addr >= region->begin && addr < region->end) + if (addr >= g_region[i]->begin && addr < g_region[i]->end) { - DEBUGASSERT(addr + size <= region->end); - addr -= region->begin; + DEBUGASSERT(addr + size <= g_region[i]->end); + addr -= g_region[i]->begin; *align = KASAN_SHADOW_SCALE; addr /= KASAN_SHADOW_SCALE; *bit = addr % KASAN_BITS_PER_WORD; - return ®ion->shadow[addr / KASAN_BITS_PER_WORD]; + return &g_region[i]->shadow[addr / KASAN_BITS_PER_WORD]; } } #ifdef CONFIG_MM_KASAN_GLOBAL - for (region = (FAR struct kasan_region_s *)g_globals_region; - region->next; - region = KASAN_GLOBAL_NEXT_REGION(region)) + for (i = 0; g_global_region[i]; i++) { - if (addr >= region->begin && addr < region->end) + if (addr >= g_global_region[i]->begin + && addr < g_global_region[i]->end) { - DEBUGASSERT(addr + size <= region->end); - addr -= region->begin; + DEBUGASSERT(addr + size <= g_global_region[i]->end); + addr -= g_global_region[i]->begin; *align = KASAN_GLOBAL_SHADOW_SCALE; addr /= KASAN_GLOBAL_SHADOW_SCALE; *bit = addr % KASAN_BITS_PER_WORD; - return ®ion->shadow[addr / KASAN_BITS_PER_WORD]; + return (FAR uintptr_t *) + &g_global_region[i]->shadow[addr / KASAN_BITS_PER_WORD]; } } #endif @@ -270,8 +264,10 @@ void kasan_register(FAR void *addr, FAR size_t *size) region->end = region->begin + *size; flags = spin_lock_irqsave(&g_lock); - region->next = g_region; - g_region = region; + + DEBUGASSERT(g_region_count <= CONFIG_MM_KASAN_REGIONS); + g_region[g_region_count++] = region; + spin_unlock_irqrestore(&g_lock, flags); kasan_start(); @@ -281,28 +277,19 @@ void kasan_register(FAR void *addr, FAR size_t *size) void kasan_unregister(FAR void *addr) { - FAR struct kasan_region_s *prev = NULL; - FAR struct kasan_region_s *region; irqstate_t flags; + size_t i; flags = spin_lock_irqsave(&g_lock); - for (region = g_region; region != NULL; region = region->next) + for (i = 0; i < g_region_count; i++) { - if (region->begin == (uintptr_t)addr) + if (g_region[i]->begin == (uintptr_t)addr) { - if (region == g_region) - { - g_region = region->next; - } - else - { - prev->next = region->next; - } - + g_region_count--; + memmove(&g_region[i], &g_region[i + 1], + (g_region_count - i) * sizeof(g_region[0])); break; } - - prev = region; } spin_unlock_irqrestore(&g_lock, flags); diff --git a/mm/kasan/sw_tags.c b/mm/kasan/sw_tags.c index e9737d32f1..c9592f17c3 100644 --- a/mm/kasan/sw_tags.c +++ b/mm/kasan/sw_tags.c @@ -58,7 +58,6 @@ struct kasan_region_s { - FAR struct kasan_region_s *next; uintptr_t begin; uintptr_t end; uint8_t shadow[1]; @@ -68,8 +67,9 @@ struct kasan_region_s * Private Data ****************************************************************************/ +static FAR struct kasan_region_s *g_region[CONFIG_MM_KASAN_REGIONS]; +static int g_region_count; static spinlock_t g_lock; -static FAR struct kasan_region_s *g_region; /**************************************************************************** * Private Functions @@ -78,18 +78,18 @@ static FAR struct kasan_region_s *g_region; static inline_function FAR uint8_t * kasan_mem_to_shadow(FAR const void *ptr, size_t size) { - FAR struct kasan_region_s *region; uintptr_t addr; + int i; addr = (uintptr_t)kasan_reset_tag(ptr); - for (region = g_region; region != NULL; region = region->next) + for (i = 0; i < g_region_count; i++) { - if (addr >= region->begin && addr < region->end) + if (addr >= g_region[i]->begin && addr < g_region[i]->end) { - DEBUGASSERT(addr + size <= region->end); - addr -= region->begin; - return ®ion->shadow[addr / KASAN_SHADOW_SCALE]; + DEBUGASSERT(addr + size <= g_region[i]->end); + addr -= g_region[i]->begin; + return &g_region[i]->shadow[addr / KASAN_SHADOW_SCALE]; } } @@ -179,8 +179,10 @@ void kasan_register(FAR void *addr, FAR size_t *size) region->end = region->begin + *size; flags = spin_lock_irqsave(&g_lock); - region->next = g_region; - g_region = region; + + DEBUGASSERT(g_region_count <= CONFIG_MM_KASAN_REGIONS); + g_region[g_region_count++] = region; + spin_unlock_irqrestore(&g_lock, flags); kasan_start(); @@ -190,28 +192,19 @@ void kasan_register(FAR void *addr, FAR size_t *size) void kasan_unregister(FAR void *addr) { - FAR struct kasan_region_s *prev = NULL; - FAR struct kasan_region_s *region; irqstate_t flags; + size_t i; flags = spin_lock_irqsave(&g_lock); - for (region = g_region; region != NULL; region = region->next) + for (i = 0; i < g_region_count; i++) { - if (region->begin == (uintptr_t)addr) + if (g_region[i]->begin == (uintptr_t)addr) { - if (region == g_region) - { - g_region = region->next; - } - else - { - prev->next = region->next; - } - + g_region_count--; + memmove(&g_region[i], &g_region[i + 1], + (g_region_count - i) * sizeof(g_region[0])); break; } - - prev = region; } spin_unlock_irqrestore(&g_lock, flags); diff --git a/tools/kasan_global.py b/tools/kasan_global.py index fc8496bbdf..061725fa96 100755 --- a/tools/kasan_global.py +++ b/tools/kasan_global.py @@ -196,24 +196,20 @@ def long_to_bytestring(bitwides, endian, value: int) -> str: def create_kasan_file(config: Config, region_list=[]): region: KASanRegion = None with open(config.outpath, "w") as file: - file.write("const unsigned char\ng_globals_region[] = {\n") + + # Write the kasan region array for i in range(len(region_list)): + file.write("static const unsigned char\nglobals_region%d[] = {\n" % (i)) region = region_list[i] # Fill the array of regions # The filling order is as follows, from mm/kasan/generic.c - # The data set to 0 is assigned by the program body - # 1. FAR struct kasan_region_s *next; - # This type will be used to record the size of the shadow area + # This type will be used to record the size of the shadow area # to facilitate the program to traverse the array. # 2. uintptr_t begin; # 3. uintptr_t end; # 4. uintptr_t shadow[1]; - file.write( - "%s\n" - % (long_to_bytestring(config.bitwides, config.endian, region.size)) - ) file.write( "%s\n" % (long_to_bytestring(config.bitwides, config.endian, region.start)) @@ -228,9 +224,13 @@ def create_kasan_file(config: Config, region_list=[]): file.write("\n") file.write("0x%02x, " % (region.shadow[j])) - file.write("\n") - file.write("0x00, 0x00, 0x00, 0x00,0x00, 0x00,0x00, 0x00\n") - file.write("\n};") + file.write("\n};") + + # Record kasan region pointer location + file.write("\nconst unsigned long g_global_region[] = {\n") + for i in range(len(region_list)): + file.write("\n(const unsigned long)&globals_region%d," % (i)) + file.write("0x00\n};") # Error extraction section processing to enable the program to compile successfully