kasan: Implementation of Kasan based on software tags.
Currently, only aarch64 is supported Signed-off-by: wangmingrong <wangmingrong@xiaomi.com>
This commit is contained in:
parent
9c6bed4b00
commit
ae3facda53
@ -19,6 +19,7 @@ Guides
|
||||
customapps.rst
|
||||
citests.rst
|
||||
zerolatencyinterrupts.rst
|
||||
kasan.rst
|
||||
nestedinterrupts.rst
|
||||
cortexmhardfaults.rst
|
||||
coredump.rst
|
||||
|
@ -8,17 +8,23 @@ Overview
|
||||
Kernel Address Sanitizer (KASAN) is a dynamic memory safety error detector
|
||||
designed to find out-of-bounds and use-after-free bugs.
|
||||
|
||||
The current version of NuttX has one modes:
|
||||
The current version of NuttX has two modes:
|
||||
|
||||
1. Generic KASAN
|
||||
2. Software Tag-Based KASAN
|
||||
|
||||
Generic KASAN, enabled with CONFIG_MM_KASAN, is the mode intended for
|
||||
Generic KASAN, enabled with CONFIG_MM_KASAN_GENERIC, is the mode intended for
|
||||
debugging, similar to linux user level ASan. This mode is supported on many CPU
|
||||
architectures, but it has significant performance and memory overheads.
|
||||
The current NuttX Generic KASAN can support memory out of bounds detection
|
||||
allocated by the default NuttX heap allocator,which depends on CONFIG_MM_DEFAULT_MANAGER
|
||||
or CONFIG_MM_TLSF_MANAGER, and detection of out of bounds with global variables.
|
||||
|
||||
Software Tag-Based KASAN or SW_TAGS KASAN, enabled with CONFIG_MM_KASAN_SW_TAGS,
|
||||
can be used for both debugging, This mode is only supported for arm64,
|
||||
but its moderate memory overhead allows using it for testing on
|
||||
memory-restricted devices with real workloads.
|
||||
|
||||
Support
|
||||
-------
|
||||
|
||||
@ -27,20 +33,33 @@ Architectures
|
||||
|
||||
Generic KASAN is supported on x86_64, arm, arm64, riscv, xtensa and so on.
|
||||
|
||||
Software Tag-Based KASAN modes are supported only on arm64.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
To enable Generic KASAN, configure the kernel with::
|
||||
|
||||
CONFIG_MM_KASAN=y
|
||||
CONFIG_MM_KASAN_ALL=y
|
||||
CONFIG_MM_KASAN_GENERIC=y
|
||||
|
||||
If you want to enable global variable out of bounds detection,
|
||||
you can add configurations based on the above::
|
||||
|
||||
CONFIG_MM_KASAN_GLOBAL=y
|
||||
|
||||
To enable Software Tag-Based KASAN, configure the kernel with::
|
||||
|
||||
CONFIG_MM_KASAN=y
|
||||
CONFIG_MM_KASAN_ALL=y
|
||||
CONFIG_MM_KASAN_SW_TAGS=y
|
||||
|
||||
Implementation details
|
||||
----------------------
|
||||
|
||||
Generic KASAN:
|
||||
|
||||
Compile with param -fsanitize=kernel-address,
|
||||
Compile-time instrumentation is used to insert memory access checks. Compiler
|
||||
inserts function calls (``__asan_load*(addr)``, ``__asan_store*(addr)``) before
|
||||
@ -94,6 +113,26 @@ The data generated by the compiler will be placed in a non-existent memory block
|
||||
After the compilation is completed, this segment will be deleted
|
||||
and will not be copied to the bin file of the final burned board.
|
||||
|
||||
Software Tag-Based KASAN:
|
||||
|
||||
Software Tag-Based KASAN uses a software memory tagging approach to checking
|
||||
access validity. It is currently only implemented for the arm64 architecture.
|
||||
|
||||
Software Tag-Based KASAN uses the Top Byte Ignore (TBI) feature of arm64 CPUs
|
||||
to store a pointer tag in the top byte of kernel pointers. It uses shadow memory
|
||||
to store memory tags associated with each heap allocated memory cell (therefore, it
|
||||
dedicates 1/8 th of the kernel memory for shadow memory).
|
||||
|
||||
On each memory allocation, Software Tag-Based KASAN generates a random tag, tags
|
||||
the allocated memory with this tag, and embeds the same tag into the returned
|
||||
pointer.
|
||||
|
||||
Software Tag-Based KASAN uses compile-time instrumentation to insert checks
|
||||
before each memory access. These checks make sure that the tag of the memory
|
||||
that is being accessed is equal to the tag of the pointer that is used to access
|
||||
this memory. In case of a tag mismatch, Software Tag-Based KASAN prints a bug
|
||||
report.
|
||||
|
||||
For developers
|
||||
--------------
|
||||
|
||||
@ -102,4 +141,6 @@ Ignoring accesses
|
||||
|
||||
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
|
||||
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,7 +79,11 @@ ifeq ($(CONFIG_MM_UBSAN_TRAP_ON_ERROR),y)
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_MM_KASAN_ALL),y)
|
||||
ARCHOPTIMIZATION += -fsanitize=kernel-address
|
||||
ifeq ($(CONFIG_MM_KASAN_GENERIC),y)
|
||||
ARCHOPTIMIZATION += -fsanitize=kernel-address
|
||||
else ifeq ($(CONFIG_MM_KASAN_SW_TAGS),y)
|
||||
ARCHOPTIMIZATION += -fsanitize=kernel-hwaddress
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_MM_KASAN_GLOBAL),y)
|
||||
|
@ -153,6 +153,12 @@
|
||||
#define TCR_PS_BITS TCR_PS_BITS_4GB
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MM_KASAN_SW_TAGS
|
||||
#define TCR_KASAN_SW_FLAGS (TCR_TBI0 | TCR_TBI1 | TCR_ASID_8)
|
||||
#else
|
||||
#define TCR_KASAN_SW_FLAGS 0
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
@ -254,7 +260,8 @@ static uint64_t get_tcr(int el)
|
||||
* inner shareable
|
||||
*/
|
||||
|
||||
tcr |= TCR_TG0_4K | TCR_SHARED_INNER | TCR_ORGN_WBWA | TCR_IRGN_WBWA;
|
||||
tcr |= TCR_TG0_4K | TCR_SHARED_INNER | TCR_ORGN_WBWA |
|
||||
TCR_IRGN_WBWA | TCR_KASAN_SW_FLAGS;
|
||||
|
||||
return tcr;
|
||||
}
|
||||
|
@ -149,6 +149,12 @@
|
||||
#define TCR_TG0_16K (2ULL << 14)
|
||||
#define TCR_EPD1_DISABLE (1ULL << 23)
|
||||
|
||||
#define TCR_AS_SHIFT 36U
|
||||
#define TCR_ASID_8 (0ULL << TCR_AS_SHIFT)
|
||||
#define TCR_ASID_16 (1ULL << TCR_AS_SHIFT)
|
||||
#define TCR_TBI0 (1ULL << 37)
|
||||
#define TCR_TBI1 (1ULL << 38)
|
||||
|
||||
#define TCR_PS_BITS_4GB 0x0ULL
|
||||
#define TCR_PS_BITS_64GB 0x1ULL
|
||||
#define TCR_PS_BITS_1TB 0x2ULL
|
||||
|
@ -37,9 +37,10 @@
|
||||
#ifndef CONFIG_MM_KASAN
|
||||
# define kasan_is_poisoned(addr, size) false
|
||||
# define kasan_poison(addr, size)
|
||||
# define kasan_unpoison(addr, size)
|
||||
# define kasan_unpoison(addr, size) addr
|
||||
# define kasan_register(addr, size)
|
||||
# define kasan_init_early()
|
||||
# define kasan_reset_tag(addr) addr
|
||||
#else
|
||||
|
||||
/****************************************************************************
|
||||
@ -99,11 +100,11 @@ void kasan_poison(FAR const void *addr, size_t size);
|
||||
* size - range size
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
* Return tagged address
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void kasan_unpoison(FAR const void *addr, size_t size);
|
||||
FAR void *kasan_unpoison(FAR const void *addr, size_t size);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: kasan_register
|
||||
@ -143,6 +144,19 @@ void kasan_register(FAR void *addr, FAR size_t *size);
|
||||
|
||||
void kasan_init_early(void);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: kasan_reset_tag
|
||||
*
|
||||
* Input Parameters:
|
||||
* addr - The address of the memory to reset the tag.
|
||||
*
|
||||
* Returned Value:
|
||||
* Unlabeled address
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR void *kasan_reset_tag(FAR const void *addr);
|
||||
|
||||
#undef EXTERN
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
21
mm/Kconfig
21
mm/Kconfig
@ -258,6 +258,25 @@ config MM_KASAN
|
||||
bugs in native code. After turn on this option, Please
|
||||
add -fsanitize=kernel-address to CFLAGS/CXXFLAGS too.
|
||||
|
||||
if MM_KASAN
|
||||
|
||||
choice
|
||||
prompt "KAsan Mode"
|
||||
default MM_KASAN_GENERIC
|
||||
|
||||
config MM_KASAN_GENERIC
|
||||
bool "KAsan generic mode"
|
||||
---help---
|
||||
KASan generic mode that does not require hardware support at all
|
||||
|
||||
config MM_KASAN_SW_TAGS
|
||||
bool "KAsan SW tags"
|
||||
depends on ARCH_ARM64
|
||||
---help---
|
||||
KAsan based on software tags
|
||||
|
||||
endchoice
|
||||
|
||||
config MM_KASAN_ALL
|
||||
bool "Enable KASan for the entire image"
|
||||
depends on MM_KASAN
|
||||
@ -288,7 +307,7 @@ config MM_KASAN_DISABLE_WRITES_CHECK
|
||||
|
||||
config MM_KASAN_GLOBAL
|
||||
bool "Enable global data check"
|
||||
depends on MM_KASAN
|
||||
depends on MM_KASAN_GENERIC
|
||||
default n
|
||||
---help---
|
||||
This option enables KASan global data check.
|
||||
|
@ -23,16 +23,24 @@
|
||||
CSRCS += hook.c
|
||||
|
||||
ifeq ($(CONFIG_MM_KASAN),y)
|
||||
CSRCS += generic.c
|
||||
|
||||
# Disable kernel-address in mm subsystem
|
||||
|
||||
ifeq ($(CONFIG_ARCH_TOOLCHAIN_GNU),y)
|
||||
CFLAGS += -fno-sanitize=kernel-address
|
||||
|
||||
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
|
||||
|
||||
ifeq ($(CONFIG_LTO_NONE),n)
|
||||
CFLAGS += -fno-lto
|
||||
endif
|
||||
|
||||
endif
|
||||
endif
|
||||
|
||||
# Add the core heap directory to the build
|
||||
|
@ -139,10 +139,10 @@ static void kasan_set_poison(FAR const void *addr, size_t size,
|
||||
bool poisoned)
|
||||
{
|
||||
FAR uintptr_t *p;
|
||||
irqstate_t flags;
|
||||
unsigned int bit;
|
||||
unsigned int nbit;
|
||||
uintptr_t mask;
|
||||
int flags;
|
||||
|
||||
p = kasan_mem_to_shadow(addr, size, &bit);
|
||||
if (p == NULL)
|
||||
@ -193,6 +193,11 @@ static void kasan_set_poison(FAR const void *addr, size_t size,
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
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;
|
||||
@ -207,9 +212,10 @@ void kasan_poison(FAR const void *addr, size_t size)
|
||||
kasan_set_poison(addr, size, true);
|
||||
}
|
||||
|
||||
void kasan_unpoison(FAR const void *addr, size_t size)
|
||||
FAR void *kasan_unpoison(FAR const void *addr, size_t size)
|
||||
{
|
||||
kasan_set_poison(addr, size, false);
|
||||
return (FAR void *)addr;
|
||||
}
|
||||
|
||||
void kasan_register(FAR void *addr, FAR size_t *size)
|
||||
|
@ -31,6 +31,46 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define DEFINE_ASAN_LOAD_STORE(size) \
|
||||
void __asan_report_load##size##_noabort(FAR void *addr) \
|
||||
{ \
|
||||
kasan_report(addr, size, false, return_address(0)); \
|
||||
} \
|
||||
void __asan_report_store##size##_noabort(FAR void *addr) \
|
||||
{ \
|
||||
kasan_report(addr, size, true, return_address(0)); \
|
||||
} \
|
||||
void __asan_load##size##_noabort(FAR void *addr) \
|
||||
{ \
|
||||
kasan_check_report(addr, size, false, return_address(0)); \
|
||||
} \
|
||||
void __asan_store##size##_noabort(FAR void *addr) \
|
||||
{ \
|
||||
kasan_check_report(addr, size, true, return_address(0)); \
|
||||
} \
|
||||
void __asan_load##size(FAR void *addr) \
|
||||
{ \
|
||||
kasan_check_report(addr, size, false, return_address(0)); \
|
||||
} \
|
||||
void __asan_store##size(FAR void *addr) \
|
||||
{ \
|
||||
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)); \
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
@ -181,34 +221,28 @@ void __asan_storeN(FAR void *addr, size_t size)
|
||||
kasan_check_report(addr, size, true, return_address(0));
|
||||
}
|
||||
|
||||
#define DEFINE_ASAN_LOAD_STORE(size) \
|
||||
void __asan_report_load##size##_noabort(FAR void *addr) \
|
||||
{ \
|
||||
kasan_report(addr, size, false, return_address(0)); \
|
||||
} \
|
||||
void __asan_report_store##size##_noabort(FAR void *addr) \
|
||||
{ \
|
||||
kasan_report(addr, size, true, return_address(0)); \
|
||||
} \
|
||||
void __asan_load##size##_noabort(FAR void *addr) \
|
||||
{ \
|
||||
kasan_check_report(addr, size, false, return_address(0)); \
|
||||
} \
|
||||
void __asan_store##size##_noabort(FAR void *addr) \
|
||||
{ \
|
||||
kasan_check_report(addr, size, true, return_address(0)); \
|
||||
} \
|
||||
void __asan_load##size(FAR void *addr) \
|
||||
{ \
|
||||
kasan_check_report(addr, size, false, return_address(0)); \
|
||||
} \
|
||||
void __asan_store##size(FAR void *addr) \
|
||||
{ \
|
||||
kasan_check_report(addr, size, true, return_address(0)); \
|
||||
}
|
||||
/* Generic KASan will instrument the following functions */
|
||||
|
||||
DEFINE_ASAN_LOAD_STORE(1)
|
||||
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)
|
||||
|
199
mm/kasan/sw_tags.c
Normal file
199
mm/kasan/sw_tags.c
Normal file
@ -0,0 +1,199 @@
|
||||
/****************************************************************************
|
||||
* mm/kasan/sw_tags.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/mm/kasan.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define KASAN_TAG_SHIFT 56
|
||||
|
||||
#define kasan_get_tag(addr) \
|
||||
((uint8_t)((uint64_t)(addr) >> KASAN_TAG_SHIFT))
|
||||
|
||||
#define kasan_set_tag(addr, tag) \
|
||||
(FAR void *)((((uint64_t)(addr)) & ~((uint64_t)0xff << KASAN_TAG_SHIFT)) | \
|
||||
(((uint64_t)(tag)) << KASAN_TAG_SHIFT))
|
||||
|
||||
#define kasan_random_tag() (rand() % ((1 << (64 - KASAN_TAG_SHIFT)) - 1))
|
||||
|
||||
#define KASAN_SHADOW_SCALE (sizeof(uintptr_t))
|
||||
|
||||
#define KASAN_SHADOW_SIZE(size) \
|
||||
((size) + KASAN_SHADOW_SCALE - 1) / KASAN_SHADOW_SCALE
|
||||
#define KASAN_REGION_SIZE(size) \
|
||||
(sizeof(struct kasan_region_s) + KASAN_SHADOW_SIZE(size))
|
||||
|
||||
#define KASAN_INIT_VALUE 0xdeadcafe
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
struct kasan_region_s
|
||||
{
|
||||
FAR struct kasan_region_s *next;
|
||||
uintptr_t begin;
|
||||
uintptr_t end;
|
||||
uint8_t shadow[1];
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static spinlock_t g_lock;
|
||||
static FAR struct kasan_region_s *g_region;
|
||||
static uint32_t g_region_init;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static FAR uint8_t *kasan_mem_to_shadow(FAR const void *ptr, size_t size)
|
||||
{
|
||||
FAR struct kasan_region_s *region;
|
||||
uintptr_t addr;
|
||||
|
||||
addr = (uintptr_t)kasan_reset_tag(ptr);
|
||||
if (size == 0 || g_region_init != KASAN_INIT_VALUE)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (region = g_region; region != NULL; region = region->next)
|
||||
{
|
||||
if (addr >= region->begin && addr < region->end)
|
||||
{
|
||||
DEBUGASSERT(addr + size <= region->end);
|
||||
addr -= region->begin;
|
||||
return ®ion->shadow[addr / KASAN_SHADOW_SCALE];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void kasan_set_poison(FAR const void *addr,
|
||||
size_t size, uint8_t value)
|
||||
{
|
||||
irqstate_t flags;
|
||||
FAR uint8_t *p;
|
||||
|
||||
addr = kasan_reset_tag(addr);
|
||||
p = kasan_mem_to_shadow(addr, size);
|
||||
if (p == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
size = KASAN_SHADOW_SIZE(size);
|
||||
flags = spin_lock_irqsave(&g_lock);
|
||||
|
||||
while (size--)
|
||||
{
|
||||
p[size] = value;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&g_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
FAR void *kasan_reset_tag(FAR const void *addr)
|
||||
{
|
||||
return (FAR void *)
|
||||
(((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);
|
||||
}
|
||||
|
||||
FAR void *kasan_unpoison(FAR const void *addr, size_t size)
|
||||
{
|
||||
uint8_t tag = kasan_random_tag();
|
||||
|
||||
kasan_set_poison(addr, size, tag);
|
||||
return kasan_set_tag(addr, tag);
|
||||
}
|
||||
|
||||
void kasan_register(FAR void *addr, FAR size_t *size)
|
||||
{
|
||||
FAR struct kasan_region_s *region;
|
||||
irqstate_t flags;
|
||||
|
||||
region = (FAR struct kasan_region_s *)
|
||||
((FAR char *)addr + *size - KASAN_REGION_SIZE(*size));
|
||||
|
||||
region->begin = (uintptr_t)addr;
|
||||
region->end = region->begin + *size;
|
||||
|
||||
flags = spin_lock_irqsave(&g_lock);
|
||||
region->next = g_region;
|
||||
g_region = region;
|
||||
spin_unlock_irqrestore(&g_lock, flags);
|
||||
|
||||
g_region_init = KASAN_INIT_VALUE;
|
||||
kasan_poison(addr, *size);
|
||||
*size -= KASAN_REGION_SIZE(*size);
|
||||
}
|
||||
|
||||
void kasan_init_early(void)
|
||||
{
|
||||
g_region_init = 0;
|
||||
}
|
@ -406,7 +406,7 @@ retry:
|
||||
|
||||
pool->nalloc++;
|
||||
spin_unlock_irqrestore(&pool->lock, flags);
|
||||
kasan_unpoison(blk, pool->blocksize);
|
||||
blk = kasan_unpoison(blk, pool->blocksize);
|
||||
#ifdef CONFIG_MM_FILL_ALLOCATIONS
|
||||
memset(blk, MM_ALLOC_MAGIC, pool->blocksize);
|
||||
#endif
|
||||
@ -648,7 +648,7 @@ int mempool_deinit(FAR struct mempool_s *pool)
|
||||
{
|
||||
blk = (FAR sq_entry_t *)((FAR char *)blk - count * blocksize);
|
||||
|
||||
kasan_unpoison(blk, count * blocksize + sizeof(sq_entry_t));
|
||||
blk = kasan_unpoison(blk, count * blocksize + sizeof(sq_entry_t));
|
||||
pool->free(pool, blk);
|
||||
if (pool->expandsize >= blocksize + sizeof(sq_entry_t))
|
||||
{
|
||||
@ -658,8 +658,8 @@ int mempool_deinit(FAR struct mempool_s *pool)
|
||||
|
||||
if (pool->ibase)
|
||||
{
|
||||
kasan_unpoison(pool->ibase,
|
||||
pool->interruptsize / blocksize * blocksize);
|
||||
pool->ibase = kasan_unpoison(pool->ibase,
|
||||
pool->interruptsize / blocksize * blocksize);
|
||||
pool->free(pool, pool->ibase);
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/mm/mm.h>
|
||||
#include <nuttx/mm/kasan.h>
|
||||
|
||||
#include "mm_heap/mm.h"
|
||||
|
||||
@ -56,6 +57,7 @@
|
||||
|
||||
bool mm_heapmember(FAR struct mm_heap_s *heap, FAR void *mem)
|
||||
{
|
||||
mem = kasan_reset_tag(mem);
|
||||
#if CONFIG_MM_REGIONS > 1
|
||||
int i;
|
||||
|
||||
|
@ -324,7 +324,7 @@ FAR void *mm_malloc(FAR struct mm_heap_s *heap, size_t size)
|
||||
if (ret)
|
||||
{
|
||||
MM_ADD_BACKTRACE(heap, node);
|
||||
kasan_unpoison(ret, mm_malloc_size(heap, ret));
|
||||
ret = kasan_unpoison(ret, mm_malloc_size(heap, ret));
|
||||
#ifdef CONFIG_MM_FILL_ALLOCATIONS
|
||||
memset(ret, MM_ALLOC_MAGIC, alignsize - MM_ALLOCNODE_OVERHEAD);
|
||||
#endif
|
||||
|
@ -277,8 +277,10 @@ FAR void *mm_memalign(FAR struct mm_heap_s *heap, size_t alignment,
|
||||
|
||||
MM_ADD_BACKTRACE(heap, node);
|
||||
|
||||
kasan_unpoison((FAR void *)alignedchunk,
|
||||
mm_malloc_size(heap, (FAR void *)alignedchunk));
|
||||
alignedchunk = (uintptr_t)kasan_unpoison
|
||||
((FAR const void *)alignedchunk,
|
||||
mm_malloc_size(heap,
|
||||
(FAR void *)alignedchunk));
|
||||
|
||||
DEBUGASSERT(alignedchunk % alignment == 0);
|
||||
return (FAR void *)alignedchunk;
|
||||
|
@ -385,8 +385,8 @@ FAR void *mm_realloc(FAR struct mm_heap_s *heap, FAR void *oldmem,
|
||||
mm_unlock(heap);
|
||||
MM_ADD_BACKTRACE(heap, (FAR char *)newmem - MM_SIZEOF_ALLOCNODE);
|
||||
|
||||
kasan_unpoison(newmem, mm_malloc_size(heap, newmem));
|
||||
if (newmem != oldmem)
|
||||
newmem = kasan_unpoison(newmem, mm_malloc_size(heap, newmem));
|
||||
if (kasan_reset_tag(newmem) != kasan_reset_tag(oldmem))
|
||||
{
|
||||
/* Now we have to move the user contents 'down' in memory. memcpy
|
||||
* should be safe for this.
|
||||
|
@ -1183,7 +1183,7 @@ FAR void *mm_malloc(FAR struct mm_heap_s *heap, size_t size)
|
||||
|
||||
memdump_backtrace(heap, buf);
|
||||
#endif
|
||||
kasan_unpoison(ret, mm_malloc_size(heap, ret));
|
||||
ret = kasan_unpoison(ret, mm_malloc_size(heap, ret));
|
||||
|
||||
#ifdef CONFIG_MM_FILL_ALLOCATIONS
|
||||
memset(ret, 0xaa, nodesize);
|
||||
@ -1260,7 +1260,7 @@ FAR void *mm_memalign(FAR struct mm_heap_s *heap, size_t alignment,
|
||||
|
||||
memdump_backtrace(heap, buf);
|
||||
#endif
|
||||
kasan_unpoison(ret, mm_malloc_size(heap, ret));
|
||||
ret = kasan_unpoison(ret, mm_malloc_size(heap, ret));
|
||||
}
|
||||
|
||||
#if CONFIG_MM_FREE_DELAYCOUNT_MAX > 0
|
||||
|
Loading…
Reference in New Issue
Block a user