mm: Support the kernel address sanitizer
Signed-off-by: chenwei23 <chenwei23@xiaomi.com>
This commit is contained in:
parent
5cb6b042aa
commit
39cdd99d77
@ -178,4 +178,12 @@ config MM_CIRCBUF
|
|||||||
---help---
|
---help---
|
||||||
Build in support for the circular buffer management.
|
Build in support for the circular buffer management.
|
||||||
|
|
||||||
|
config MM_KASAN
|
||||||
|
bool "Kernel Address Sanitizer"
|
||||||
|
default n
|
||||||
|
---help---
|
||||||
|
KASan is a fast compiler-based tool for detecting memory
|
||||||
|
bugs in native code. After turn on this option, Please
|
||||||
|
add -fsanitize=kernel-address to CFLAGS/CXXFLAGS too.
|
||||||
|
|
||||||
source "mm/iob/Kconfig"
|
source "mm/iob/Kconfig"
|
||||||
|
@ -29,6 +29,7 @@ include mm_gran/Make.defs
|
|||||||
include shm/Make.defs
|
include shm/Make.defs
|
||||||
include iob/Make.defs
|
include iob/Make.defs
|
||||||
include circbuf/Make.defs
|
include circbuf/Make.defs
|
||||||
|
include kasan/Make.defs
|
||||||
|
|
||||||
BINDIR ?= bin
|
BINDIR ?= bin
|
||||||
|
|
||||||
|
34
mm/kasan/Make.defs
Normal file
34
mm/kasan/Make.defs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
############################################################################
|
||||||
|
# mm/kasan/Make.defs
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
############################################################################
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_MM_KASAN),y)
|
||||||
|
|
||||||
|
CSRCS += kasan.c
|
||||||
|
|
||||||
|
# Disable kernel-address in mm subsystem
|
||||||
|
|
||||||
|
CFLAGS += -fno-sanitize=kernel-address
|
||||||
|
|
||||||
|
# Add the core heap directory to the build
|
||||||
|
|
||||||
|
DEPPATH += --dep-path kasan
|
||||||
|
VPATH += :kasan
|
||||||
|
|
||||||
|
endif
|
409
mm/kasan/kasan.c
Normal file
409
mm/kasan/kasan.c
Normal file
@ -0,0 +1,409 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* mm/kasan/kasan.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/semaphore.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <debug.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "kasan.h"
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Pre-processor Definitions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#define KASAN_BYTES_PER_WORD (sizeof(uintptr_t))
|
||||||
|
#define KASAN_BITS_PER_WORD (KASAN_BYTES_PER_WORD * 8)
|
||||||
|
|
||||||
|
#define KASAN_FIRST_WORD_MASK(start) \
|
||||||
|
(UINTPTR_MAX << ((start) & (KASAN_BITS_PER_WORD - 1)))
|
||||||
|
#define KASAN_LAST_WORD_MASK(end) \
|
||||||
|
(UINTPTR_MAX >> (-(end) & (KASAN_BITS_PER_WORD - 1)))
|
||||||
|
|
||||||
|
#define KASAN_SHADOW_SCALE (sizeof(uintptr_t))
|
||||||
|
|
||||||
|
#define KASAN_SHADOW_SIZE(size) \
|
||||||
|
(KASAN_BYTES_PER_WORD * ((size) / KASAN_SHADOW_SCALE / KASAN_BITS_PER_WORD))
|
||||||
|
#define KASAN_REGION_SIZE(size) \
|
||||||
|
(sizeof(struct kasan_region_s) + KASAN_SHADOW_SIZE(size))
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Types
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
struct kasan_region_s
|
||||||
|
{
|
||||||
|
FAR struct kasan_region_s *next;
|
||||||
|
uintptr_t begin;
|
||||||
|
uintptr_t end;
|
||||||
|
uintptr_t shadow[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Data
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static sem_t g_lock = SEM_INITIALIZER(1);
|
||||||
|
static FAR struct kasan_region_s *g_region;
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static FAR uintptr_t *kasan_mem_to_shadow(uintptr_t addr, size_t size,
|
||||||
|
unsigned int *bit)
|
||||||
|
{
|
||||||
|
FAR struct kasan_region_s *region;
|
||||||
|
|
||||||
|
for (region = g_region; region != NULL; region = region->next)
|
||||||
|
{
|
||||||
|
if (addr >= region->begin && addr < region->end)
|
||||||
|
{
|
||||||
|
DEBUGASSERT(addr + size <= region->end);
|
||||||
|
addr -= region->begin;
|
||||||
|
addr /= KASAN_SHADOW_SCALE;
|
||||||
|
*bit = addr % KASAN_BITS_PER_WORD;
|
||||||
|
return ®ion->shadow[addr / KASAN_BITS_PER_WORD];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void kasan_report(uintptr_t addr, size_t size, bool is_write)
|
||||||
|
{
|
||||||
|
static int recursion;
|
||||||
|
|
||||||
|
if (++recursion == 1)
|
||||||
|
{
|
||||||
|
_alert("kasan detected a %s access error, address at %0#"PRIxPTR
|
||||||
|
", size is %zu\n", is_write ? "write" : "read", addr, size);
|
||||||
|
PANIC();
|
||||||
|
}
|
||||||
|
|
||||||
|
--recursion;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool kasan_is_poisoned(uintptr_t addr, size_t size)
|
||||||
|
{
|
||||||
|
FAR uintptr_t *p;
|
||||||
|
unsigned int bit;
|
||||||
|
|
||||||
|
p = kasan_mem_to_shadow(addr + size - 1, 1, &bit);
|
||||||
|
return p && ((*p >> bit) & 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void kasan_set_poison(uintptr_t addr, size_t size, bool poisoned)
|
||||||
|
{
|
||||||
|
FAR uintptr_t *p;
|
||||||
|
unsigned int bit;
|
||||||
|
unsigned int nbit;
|
||||||
|
uintptr_t mask;
|
||||||
|
|
||||||
|
p = kasan_mem_to_shadow(addr, size, &bit);
|
||||||
|
DEBUGASSERT(p != NULL);
|
||||||
|
|
||||||
|
nbit = KASAN_BITS_PER_WORD - bit % KASAN_BITS_PER_WORD;
|
||||||
|
mask = KASAN_FIRST_WORD_MASK(bit);
|
||||||
|
|
||||||
|
size /= KASAN_SHADOW_SCALE;
|
||||||
|
while (size >= nbit)
|
||||||
|
{
|
||||||
|
if (poisoned)
|
||||||
|
{
|
||||||
|
*p++ |= mask;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*p++ &= ~mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
bit += nbit;
|
||||||
|
size -= nbit;
|
||||||
|
|
||||||
|
nbit = KASAN_BITS_PER_WORD;
|
||||||
|
mask = UINTPTR_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size)
|
||||||
|
{
|
||||||
|
mask &= KASAN_LAST_WORD_MASK(bit + size);
|
||||||
|
if (poisoned)
|
||||||
|
{
|
||||||
|
*p |= mask;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*p &= ~mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/* Exported functions called from other mm module */
|
||||||
|
|
||||||
|
void kasan_poison(FAR const void *addr, size_t size)
|
||||||
|
{
|
||||||
|
kasan_set_poison((uintptr_t)addr, size, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void kasan_unpoison(FAR const void *addr, size_t size)
|
||||||
|
{
|
||||||
|
kasan_set_poison((uintptr_t)addr, size, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void kasan_register(FAR void *addr, FAR size_t *size)
|
||||||
|
{
|
||||||
|
FAR struct kasan_region_s *region;
|
||||||
|
|
||||||
|
region = (FAR struct kasan_region_s *)
|
||||||
|
((FAR char *)addr + *size - KASAN_REGION_SIZE(*size));
|
||||||
|
|
||||||
|
region->begin = (uintptr_t)addr;
|
||||||
|
region->end = region->begin + *size;
|
||||||
|
|
||||||
|
_SEM_WAIT(&g_lock);
|
||||||
|
region->next = g_region;
|
||||||
|
g_region = region;
|
||||||
|
_SEM_POST(&g_lock);
|
||||||
|
|
||||||
|
kasan_poison(addr, *size);
|
||||||
|
*size -= KASAN_REGION_SIZE(*size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Exported functions called from the compiler generated code */
|
||||||
|
|
||||||
|
void __sanitizer_annotate_contiguous_container(FAR const void *beg,
|
||||||
|
FAR const void *end,
|
||||||
|
FAR const void *old_mid,
|
||||||
|
FAR const void *new_mid)
|
||||||
|
{
|
||||||
|
/* Shut up compiler complaints */
|
||||||
|
}
|
||||||
|
|
||||||
|
void __asan_before_dynamic_init(FAR const char *module_name)
|
||||||
|
{
|
||||||
|
/* Shut up compiler complaints */
|
||||||
|
}
|
||||||
|
|
||||||
|
void __asan_after_dynamic_init(void)
|
||||||
|
{
|
||||||
|
/* Shut up compiler complaints */
|
||||||
|
}
|
||||||
|
|
||||||
|
void __asan_handle_no_return(void)
|
||||||
|
{
|
||||||
|
/* Shut up compiler complaints */
|
||||||
|
}
|
||||||
|
|
||||||
|
void __asan_report_load_n_noabort(uintptr_t addr, size_t size)
|
||||||
|
{
|
||||||
|
kasan_report(addr, size, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __asan_report_store_n_noabort(uintptr_t addr, size_t size)
|
||||||
|
{
|
||||||
|
kasan_report(addr, size, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __asan_report_load16_noabort(uintptr_t addr)
|
||||||
|
{
|
||||||
|
__asan_report_load_n_noabort(addr, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __asan_report_store16_noabort(uintptr_t addr)
|
||||||
|
{
|
||||||
|
__asan_report_store_n_noabort(addr, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __asan_report_load8_noabort(uintptr_t addr)
|
||||||
|
{
|
||||||
|
__asan_report_load_n_noabort(addr, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __asan_report_store8_noabort(uintptr_t addr)
|
||||||
|
{
|
||||||
|
__asan_report_store_n_noabort(addr, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __asan_report_load4_noabort(uintptr_t addr)
|
||||||
|
{
|
||||||
|
__asan_report_load_n_noabort(addr, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __asan_report_store4_noabort(uintptr_t addr)
|
||||||
|
{
|
||||||
|
__asan_report_store_n_noabort(addr, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __asan_report_load2_noabort(uintptr_t addr)
|
||||||
|
{
|
||||||
|
__asan_report_load_n_noabort(addr, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __asan_report_store2_noabort(uintptr_t addr)
|
||||||
|
{
|
||||||
|
__asan_report_store_n_noabort(addr, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __asan_report_load1_noabort(uintptr_t addr)
|
||||||
|
{
|
||||||
|
__asan_report_load_n_noabort(addr, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __asan_report_store1_noabort(uintptr_t addr)
|
||||||
|
{
|
||||||
|
__asan_report_store_n_noabort(addr, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __asan_loadN_noabort(uintptr_t addr, size_t size)
|
||||||
|
{
|
||||||
|
if (kasan_is_poisoned(addr, size))
|
||||||
|
{
|
||||||
|
kasan_report(addr, size, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void __asan_storeN_noabort(uintptr_t addr, size_t size)
|
||||||
|
{
|
||||||
|
if (kasan_is_poisoned(addr, size))
|
||||||
|
{
|
||||||
|
kasan_report(addr, size, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void __asan_load16_noabort(uintptr_t addr)
|
||||||
|
{
|
||||||
|
__asan_loadN_noabort(addr, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __asan_store16_noabort(uintptr_t addr)
|
||||||
|
{
|
||||||
|
__asan_storeN_noabort(addr, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __asan_load8_noabort(uintptr_t addr)
|
||||||
|
{
|
||||||
|
__asan_loadN_noabort(addr, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __asan_store8_noabort(uintptr_t addr)
|
||||||
|
{
|
||||||
|
__asan_storeN_noabort(addr, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __asan_load4_noabort(uintptr_t addr)
|
||||||
|
{
|
||||||
|
__asan_loadN_noabort(addr, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __asan_store4_noabort(uintptr_t addr)
|
||||||
|
{
|
||||||
|
__asan_storeN_noabort(addr, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __asan_load2_noabort(uintptr_t addr)
|
||||||
|
{
|
||||||
|
__asan_loadN_noabort(addr, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __asan_store2_noabort(uintptr_t addr)
|
||||||
|
{
|
||||||
|
__asan_storeN_noabort(addr, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __asan_load1_noabort(uintptr_t addr)
|
||||||
|
{
|
||||||
|
__asan_loadN_noabort(addr, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __asan_store1_noabort(uintptr_t addr)
|
||||||
|
{
|
||||||
|
__asan_storeN_noabort(addr, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __asan_loadN(uintptr_t addr, size_t size)
|
||||||
|
{
|
||||||
|
__asan_loadN_noabort(addr, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __asan_storeN(uintptr_t addr, size_t size)
|
||||||
|
{
|
||||||
|
__asan_storeN_noabort(addr, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __asan_load16(uintptr_t addr)
|
||||||
|
{
|
||||||
|
__asan_load16_noabort(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __asan_store16(uintptr_t addr)
|
||||||
|
{
|
||||||
|
__asan_store16_noabort(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __asan_load8(uintptr_t addr)
|
||||||
|
{
|
||||||
|
__asan_load8_noabort(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __asan_store8(uintptr_t addr)
|
||||||
|
{
|
||||||
|
__asan_store8_noabort(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __asan_load4(uintptr_t addr)
|
||||||
|
{
|
||||||
|
__asan_load4_noabort(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __asan_store4(uintptr_t addr)
|
||||||
|
{
|
||||||
|
__asan_store4_noabort(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __asan_load2(uintptr_t addr)
|
||||||
|
{
|
||||||
|
__asan_load2_noabort(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __asan_store2(uintptr_t addr)
|
||||||
|
{
|
||||||
|
__asan_store2_noabort(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __asan_load1(uintptr_t addr)
|
||||||
|
{
|
||||||
|
__asan_load1_noabort(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __asan_store1(uintptr_t addr)
|
||||||
|
{
|
||||||
|
__asan_store1_noabort(addr);
|
||||||
|
}
|
115
mm/kasan/kasan.h
Normal file
115
mm/kasan/kasan.h
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* mm/kasan/kasan.h
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef __MM_KASAN_KASAN_H
|
||||||
|
#define __MM_KASAN_KASAN_H
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Included Files
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Pre-processor Definitions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef CONFIG_MM_KASAN
|
||||||
|
# define kasan_poison(addr, size)
|
||||||
|
# define kasan_unpoison(addr, size)
|
||||||
|
# define kasan_register(addr, size)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Function Prototypes
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#define EXTERN extern "C"
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#else
|
||||||
|
#define EXTERN extern
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_MM_KASAN
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: kasan_poison
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Mark the memory range as inaccessible
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* addr - range start address
|
||||||
|
* size - range size
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void kasan_poison(FAR const void *addr, size_t size);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: kasan_unpoison
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Mark the memory range as accessible
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* addr - range start address
|
||||||
|
* size - range size
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void kasan_unpoison(FAR const void *addr, size_t size);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: kasan_register
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Monitor the memory range for invalid access check
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* addr - range start address
|
||||||
|
* size - range size
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Note:
|
||||||
|
* The size is shrinked for the shadow region
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void kasan_register(FAR void *addr, FAR size_t *size);
|
||||||
|
|
||||||
|
#endif /* CONFIG_MM_KASAN */
|
||||||
|
|
||||||
|
#undef EXTERN
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __MM_KASAN_KASAN_H */
|
@ -31,6 +31,7 @@
|
|||||||
#include <nuttx/mm/mm.h>
|
#include <nuttx/mm/mm.h>
|
||||||
|
|
||||||
#include "mm_heap/mm.h"
|
#include "mm_heap/mm.h"
|
||||||
|
#include "kasan/kasan.h"
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
@ -83,8 +84,12 @@ void mm_free(FAR struct mm_heap_s *heap, FAR void *mem)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kasan_poison(mem, mm_malloc_size(mem));
|
||||||
|
|
||||||
if (mm_takesemaphore(heap) == false)
|
if (mm_takesemaphore(heap) == false)
|
||||||
{
|
{
|
||||||
|
kasan_unpoison(mem, mm_malloc_size(mem));
|
||||||
|
|
||||||
/* We are in IDLE task & can't get sem, or meet -ESRCH return,
|
/* We are in IDLE task & can't get sem, or meet -ESRCH return,
|
||||||
* which means we are in situations during context switching(See
|
* which means we are in situations during context switching(See
|
||||||
* mm_takesemaphore() & getpid()). Then add to the delay list.
|
* mm_takesemaphore() & getpid()). Then add to the delay list.
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include <nuttx/mm/mm.h>
|
#include <nuttx/mm/mm.h>
|
||||||
|
|
||||||
#include "mm_heap/mm.h"
|
#include "mm_heap/mm.h"
|
||||||
|
#include "kasan/kasan.h"
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
@ -86,6 +87,10 @@ void mm_addregion(FAR struct mm_heap_s *heap, FAR void *heapstart,
|
|||||||
DEBUGASSERT(heapsize <= MMSIZE_MAX + 1);
|
DEBUGASSERT(heapsize <= MMSIZE_MAX + 1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Register to KASan for access check */
|
||||||
|
|
||||||
|
kasan_register(heapstart, &heapsize);
|
||||||
|
|
||||||
DEBUGVERIFY(mm_takesemaphore(heap));
|
DEBUGVERIFY(mm_takesemaphore(heap));
|
||||||
|
|
||||||
/* Adjust the provided heap start and size so that they are both aligned
|
/* Adjust the provided heap start and size so that they are both aligned
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include <nuttx/mm/mm.h>
|
#include <nuttx/mm/mm.h>
|
||||||
|
|
||||||
#include "mm_heap/mm.h"
|
#include "mm_heap/mm.h"
|
||||||
|
#include "kasan/kasan.h"
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
@ -228,25 +229,20 @@ FAR void *mm_malloc(FAR struct mm_heap_s *heap, size_t size)
|
|||||||
DEBUGASSERT(ret == NULL || mm_heapmember(heap, ret));
|
DEBUGASSERT(ret == NULL || mm_heapmember(heap, ret));
|
||||||
mm_givesemaphore(heap);
|
mm_givesemaphore(heap);
|
||||||
|
|
||||||
#ifdef CONFIG_MM_FILL_ALLOCATIONS
|
|
||||||
if (ret)
|
if (ret)
|
||||||
{
|
{
|
||||||
|
kasan_unpoison(ret, mm_malloc_size(ret));
|
||||||
|
#ifdef CONFIG_MM_FILL_ALLOCATIONS
|
||||||
memset(ret, 0xaa, alignsize - SIZEOF_MM_ALLOCNODE);
|
memset(ret, 0xaa, alignsize - SIZEOF_MM_ALLOCNODE);
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* If CONFIG_DEBUG_MM is defined, then output the result of the allocation
|
|
||||||
* to the SYSLOG.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_MM
|
#ifdef CONFIG_DEBUG_MM
|
||||||
if (!ret)
|
minfo("Allocated %p, size %zu\n", ret, alignsize);
|
||||||
{
|
#endif
|
||||||
mwarn("WARNING: Allocation failed, size %zu\n", alignsize);
|
|
||||||
}
|
}
|
||||||
|
#ifdef CONFIG_DEBUG_MM
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
minfo("Allocated %p, size %zu\n", ret, alignsize);
|
mwarn("WARNING: Allocation failed, size %zu\n", alignsize);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include <nuttx/mm/mm.h>
|
#include <nuttx/mm/mm.h>
|
||||||
|
|
||||||
#include "mm_heap/mm.h"
|
#include "mm_heap/mm.h"
|
||||||
|
#include "kasan/kasan.h"
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
@ -111,6 +112,8 @@ FAR void *mm_memalign(FAR struct mm_heap_s *heap, size_t alignment,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kasan_poison((FAR void *)rawchunk, mm_malloc_size((FAR void *)rawchunk));
|
||||||
|
|
||||||
/* We need to hold the MM semaphore while we muck with the chunks and
|
/* We need to hold the MM semaphore while we muck with the chunks and
|
||||||
* nodelist.
|
* nodelist.
|
||||||
*/
|
*/
|
||||||
@ -219,5 +222,9 @@ FAR void *mm_memalign(FAR struct mm_heap_s *heap, size_t alignment,
|
|||||||
}
|
}
|
||||||
|
|
||||||
mm_givesemaphore(heap);
|
mm_givesemaphore(heap);
|
||||||
|
|
||||||
|
kasan_unpoison((FAR void *)alignedchunk,
|
||||||
|
mm_malloc_size((FAR void *)alignedchunk));
|
||||||
|
|
||||||
return (FAR void *)alignedchunk;
|
return (FAR void *)alignedchunk;
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include <nuttx/mm/mm.h>
|
#include <nuttx/mm/mm.h>
|
||||||
|
|
||||||
#include "mm_heap/mm.h"
|
#include "mm_heap/mm.h"
|
||||||
|
#include "kasan/kasan.h"
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
@ -123,6 +124,8 @@ FAR void *mm_realloc(FAR struct mm_heap_s *heap, FAR void *oldmem,
|
|||||||
if (newsize < oldsize)
|
if (newsize < oldsize)
|
||||||
{
|
{
|
||||||
mm_shrinkchunk(heap, oldnode, newsize);
|
mm_shrinkchunk(heap, oldnode, newsize);
|
||||||
|
kasan_poison((FAR char *)oldnode + oldnode->size,
|
||||||
|
oldsize - oldnode->size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Then return the original address */
|
/* Then return the original address */
|
||||||
@ -264,12 +267,7 @@ FAR void *mm_realloc(FAR struct mm_heap_s *heap, FAR void *oldmem,
|
|||||||
(next->preceding & MM_ALLOC_BIT);
|
(next->preceding & MM_ALLOC_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now we have to move the user contents 'down' in memory. memcpy
|
|
||||||
* should be safe for this.
|
|
||||||
*/
|
|
||||||
|
|
||||||
newmem = (FAR void *)((FAR char *)newnode + SIZEOF_MM_ALLOCNODE);
|
newmem = (FAR void *)((FAR char *)newnode + SIZEOF_MM_ALLOCNODE);
|
||||||
memcpy(newmem, oldmem, oldsize - SIZEOF_MM_ALLOCNODE);
|
|
||||||
|
|
||||||
/* Now we want to return newnode */
|
/* Now we want to return newnode */
|
||||||
|
|
||||||
@ -335,6 +333,17 @@ FAR void *mm_realloc(FAR struct mm_heap_s *heap, FAR void *oldmem,
|
|||||||
}
|
}
|
||||||
|
|
||||||
mm_givesemaphore(heap);
|
mm_givesemaphore(heap);
|
||||||
|
|
||||||
|
kasan_unpoison(newmem, mm_malloc_size(newmem));
|
||||||
|
if (newmem != oldmem)
|
||||||
|
{
|
||||||
|
/* Now we have to move the user contents 'down' in memory. memcpy
|
||||||
|
* should be safe for this.
|
||||||
|
*/
|
||||||
|
|
||||||
|
memcpy(newmem, oldmem, oldsize - SIZEOF_MM_ALLOCNODE);
|
||||||
|
}
|
||||||
|
|
||||||
return newmem;
|
return newmem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,6 +102,7 @@ void umm_initialize(FAR void *heap_start, size_t heap_size)
|
|||||||
void umm_try_initialize(void)
|
void umm_try_initialize(void)
|
||||||
{
|
{
|
||||||
uintptr_t allocbase;
|
uintptr_t allocbase;
|
||||||
|
size_t npages = 1;
|
||||||
|
|
||||||
/* Return if the user heap is already initialized. */
|
/* Return if the user heap is already initialized. */
|
||||||
|
|
||||||
@ -110,16 +111,22 @@ void umm_try_initialize(void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate one page. If we provide a zero brkaddr to pgalloc(),
|
#ifdef CONFIG_MM_KASAN
|
||||||
|
/* we have to commit all memory for the shadow region */
|
||||||
|
|
||||||
|
npages = CONFIG_ARCH_HEAP_NPAGES;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* If we provide a zero brkaddr to pgalloc(),
|
||||||
* it will create the first block in the correct virtual address
|
* it will create the first block in the correct virtual address
|
||||||
* space and return the start address of that block.
|
* space and return the start address of that block.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
allocbase = pgalloc(0, 1);
|
allocbase = pgalloc(0, npages);
|
||||||
DEBUGASSERT(allocbase != 0);
|
DEBUGASSERT(allocbase != 0);
|
||||||
|
|
||||||
/* Let umm_initialize do the real work. */
|
/* Let umm_initialize do the real work. */
|
||||||
|
|
||||||
umm_initialize((FAR void *)allocbase, CONFIG_MM_PGSIZE);
|
umm_initialize((FAR void *)allocbase, npages * CONFIG_MM_PGSIZE);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -276,6 +276,15 @@ static const char *g_white_list[] =
|
|||||||
"SETATTR3resok",
|
"SETATTR3resok",
|
||||||
"FS3args",
|
"FS3args",
|
||||||
|
|
||||||
|
/* Ref:
|
||||||
|
* mm/kasan/kasan.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
"__asan_loadN",
|
||||||
|
"__asan_storeN",
|
||||||
|
"__asan_loadN_noabort",
|
||||||
|
"__asan_storeN_noabort",
|
||||||
|
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user