From 5c511443fefcb000f1fb766542b7f44e09f53d05 Mon Sep 17 00:00:00 2001 From: wangmingrong1 Date: Thu, 12 Sep 2024 11:24:54 +0800 Subject: [PATCH] mm/kasan: Using arrays instead of linked lists 1. Modify the Kasan global variable script to support array storage of region addresses 2. Due to the lack of formatting in the previous attempt, a formatting script was created Signed-off-by: wangmingrong1 --- mm/Kconfig | 4 +++ mm/kasan/generic.c | 65 +++++++++++++++++-------------------------- mm/kasan/sw_tags.c | 43 ++++++++++++---------------- tools/kasan_global.py | 22 +++++++-------- 4 files changed, 59 insertions(+), 75 deletions(-) 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