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---
|
||||
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"
|
||||
|
@ -29,6 +29,7 @@ include mm_gran/Make.defs
|
||||
include shm/Make.defs
|
||||
include iob/Make.defs
|
||||
include circbuf/Make.defs
|
||||
include kasan/Make.defs
|
||||
|
||||
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 "mm_heap/mm.h"
|
||||
#include "kasan/kasan.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
@ -83,8 +84,12 @@ void mm_free(FAR struct mm_heap_s *heap, FAR void *mem)
|
||||
return;
|
||||
}
|
||||
|
||||
kasan_poison(mem, mm_malloc_size(mem));
|
||||
|
||||
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,
|
||||
* which means we are in situations during context switching(See
|
||||
* mm_takesemaphore() & getpid()). Then add to the delay list.
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <nuttx/mm/mm.h>
|
||||
|
||||
#include "mm_heap/mm.h"
|
||||
#include "kasan/kasan.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
@ -86,6 +87,10 @@ void mm_addregion(FAR struct mm_heap_s *heap, FAR void *heapstart,
|
||||
DEBUGASSERT(heapsize <= MMSIZE_MAX + 1);
|
||||
#endif
|
||||
|
||||
/* Register to KASan for access check */
|
||||
|
||||
kasan_register(heapstart, &heapsize);
|
||||
|
||||
DEBUGVERIFY(mm_takesemaphore(heap));
|
||||
|
||||
/* Adjust the provided heap start and size so that they are both aligned
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <nuttx/mm/mm.h>
|
||||
|
||||
#include "mm_heap/mm.h"
|
||||
#include "kasan/kasan.h"
|
||||
|
||||
/****************************************************************************
|
||||
* 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));
|
||||
mm_givesemaphore(heap);
|
||||
|
||||
#ifdef CONFIG_MM_FILL_ALLOCATIONS
|
||||
if (ret)
|
||||
{
|
||||
memset(ret, 0xaa, alignsize - SIZEOF_MM_ALLOCNODE);
|
||||
}
|
||||
kasan_unpoison(ret, mm_malloc_size(ret));
|
||||
#ifdef CONFIG_MM_FILL_ALLOCATIONS
|
||||
memset(ret, 0xaa, alignsize - SIZEOF_MM_ALLOCNODE);
|
||||
#endif
|
||||
|
||||
/* If CONFIG_DEBUG_MM is defined, then output the result of the allocation
|
||||
* to the SYSLOG.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_DEBUG_MM
|
||||
if (!ret)
|
||||
{
|
||||
mwarn("WARNING: Allocation failed, size %zu\n", alignsize);
|
||||
minfo("Allocated %p, size %zu\n", ret, alignsize);
|
||||
#endif
|
||||
}
|
||||
#ifdef CONFIG_DEBUG_MM
|
||||
else
|
||||
{
|
||||
minfo("Allocated %p, size %zu\n", ret, alignsize);
|
||||
mwarn("WARNING: Allocation failed, size %zu\n", alignsize);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <nuttx/mm/mm.h>
|
||||
|
||||
#include "mm_heap/mm.h"
|
||||
#include "kasan/kasan.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
@ -111,6 +112,8 @@ FAR void *mm_memalign(FAR struct mm_heap_s *heap, size_t alignment,
|
||||
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
|
||||
* nodelist.
|
||||
*/
|
||||
@ -219,5 +222,9 @@ FAR void *mm_memalign(FAR struct mm_heap_s *heap, size_t alignment,
|
||||
}
|
||||
|
||||
mm_givesemaphore(heap);
|
||||
|
||||
kasan_unpoison((FAR void *)alignedchunk,
|
||||
mm_malloc_size((FAR void *)alignedchunk));
|
||||
|
||||
return (FAR void *)alignedchunk;
|
||||
}
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <nuttx/mm/mm.h>
|
||||
|
||||
#include "mm_heap/mm.h"
|
||||
#include "kasan/kasan.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
@ -123,6 +124,8 @@ FAR void *mm_realloc(FAR struct mm_heap_s *heap, FAR void *oldmem,
|
||||
if (newsize < oldsize)
|
||||
{
|
||||
mm_shrinkchunk(heap, oldnode, newsize);
|
||||
kasan_poison((FAR char *)oldnode + oldnode->size,
|
||||
oldsize - oldnode->size);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
memcpy(newmem, oldmem, oldsize - SIZEOF_MM_ALLOCNODE);
|
||||
|
||||
/* 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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -102,6 +102,7 @@ void umm_initialize(FAR void *heap_start, size_t heap_size)
|
||||
void umm_try_initialize(void)
|
||||
{
|
||||
uintptr_t allocbase;
|
||||
size_t npages = 1;
|
||||
|
||||
/* Return if the user heap is already initialized. */
|
||||
|
||||
@ -110,16 +111,22 @@ void umm_try_initialize(void)
|
||||
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
|
||||
* space and return the start address of that block.
|
||||
*/
|
||||
|
||||
allocbase = pgalloc(0, 1);
|
||||
allocbase = pgalloc(0, npages);
|
||||
DEBUGASSERT(allocbase != 0);
|
||||
|
||||
/* 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
|
||||
|
@ -276,6 +276,15 @@ static const char *g_white_list[] =
|
||||
"SETATTR3resok",
|
||||
"FS3args",
|
||||
|
||||
/* Ref:
|
||||
* mm/kasan/kasan.c
|
||||
*/
|
||||
|
||||
"__asan_loadN",
|
||||
"__asan_storeN",
|
||||
"__asan_loadN_noabort",
|
||||
"__asan_storeN_noabort",
|
||||
|
||||
NULL
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user