mm/kasan: Tag kasan and generic kasan use the same instrumentation options
1. Tested on QEMU, the two sockets were basically the same, and their performance was not affected. The size of the generated bin file was also the same 2. Extract global detection as a separate file, both types of Kasan support global variable out of bounds detection simultaneously Signed-off-by: wangmingrong1 <wangmingrong1@xiaomi.com>
This commit is contained in:
parent
5c511443fe
commit
071af0c993
@ -143,4 +143,3 @@ If you want the module you are writing to not be inserted by the compiler,
|
||||
you can add the option 'CFLAGS += -fno-sanitize=kernel-address' to a single module.
|
||||
If it is a file, you can write it this way,
|
||||
special_file.o: CFLAGS = -fno-sanitize=kernel-address
|
||||
or : special_file.o: CFLAGS = -fno-sanitize=kernel-hwaddress
|
||||
|
@ -79,11 +79,7 @@ ifeq ($(CONFIG_MM_UBSAN_TRAP_ON_ERROR),y)
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_MM_KASAN_ALL),y)
|
||||
ifeq ($(CONFIG_MM_KASAN_GENERIC),y)
|
||||
ARCHOPTIMIZATION += -fsanitize=kernel-address
|
||||
else ifeq ($(CONFIG_MM_KASAN_SW_TAGS),y)
|
||||
ARCHOPTIMIZATION += -fsanitize=kernel-hwaddress
|
||||
endif
|
||||
ARCHOPTIMIZATION += -fsanitize=kernel-address
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_MM_KASAN_GLOBAL),y)
|
||||
|
@ -328,7 +328,7 @@ config MM_KASAN_DISABLE_WRITES_CHECK
|
||||
|
||||
config MM_KASAN_GLOBAL
|
||||
bool "Enable global data check"
|
||||
depends on MM_KASAN_GENERIC
|
||||
depends on MM_KASAN_ALL
|
||||
default n
|
||||
---help---
|
||||
This option enables KASan global data check.
|
||||
|
@ -23,13 +23,7 @@ set(SRCS hook.c)
|
||||
|
||||
if(CONFIG_MM_KASAN)
|
||||
list(APPEND FLAGS -fno-builtin)
|
||||
if(CONFIG_MM_KASAN_GENERIC)
|
||||
list(APPEND FLAGS -fno-sanitize=kernel-address)
|
||||
endif()
|
||||
|
||||
if(CONFIG_MM_KASAN_SW_TAGS)
|
||||
list(APPEND FLAGS -fno-sanitize=kernel-hwaddress)
|
||||
endif()
|
||||
list(APPEND FLAGS -fno-sanitize=kernel-address)
|
||||
|
||||
if(CONFIG_LTO_NONE)
|
||||
list(APPEND FLAGS -fno-lto)
|
||||
|
@ -23,23 +23,14 @@
|
||||
CSRCS += hook.c
|
||||
|
||||
ifeq ($(CONFIG_MM_KASAN),y)
|
||||
|
||||
ifeq ($(CONFIG_MM_KASAN_GENERIC),y)
|
||||
CFLAGS += -fno-sanitize=kernel-address
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_MM_KASAN_SW_TAGS),y)
|
||||
CFLAGS += -fno-sanitize=kernel-hwaddress
|
||||
endif
|
||||
CFLAGS += -fno-builtin
|
||||
CFLAGS += -fno-sanitize=kernel-address
|
||||
|
||||
ifeq ($(CONFIG_LTO_NONE),n)
|
||||
CFLAGS += -fno-lto
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
CFLAGS += -fno-builtin
|
||||
|
||||
# Add the core heap directory to the build
|
||||
|
||||
DEPPATH += --dep-path kasan
|
||||
|
@ -51,10 +51,6 @@
|
||||
#define KASAN_REGION_SIZE(size) \
|
||||
(sizeof(struct kasan_region_s) + KASAN_SHADOW_SIZE(size))
|
||||
|
||||
#ifdef CONFIG_MM_KASAN_GLOBAL
|
||||
# define KASAN_GLOBAL_SHADOW_SCALE (32)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
@ -74,21 +70,13 @@ static FAR struct kasan_region_s *g_region[CONFIG_MM_KASAN_REGIONS];
|
||||
static size_t g_region_count;
|
||||
static spinlock_t g_lock;
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_MM_KASAN_GLOBAL
|
||||
extern const struct kasan_region_s *g_global_region[];
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
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 unsigned int *bit)
|
||||
{
|
||||
uintptr_t addr = (uintptr_t)ptr;
|
||||
size_t i;
|
||||
@ -99,30 +87,12 @@ kasan_mem_to_shadow(FAR const void *ptr, size_t size,
|
||||
{
|
||||
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 &g_region[i]->shadow[addr / KASAN_BITS_PER_WORD];
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MM_KASAN_GLOBAL
|
||||
for (i = 0; g_global_region[i]; i++)
|
||||
{
|
||||
if (addr >= g_global_region[i]->begin
|
||||
&& addr < g_global_region[i]->end)
|
||||
{
|
||||
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 (FAR uintptr_t *)
|
||||
&g_global_region[i]->shadow[addr / KASAN_BITS_PER_WORD];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -133,23 +103,22 @@ kasan_is_poisoned(FAR const void *addr, size_t size)
|
||||
unsigned int bit;
|
||||
unsigned int nbit;
|
||||
uintptr_t mask;
|
||||
size_t align;
|
||||
|
||||
p = kasan_mem_to_shadow(addr, size, &bit, &align);
|
||||
p = kasan_mem_to_shadow(addr, size, &bit);
|
||||
if (p == NULL)
|
||||
{
|
||||
return false;
|
||||
return kasan_global_is_poisoned(addr, size);
|
||||
}
|
||||
|
||||
if (size <= align)
|
||||
if (size <= KASAN_SHADOW_SCALE)
|
||||
{
|
||||
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;
|
||||
size = ALIGN_UP(size, KASAN_SHADOW_SCALE);
|
||||
size /= KASAN_SHADOW_SCALE;
|
||||
|
||||
while (size >= nbit)
|
||||
{
|
||||
@ -185,9 +154,8 @@ static void kasan_set_poison(FAR const void *addr, size_t size,
|
||||
unsigned int bit;
|
||||
unsigned int nbit;
|
||||
uintptr_t mask;
|
||||
size_t align;
|
||||
|
||||
p = kasan_mem_to_shadow(addr, size, &bit, &align);
|
||||
p = kasan_mem_to_shadow(addr, size, &bit);
|
||||
if (p == NULL)
|
||||
{
|
||||
return;
|
||||
@ -195,7 +163,7 @@ static void kasan_set_poison(FAR const void *addr, size_t size,
|
||||
|
||||
nbit = KASAN_BITS_PER_WORD - bit % KASAN_BITS_PER_WORD;
|
||||
mask = KASAN_FIRST_WORD_MASK(bit);
|
||||
size /= align;
|
||||
size /= KASAN_SHADOW_SCALE;
|
||||
|
||||
flags = spin_lock_irqsave(&g_lock);
|
||||
while (size >= nbit)
|
||||
|
138
mm/kasan/global.c
Normal file
138
mm/kasan/global.c
Normal file
@ -0,0 +1,138 @@
|
||||
/****************************************************************************
|
||||
* mm/kasan/global.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/nuttx.h>
|
||||
#include <nuttx/mm/kasan.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define KASAN_BYTES_PER_WORD (sizeof(uintptr_t))
|
||||
#define KASAN_BITS_PER_WORD (KASAN_BYTES_PER_WORD * 8)
|
||||
|
||||
#define KASAN_GLOBAL_FIRST_WORD_MASK(start) \
|
||||
(UINTPTR_MAX << ((start) & (KASAN_BITS_PER_WORD - 1)))
|
||||
#define KASAN_GLOBAL_LAST_WORD_MASK(end) \
|
||||
(UINTPTR_MAX >> (-(end) & (KASAN_BITS_PER_WORD - 1)))
|
||||
|
||||
#define KASAN_GLOBAL_SHADOW_SCALE (32)
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
struct kasan_global_region_s
|
||||
{
|
||||
uintptr_t begin;
|
||||
uintptr_t end;
|
||||
uintptr_t shadow[1];
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
extern const struct kasan_global_region_s *g_global_region[];
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static inline_function FAR uintptr_t *
|
||||
kasan_global_mem_to_shadow(FAR const void *ptr, size_t size,
|
||||
FAR unsigned int *bit)
|
||||
{
|
||||
uintptr_t addr = (uintptr_t)ptr;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; g_global_region[i]; i++)
|
||||
{
|
||||
if (addr >= g_global_region[i]->begin &&
|
||||
addr < g_global_region[i]->end)
|
||||
{
|
||||
DEBUGASSERT(addr + size <= g_global_region[i]->end);
|
||||
addr -= g_global_region[i]->begin;
|
||||
addr /= KASAN_GLOBAL_SHADOW_SCALE;
|
||||
*bit = addr % KASAN_BITS_PER_WORD;
|
||||
return (FAR uintptr_t *)
|
||||
&g_global_region[i]->shadow[addr / KASAN_BITS_PER_WORD];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline_function bool
|
||||
kasan_global_is_poisoned(FAR const void *addr, size_t size)
|
||||
{
|
||||
FAR uintptr_t *p;
|
||||
unsigned int bit;
|
||||
unsigned int nbit;
|
||||
uintptr_t mask;
|
||||
|
||||
p = kasan_global_mem_to_shadow(addr, size, &bit);
|
||||
if (p == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (size <= KASAN_GLOBAL_SHADOW_SCALE)
|
||||
{
|
||||
return ((*p >> bit) & 1);
|
||||
}
|
||||
|
||||
nbit = KASAN_BITS_PER_WORD - bit % KASAN_BITS_PER_WORD;
|
||||
mask = KASAN_GLOBAL_FIRST_WORD_MASK(bit);
|
||||
size = ALIGN_UP(size, KASAN_GLOBAL_SHADOW_SCALE);
|
||||
size /= KASAN_GLOBAL_SHADOW_SCALE;
|
||||
|
||||
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_GLOBAL_LAST_WORD_MASK(bit + size);
|
||||
if ((*p & mask) != 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
@ -32,6 +32,12 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef CONFIG_MM_KASAN_GLOBAL
|
||||
# include "global.c"
|
||||
#else
|
||||
# define kasan_global_is_poisoned(addr, size) false
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MM_KASAN_GENERIC
|
||||
# include "generic.c"
|
||||
#elif defined(CONFIG_MM_KASAN_SW_TAGS)
|
||||
@ -70,16 +76,6 @@
|
||||
kasan_check_report(addr, size, true, return_address(0)); \
|
||||
}
|
||||
|
||||
#define DEFINE_HWASAN_LOAD_STORE(size) \
|
||||
void __hwasan_load##size##_noabort(void *addr) \
|
||||
{ \
|
||||
kasan_check_report(addr, size, false, return_address(0)); \
|
||||
} \
|
||||
void __hwasan_store##size##_noabort(void *addr) \
|
||||
{ \
|
||||
kasan_check_report(addr, size, true, return_address(0)); \
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MM_KASAN_DISABLE_READ_PANIC
|
||||
# define MM_KASAN_DISABLE_READ_PANIC 1
|
||||
#else
|
||||
@ -403,21 +399,3 @@ DEFINE_ASAN_LOAD_STORE(2)
|
||||
DEFINE_ASAN_LOAD_STORE(4)
|
||||
DEFINE_ASAN_LOAD_STORE(8)
|
||||
DEFINE_ASAN_LOAD_STORE(16)
|
||||
|
||||
/* Soft tags KASan will instrument the following functions */
|
||||
|
||||
void __hwasan_loadN_noabort(FAR void *addr, size_t size)
|
||||
{
|
||||
kasan_check_report(addr, size, false, return_address(0));
|
||||
}
|
||||
|
||||
void __hwasan_storeN_noabort(FAR void *addr, size_t size)
|
||||
{
|
||||
kasan_check_report(addr, size, true, return_address(0));
|
||||
}
|
||||
|
||||
DEFINE_HWASAN_LOAD_STORE(1)
|
||||
DEFINE_HWASAN_LOAD_STORE(2)
|
||||
DEFINE_HWASAN_LOAD_STORE(4)
|
||||
DEFINE_HWASAN_LOAD_STORE(8)
|
||||
DEFINE_HWASAN_LOAD_STORE(16)
|
||||
|
@ -106,7 +106,7 @@ kasan_is_poisoned(FAR const void *addr, size_t size)
|
||||
p = kasan_mem_to_shadow(addr, size);
|
||||
if (p == NULL)
|
||||
{
|
||||
return false;
|
||||
return kasan_global_is_poisoned(addr, size);
|
||||
}
|
||||
|
||||
size = KASAN_SHADOW_SIZE(size);
|
||||
|
Loading…
Reference in New Issue
Block a user