mm/kasan: add kasan watch point implementation

Signed-off-by: yinshengkai <yinshengkai@xiaomi.com>
This commit is contained in:
yinshengkai 2024-08-20 10:41:56 +08:00 committed by Xiang Xiao
parent e154c6d071
commit 87dc91b588
3 changed files with 159 additions and 0 deletions

View File

@ -30,6 +30,8 @@
#include <stdbool.h>
#include <stddef.h>
#include <nuttx/arch.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
@ -193,6 +195,28 @@ void kasan_start(void);
void kasan_stop(void);
/****************************************************************************
* Name: kasan_debugpoint
*
* Description:
* Monitor the memory range for invalid access check
*
* Input Parameters:
* type - DEBUGPOINT_NONE : remove
* DEBUGPOINT_WATCHPOINT_RO: read
* DEBUGPOINT_WATCHPOINT_WO: write
* DEBUGPOINT_WATCHPOINT_RW: read/write
* addr - range start address
* size - range size
*
* Returned Value:
* If the setting is successful, it returns 0, otherwise it
* returns an error code.
*
****************************************************************************/
int kasan_debugpoint(int type, FAR void *addr, size_t size);
#undef EXTERN
#ifdef __cplusplus
}

View File

@ -264,6 +264,11 @@ choice
prompt "KAsan Mode"
default MM_KASAN_GENERIC
config MM_KASAN_NONE
bool "KAsan disable"
---help---
Disable KASan check
config MM_KASAN_GENERIC
bool "KAsan generic mode"
---help---
@ -288,6 +293,12 @@ config MM_KASAN_ALL
to check. Enabling this option will get image size increased
and performance decreased significantly.
config MM_KASAN_WATCHPOINT
int "Kasan watchpoint maximum number"
default 0
---help---
The maximum number of watchpoints that can be set by KASan.
config MM_KASAN_DISABLE_NULL_POINTER_CHECK
bool "Disable null pointer access check"
default n

View File

@ -83,12 +83,33 @@
# define MM_KASAN_DISABLE_WRITE_PANIC 0
#endif
#ifdef CONFIG_MM_KASAN_WATCHPOINT
# define MM_KASAN_WATCHPOINT CONFIG_MM_KASAN_WATCHPOINT
#else
# define MM_KASAN_WATCHPOINT 0
#endif
#define KASAN_INIT_VALUE 0xdeadcafe
/****************************************************************************
* Private Types
****************************************************************************/
struct kasan_watchpoint_s
{
FAR void *addr;
size_t size;
int type;
};
/****************************************************************************
* Private Data
****************************************************************************/
#if MM_KASAN_WATCHPOINT > 0
static struct kasan_watchpoint_s g_watchpoint[MM_KASAN_WATCHPOINT];
#endif
static uint32_t g_region_init;
/****************************************************************************
@ -164,6 +185,37 @@ static void kasan_report(FAR const void *addr, size_t size,
leave_critical_section(flags);
}
#if MM_KASAN_WATCHPOINT > 0
static void kasan_check_watchpoint(FAR const void *addr, size_t size,
bool is_write,
FAR void *return_address)
{
int i;
for (i = 0; i < MM_KASAN_WATCHPOINT; i++)
{
FAR struct kasan_watchpoint_s *watchpoint = &g_watchpoint[i];
if (watchpoint->type == DEBUGPOINT_NONE)
{
break;
}
if (addr + size <= watchpoint->addr ||
addr > watchpoint->addr + watchpoint->size)
{
continue;
}
if ((is_write && (watchpoint->type & DEBUGPOINT_WATCHPOINT_WO)) ||
(!is_write && (watchpoint->type & DEBUGPOINT_WATCHPOINT_RO)))
{
kasan_report(addr, size, is_write, return_address);
}
}
}
#endif
static inline void kasan_check_report(FAR const void *addr, size_t size,
bool is_write,
FAR void *return_address)
@ -180,10 +232,16 @@ static inline void kasan_check_report(FAR const void *addr, size_t size,
}
#endif
#ifndef CONFIG_MM_KASAN_NONE
if (kasan_is_poisoned(addr, size))
{
kasan_report(addr, size, is_write, return_address);
}
#endif
#if MM_KASAN_WATCHPOINT > 0
kasan_check_watchpoint(addr, size, is_write, return_address);
#endif
}
/****************************************************************************
@ -200,6 +258,72 @@ void kasan_stop(void)
g_region_init = 0;
}
/****************************************************************************
* Name: kasan_debugpoint
*
* Description:
* Monitor the memory range for invalid access check
*
* Input Parameters:
* type - DEBUGPOINT_NONE : remove
* DEBUGPOINT_WATCHPOINT_RO: read
* DEBUGPOINT_WATCHPOINT_WO: write
* DEBUGPOINT_WATCHPOINT_RW: read/write
* addr - range start address
* size - range size
*
* Returned Value:
* If the setting is successful, it returns 0, otherwise it
* returns an error code.
*
****************************************************************************/
#if MM_KASAN_WATCHPOINT > 0
int kasan_debugpoint(int type, FAR void *addr, size_t size)
{
FAR struct kasan_watchpoint_s *watchpoint;
int i;
int j;
if (addr == NULL || size == 0)
{
return -EINVAL;
}
for (i = 0; i < MM_KASAN_WATCHPOINT; i++)
{
watchpoint = &g_watchpoint[i];
if (watchpoint->type == DEBUGPOINT_NONE || watchpoint->addr == addr)
{
if (type != DEBUGPOINT_NONE)
{
watchpoint->addr = addr;
watchpoint->size = size;
watchpoint->type = type;
return 0;
}
for (j = MM_KASAN_WATCHPOINT - 1; j > i; j--)
{
if (g_watchpoint[j].type != DEBUGPOINT_NONE)
{
watchpoint->addr = g_watchpoint[j].addr;
watchpoint->size = g_watchpoint[j].size;
watchpoint->type = g_watchpoint[j].type;
watchpoint = &g_watchpoint[j];
break;
}
}
watchpoint->type = DEBUGPOINT_NONE;
return 0;
}
}
return -ENOMEM;
}
#endif
void __asan_before_dynamic_init(FAR const void *module_name)
{
/* Shut up compiler complaints */