diff --git a/include/nuttx/mm/kasan.h b/include/nuttx/mm/kasan.h index aeeb8f3f5c..18755e0551 100644 --- a/include/nuttx/mm/kasan.h +++ b/include/nuttx/mm/kasan.h @@ -39,7 +39,6 @@ #define kasan_init_early() kasan_stop() #ifndef CONFIG_MM_KASAN -# define kasan_is_poisoned(addr, size) false # define kasan_poison(addr, size) # define kasan_unpoison(addr, size) addr # define kasan_register(addr, size) @@ -59,23 +58,6 @@ extern "C" #define EXTERN extern #endif -/**************************************************************************** - * Name: kasan_is_poisoned - * - * Description: - * Check if the memory range is poisoned - * - * Input Parameters: - * addr - range start address - * size - range size - * - * Returned Value: - * true if the memory range is poisoned, false otherwise. - * - ****************************************************************************/ - -bool kasan_is_poisoned(FAR const void *addr, size_t size); - /**************************************************************************** * Name: kasan_poison * diff --git a/mm/kasan/CMakeLists.txt b/mm/kasan/CMakeLists.txt index 56b8e5425a..c904b5c03a 100644 --- a/mm/kasan/CMakeLists.txt +++ b/mm/kasan/CMakeLists.txt @@ -24,12 +24,10 @@ set(SRCS hook.c) if(CONFIG_MM_KASAN) list(APPEND FLAGS -fno-builtin) if(CONFIG_MM_KASAN_GENERIC) - list(APPEND SRCS generic.c) list(APPEND FLAGS -fno-sanitize=kernel-address) endif() if(CONFIG_MM_KASAN_SW_TAGS) - list(APPEND SRCS sw_tags.c) list(APPEND FLAGS -fno-sanitize=kernel-hwaddress) endif() diff --git a/mm/kasan/Make.defs b/mm/kasan/Make.defs index bc8e0c5696..23885b8ab6 100644 --- a/mm/kasan/Make.defs +++ b/mm/kasan/Make.defs @@ -27,12 +27,10 @@ ifeq ($(CONFIG_MM_KASAN),y) ifeq ($(CONFIG_ARCH_TOOLCHAIN_GNU),y) ifeq ($(CONFIG_MM_KASAN_GENERIC),y) - CSRCS += generic.c CFLAGS += -fno-sanitize=kernel-address endif ifeq ($(CONFIG_MM_KASAN_SW_TAGS),y) - CSRCS += sw_tags.c CFLAGS += -fno-sanitize=kernel-hwaddress endif diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c index a0ab366df3..4f1476ec1b 100644 --- a/mm/kasan/generic.c +++ b/mm/kasan/generic.c @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -91,9 +92,9 @@ extern const unsigned char g_globals_region[]; * Private Functions ****************************************************************************/ -static FAR uintptr_t *kasan_mem_to_shadow(FAR const void *ptr, size_t size, - FAR unsigned int *bit, - FAR size_t *align) +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; @@ -131,6 +132,57 @@ static FAR uintptr_t *kasan_mem_to_shadow(FAR const void *ptr, size_t size, return NULL; } +static inline_function bool +kasan_is_poisoned(FAR const void *addr, size_t size) +{ + FAR uintptr_t *p; + unsigned int bit; + unsigned int nbit; + uintptr_t mask; + size_t align; + + p = kasan_mem_to_shadow(addr, size, &bit, &align); + if (p == NULL) + { + return false; + } + + if (size <= align) + { + return ((*p >> bit) & 1); + } + + nbit = KASAN_BITS_PER_WORD - bit % KASAN_BITS_PER_WORD; + mask = KASAN_FIRST_WORD_MASK(bit); + size = ALIGN_UP(size, align); + size /= align; + + while (size >= nbit) + { + if ((*p++ & mask) != 0) + { + return true; + } + + bit += nbit; + size -= nbit; + + nbit = KASAN_BITS_PER_WORD; + mask = UINTPTR_MAX; + } + + if (size) + { + mask &= KASAN_LAST_WORD_MASK(bit + size); + if ((*p & mask) != 0) + { + return true; + } + } + + return false; +} + static void kasan_set_poison(FAR const void *addr, size_t size, bool poisoned) { @@ -195,56 +247,6 @@ FAR void *kasan_reset_tag(FAR const void *addr) return (FAR void *)addr; } -bool kasan_is_poisoned(FAR const void *addr, size_t size) -{ - FAR uintptr_t *p; - unsigned int bit; - unsigned int nbit; - uintptr_t mask; - size_t align; - - p = kasan_mem_to_shadow(addr, size, &bit, &align); - if (p == NULL) - { - return false; - } - - if (size <= align) - { - return ((*p >> bit) & 1); - } - - nbit = KASAN_BITS_PER_WORD - bit % KASAN_BITS_PER_WORD; - mask = KASAN_FIRST_WORD_MASK(bit); - size = ALIGN_UP(size, align); - size /= align; - - while (size >= nbit) - { - if ((*p++ & mask) != 0) - { - return true; - } - - bit += nbit; - size -= nbit; - - nbit = KASAN_BITS_PER_WORD; - mask = UINTPTR_MAX; - } - - if (size) - { - mask &= KASAN_LAST_WORD_MASK(bit + size); - if ((*p & mask) != 0) - { - return true; - } - } - - return false; -} - void kasan_poison(FAR const void *addr, size_t size) { kasan_set_poison(addr, size, true); diff --git a/mm/kasan/hook.c b/mm/kasan/hook.c index 56f06f523e..7b50ca5d44 100644 --- a/mm/kasan/hook.c +++ b/mm/kasan/hook.c @@ -31,6 +31,14 @@ #include #include +#ifdef CONFIG_MM_KASAN_GENERIC +# include "generic.c" +#elif defined(CONFIG_MM_KASAN_SW_TAGS) +# include "sw_tags.c" +#else +# define kasan_is_poisoned(addr, size) false +#endif + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ diff --git a/mm/kasan/sw_tags.c b/mm/kasan/sw_tags.c index 572d7964e9..e9737d32f1 100644 --- a/mm/kasan/sw_tags.c +++ b/mm/kasan/sw_tags.c @@ -23,6 +23,7 @@ ****************************************************************************/ #include +#include #include #include @@ -74,7 +75,8 @@ static FAR struct kasan_region_s *g_region; * Private Functions ****************************************************************************/ -static FAR uint8_t *kasan_mem_to_shadow(FAR const void *ptr, size_t size) +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; @@ -94,6 +96,31 @@ static FAR uint8_t *kasan_mem_to_shadow(FAR const void *ptr, size_t size) return NULL; } +static inline_function bool +kasan_is_poisoned(FAR const void *addr, size_t size) +{ + FAR uint8_t *p; + uint8_t tag; + + tag = kasan_get_tag(addr); + p = kasan_mem_to_shadow(addr, size); + if (p == NULL) + { + return false; + } + + size = KASAN_SHADOW_SIZE(size); + while (size--) + { + if (p[size] != tag) + { + return true; + } + } + + return false; +} + static void kasan_set_poison(FAR const void *addr, size_t size, uint8_t value) { @@ -127,30 +154,6 @@ FAR void *kasan_reset_tag(FAR const void *addr) (((uint64_t)(addr)) & ~((uint64_t)0xff << KASAN_TAG_SHIFT)); } -bool kasan_is_poisoned(FAR const void *addr, size_t size) -{ - FAR uint8_t *p; - uint8_t tag; - - tag = kasan_get_tag(addr); - p = kasan_mem_to_shadow(addr, size); - if (p == NULL) - { - return false; - } - - size = KASAN_SHADOW_SIZE(size); - while (size--) - { - if (p[size] != tag) - { - return true; - } - } - - return false; -} - void kasan_poison(FAR const void *addr, size_t size) { kasan_set_poison(addr, size, 0xff);