This is an automated email from the ASF dual-hosted git repository. xiaoxiang781216 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit e2e5ed6a53b39cdc3d56ae258dcf8bd0412bf3c1 Author: wangmingrong1 <[email protected]> AuthorDate: Wed Jan 21 15:02:43 2026 +0800 kasan: Use atomic to increment g_region_count An error occurs when `g_region_count` is incremented, but the data is not updated in time when other cores in SMP iterate through `g_region`, causing the error. Signed-off-by: wangmingrong1 <[email protected]> --- mm/kasan/generic.c | 15 ++++++++++----- mm/kasan/sw_tags.c | 15 ++++++++++----- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c index 3510c2b39aa..ddeba0158d5 100644 --- a/mm/kasan/generic.c +++ b/mm/kasan/generic.c @@ -67,7 +67,7 @@ struct kasan_region_s ****************************************************************************/ static FAR struct kasan_region_s *g_region[CONFIG_MM_KASAN_REGIONS]; -static size_t g_region_count; +static atomic_t g_region_count; static spinlock_t g_lock; /**************************************************************************** @@ -78,10 +78,11 @@ static inline_function FAR uintptr_t * kasan_mem_to_shadow(FAR const void *ptr, size_t size, FAR unsigned int *bit) { + size_t count = atomic_read(&g_region_count); uintptr_t addr = (uintptr_t)ptr; size_t i; - for (i = 0; i < g_region_count; i++) + for (i = 0; i < count; i++) { if (addr >= g_region[i]->begin && addr < g_region[i]->end) { @@ -239,6 +240,7 @@ void kasan_register(FAR void *addr, FAR size_t *size) { FAR struct kasan_region_s *region; irqstate_t flags; + size_t idx; region = (FAR struct kasan_region_s *) ((FAR char *)addr + *size - KASAN_REGION_SIZE(*size)); @@ -248,8 +250,10 @@ void kasan_register(FAR void *addr, FAR size_t *size) flags = spin_lock_irqsave_notrace(&g_lock); - DEBUGASSERT(g_region_count < CONFIG_MM_KASAN_REGIONS); - g_region[g_region_count++] = region; + idx = atomic_read(&g_region_count); + DEBUGASSERT(idx < CONFIG_MM_KASAN_REGIONS); + g_region[idx] = region; + atomic_add(&g_region_count, 1); spin_unlock_irqrestore_notrace(&g_lock, flags); @@ -270,7 +274,8 @@ void kasan_unregister(FAR void *addr) { size_t size = g_region[i]->end - g_region[i]->begin; - g_region_count--; + atomic_sub(&g_region_count, 1); + g_region[i] = NULL; memmove(&g_region[i], &g_region[i + 1], (g_region_count - i) * sizeof(g_region[0])); spin_unlock_irqrestore_notrace(&g_lock, flags); diff --git a/mm/kasan/sw_tags.c b/mm/kasan/sw_tags.c index c5640412f8f..90dbbd9fa98 100644 --- a/mm/kasan/sw_tags.c +++ b/mm/kasan/sw_tags.c @@ -61,7 +61,7 @@ struct kasan_region_s ****************************************************************************/ static FAR struct kasan_region_s *g_region[CONFIG_MM_KASAN_REGIONS]; -static int g_region_count; +static atomic_t g_region_count; static spinlock_t g_lock; /**************************************************************************** @@ -71,12 +71,13 @@ static spinlock_t g_lock; static inline_function FAR uint8_t * kasan_mem_to_shadow(FAR const void *ptr, size_t size) { + size_t count = atomic_read(&g_region_count); uintptr_t addr; int i; addr = (uintptr_t)kasan_clear_tag(ptr); - for (i = 0; i < g_region_count; i++) + for (i = 0; i < count; i++) { if (addr >= g_region[i]->begin && addr < g_region[i]->end) { @@ -188,6 +189,7 @@ void kasan_register(FAR void *addr, FAR size_t *size) { FAR struct kasan_region_s *region; irqstate_t flags; + size_t idx; region = (FAR struct kasan_region_s *) ((FAR char *)addr + *size - KASAN_REGION_SIZE(*size)); @@ -197,8 +199,10 @@ void kasan_register(FAR void *addr, FAR size_t *size) flags = spin_lock_irqsave(&g_lock); - DEBUGASSERT(g_region_count < CONFIG_MM_KASAN_REGIONS); - g_region[g_region_count++] = region; + idx = atomic_read(&g_region_count); + DEBUGASSERT(idx < CONFIG_MM_KASAN_REGIONS); + g_region[idx] = region; + atomic_add(&g_region_count, 1); spin_unlock_irqrestore(&g_lock, flags); @@ -219,7 +223,8 @@ void kasan_unregister(FAR void *addr) { size_t size = g_region[i]->end - g_region[i]->begin; - g_region_count--; + atomic_sub(&g_region_count, 1); + g_region[i] = NULL; memmove(&g_region[i], &g_region[i + 1], (g_region_count - i) * sizeof(g_region[0])); spin_unlock_irqrestore(&g_lock, flags);
