You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by gu...@apache.org on 2021/11/02 16:32:55 UTC

[incubator-nuttx] branch master updated (a16a9f8 -> df877a8)

This is an automated email from the ASF dual-hosted git repository.

gustavonihei pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git.


    from a16a9f8  mpfs: i2c: Add support for adaptive I2C bus frequency
     new 5cb6b04  mm/heap: Simplify the condition check in mm_realloc
     new 39cdd99  mm: Support the kernel address sanitizer
     new df877a8  boards/sim: Add new config for KASan

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../sim/sim/sim/configs/{asan => kasan}/defconfig  |   4 +-
 boards/sim/sim/sim/scripts/Make.defs               |  15 +-
 mm/Kconfig                                         |   8 +
 mm/Makefile                                        |   1 +
 {libs/libc/lzf => mm/kasan}/Make.defs              |  16 +-
 mm/kasan/kasan.c                                   | 409 +++++++++++++++++++++
 .../src/bl602/bl602_glb.h => mm/kasan/kasan.h      |  74 ++--
 mm/mm_heap/mm_free.c                               |   5 +
 mm/mm_heap/mm_initialize.c                         |   5 +
 mm/mm_heap/mm_malloc.c                             |  20 +-
 mm/mm_heap/mm_memalign.c                           |   7 +
 mm/mm_heap/mm_realloc.c                            |  40 +-
 mm/umm_heap/umm_initialize.c                       |  13 +-
 tools/ci/testlist/sim-01.dat                       |   9 +-
 tools/nxstyle.c                                    |   9 +
 15 files changed, 552 insertions(+), 83 deletions(-)
 copy boards/sim/sim/sim/configs/{asan => kasan}/defconfig (93%)
 copy {libs/libc/lzf => mm/kasan}/Make.defs (80%)
 create mode 100644 mm/kasan/kasan.c
 copy arch/risc-v/src/bl602/bl602_glb.h => mm/kasan/kasan.h (69%)

[incubator-nuttx] 02/03: mm: Support the kernel address sanitizer

Posted by gu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

gustavonihei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 39cdd99d77137e1c92859cf8dd7a2675690cc1d6
Author: chenwei23 <ch...@xiaomi.com>
AuthorDate: Sat Oct 9 15:22:28 2021 +0800

    mm: Support the kernel address sanitizer
    
    Signed-off-by: chenwei23 <ch...@xiaomi.com>
---
 mm/Kconfig                   |   8 +
 mm/Makefile                  |   1 +
 mm/kasan/Make.defs           |  34 ++++
 mm/kasan/kasan.c             | 409 +++++++++++++++++++++++++++++++++++++++++++
 mm/kasan/kasan.h             | 115 ++++++++++++
 mm/mm_heap/mm_free.c         |   5 +
 mm/mm_heap/mm_initialize.c   |   5 +
 mm/mm_heap/mm_malloc.c       |  20 +--
 mm/mm_heap/mm_memalign.c     |   7 +
 mm/mm_heap/mm_realloc.c      |  19 +-
 mm/umm_heap/umm_initialize.c |  13 +-
 tools/nxstyle.c              |   9 +
 12 files changed, 625 insertions(+), 20 deletions(-)

diff --git a/mm/Kconfig b/mm/Kconfig
index 8c5e772..8746a20 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -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"
diff --git a/mm/Makefile b/mm/Makefile
index 0398029..323a8ed 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -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
 
diff --git a/mm/kasan/Make.defs b/mm/kasan/Make.defs
new file mode 100644
index 0000000..ab67a9c
--- /dev/null
+++ b/mm/kasan/Make.defs
@@ -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
diff --git a/mm/kasan/kasan.c b/mm/kasan/kasan.c
new file mode 100644
index 0000000..90c324e
--- /dev/null
+++ b/mm/kasan/kasan.c
@@ -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 &region->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);
+}
diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
new file mode 100644
index 0000000..c6fd07c
--- /dev/null
+++ b/mm/kasan/kasan.h
@@ -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 */
diff --git a/mm/mm_heap/mm_free.c b/mm/mm_heap/mm_free.c
index c3545cf..c788649 100644
--- a/mm/mm_heap/mm_free.c
+++ b/mm/mm_heap/mm_free.c
@@ -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.
diff --git a/mm/mm_heap/mm_initialize.c b/mm/mm_heap/mm_initialize.c
index 9156111..4e2a21b 100644
--- a/mm/mm_heap/mm_initialize.c
+++ b/mm/mm_heap/mm_initialize.c
@@ -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
diff --git a/mm/mm_heap/mm_malloc.c b/mm/mm_heap/mm_malloc.c
index 598f553..a1262f5 100644
--- a/mm/mm_heap/mm_malloc.c
+++ b/mm/mm_heap/mm_malloc.c
@@ -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
 
diff --git a/mm/mm_heap/mm_memalign.c b/mm/mm_heap/mm_memalign.c
index 9d1bdd6..1fcd387 100644
--- a/mm/mm_heap/mm_memalign.c
+++ b/mm/mm_heap/mm_memalign.c
@@ -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;
 }
diff --git a/mm/mm_heap/mm_realloc.c b/mm/mm_heap/mm_realloc.c
index 897201c..1842572 100644
--- a/mm/mm_heap/mm_realloc.c
+++ b/mm/mm_heap/mm_realloc.c
@@ -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;
     }
 
diff --git a/mm/umm_heap/umm_initialize.c b/mm/umm_heap/umm_initialize.c
index ca0fcc6..1eb726e 100644
--- a/mm/umm_heap/umm_initialize.c
+++ b/mm/umm_heap/umm_initialize.c
@@ -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
diff --git a/tools/nxstyle.c b/tools/nxstyle.c
index ae0c288..f2b44fb 100644
--- a/tools/nxstyle.c
+++ b/tools/nxstyle.c
@@ -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
 };
 

[incubator-nuttx] 03/03: boards/sim: Add new config for KASan

Posted by gu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

gustavonihei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit df877a8a91ce28e69034f56011c9e2ebe93b6fb2
Author: Xiang Xiao <xi...@xiaomi.com>
AuthorDate: Fri Oct 15 22:45:40 2021 +0800

    boards/sim: Add new config for KASan
    
    Signed-off-by: Xiang Xiao <xi...@xiaomi.com>
---
 boards/sim/sim/sim/configs/kasan/defconfig | 32 ++++++++++++++++++++++++++++++
 boards/sim/sim/sim/scripts/Make.defs       | 15 +++++++++-----
 tools/ci/testlist/sim-01.dat               |  9 ++++++---
 3 files changed, 48 insertions(+), 8 deletions(-)

diff --git a/boards/sim/sim/sim/configs/kasan/defconfig b/boards/sim/sim/sim/configs/kasan/defconfig
new file mode 100644
index 0000000..1a98918
--- /dev/null
+++ b/boards/sim/sim/sim/configs/kasan/defconfig
@@ -0,0 +1,32 @@
+#
+# This file is autogenerated: PLEASE DO NOT EDIT IT.
+#
+# You can use "make menuconfig" to make any modifications to the installed .config file.
+# You can then do "make savedefconfig" to generate a new defconfig file that includes your
+# modifications.
+#
+CONFIG_ARCH="sim"
+CONFIG_ARCH_BOARD="sim"
+CONFIG_ARCH_BOARD_SIM=y
+CONFIG_ARCH_CHIP="sim"
+CONFIG_ARCH_SIM=y
+CONFIG_BOARDCTL_POWEROFF=y
+CONFIG_BUILTIN=y
+CONFIG_DEBUG_FEATURES=y
+CONFIG_DEBUG_SYMBOLS=y
+CONFIG_DEV_LOOP=y
+CONFIG_DEV_ZERO=y
+CONFIG_EXAMPLES_HELLO=y
+CONFIG_FS_BINFS=y
+CONFIG_FS_PROCFS=y
+CONFIG_MM_KASAN=y
+CONFIG_NSH_ARCHINIT=y
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_READLINE=y
+CONFIG_READLINE_TABCOMPLETION=y
+CONFIG_SCHED_HAVE_PARENT=y
+CONFIG_SCHED_ONEXIT=y
+CONFIG_SCHED_WAITPID=y
+CONFIG_SYSTEM_NSH=y
+CONFIG_TESTING_OSTEST=y
+CONFIG_USER_ENTRYPOINT="nsh_main"
diff --git a/boards/sim/sim/sim/scripts/Make.defs b/boards/sim/sim/sim/scripts/Make.defs
index 080eb70..119d6a1 100644
--- a/boards/sim/sim/sim/scripts/Make.defs
+++ b/boards/sim/sim/sim/scripts/Make.defs
@@ -51,10 +51,6 @@ ifeq ($(CONFIG_STACK_CANARIES),y)
   ARCHOPTIMIZATION += -fstack-protector-all
 endif
 
-ifeq ($(CONFIG_SIM_SANITIZE),y)
-  ARCHOPTIMIZATION += -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer
-endif
-
 ifeq ($(CONFIG_ARCH_COVERAGE),y)
   ARCHOPTIMIZATION += -fprofile-arcs -ftest-coverage
 endif
@@ -133,6 +129,14 @@ ifeq ($(CONFIG_LIBCXX),y)
   endif
 endif
 
+ifeq ($(CONFIG_SIM_SANITIZE),y)
+  CFLAGS += -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer
+  CXXFLAGS += -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer
+else ifeq ($(CONFIG_MM_KASAN),y)
+  CFLAGS += -fsanitize=kernel-address
+  CXXFLAGS += -fsanitize=kernel-address
+endif
+
 # Loadable module definitions
 
 CMODULEFLAGS = $(CFLAGS)
@@ -198,7 +202,8 @@ endif
 
 ifeq ($(CONFIG_SIM_SANITIZE),y)
   CCLINKFLAGS += -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer
-  HOSTLDFLAGS += -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer
+else ifeq ($(CONFIG_MM_KASAN),y)
+  CCLINKFLAGS += -fsanitize=kernel-address
 endif
 
 HOSTCFLAGS = $(ARCHWARNINGS) $(ARCHOPTIMIZATION) \
diff --git a/tools/ci/testlist/sim-01.dat b/tools/ci/testlist/sim-01.dat
index 21fc19b..0c1e472 100644
--- a/tools/ci/testlist/sim-01.dat
+++ b/tools/ci/testlist/sim-01.dat
@@ -6,9 +6,8 @@
 -Darwin,sim:cxxtest
 -Darwin,sim:libcxxtest
 
-# Do not build Linux configs
--Darwin,sim:linuxi2c
--Darwin,sim:linuxspi
+# clang doesn't -fsanitize=kernel-address
+-Darwin,sim:kasan
 
 # macOS doesn't support 32bit(CONFIG_SIM_M32=y) anymore
 -Darwin,sim:elf
@@ -16,6 +15,10 @@
 -Darwin,sim:loadable
 -Darwin,sim:module32
 
+# Do not build Linux configs
+-Darwin,sim:linuxi2c
+-Darwin,sim:linuxspi
+
 # macOS doesn't have X11
 -Darwin,sim:lvgl
 -Darwin,sim:nsh2

[incubator-nuttx] 01/03: mm/heap: Simplify the condition check in mm_realloc

Posted by gu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

gustavonihei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 5cb6b042aae0b0ba03a5349085020f3fa13696ae
Author: Xiang Xiao <xi...@xiaomi.com>
AuthorDate: Tue Oct 26 03:27:23 2021 +0800

    mm/heap: Simplify the condition check in mm_realloc
    
    Signed-off-by: Xiang Xiao <xi...@xiaomi.com>
---
 mm/mm_heap/mm_realloc.c | 21 +++++++++------------
 1 file changed, 9 insertions(+), 12 deletions(-)

diff --git a/mm/mm_heap/mm_realloc.c b/mm/mm_heap/mm_realloc.c
index bfaf2e6..897201c 100644
--- a/mm/mm_heap/mm_realloc.c
+++ b/mm/mm_heap/mm_realloc.c
@@ -154,15 +154,15 @@ FAR void *mm_realloc(FAR struct mm_heap_s *heap, FAR void *oldmem,
 
   if (nextsize + prevsize + oldsize >= newsize)
     {
-      size_t needed   = newsize - oldsize;
-      size_t takeprev = 0;
-      size_t takenext = 0;
+      size_t needed = newsize - oldsize;
+      size_t takeprev;
+      size_t takenext;
 
       /* Check if we can extend into the previous chunk and if the
        * previous chunk is smaller than the next chunk.
        */
 
-      if (prevsize > 0 && (nextsize >= prevsize || nextsize < 1))
+      if (nextsize > prevsize)
         {
           /* Can we get everything we need from the previous chunk? */
 
@@ -182,15 +182,13 @@ FAR void *mm_realloc(FAR struct mm_heap_s *heap, FAR void *oldmem,
               takeprev = needed;
               takenext = 0;
             }
-
-          needed = 0;
         }
 
       /* Check if we can extend into the next chunk and if we still need
        * more memory.
        */
 
-      if (nextsize > 0 && needed)
+      else
         {
           /* Can we get everything we need from the next chunk? */
 
@@ -276,7 +274,6 @@ FAR void *mm_realloc(FAR struct mm_heap_s *heap, FAR void *oldmem,
           /* Now we want to return newnode */
 
           oldnode = newnode;
-          oldsize = newnode->size;
         }
 
       /* Extend into the next free chunk */
@@ -306,9 +303,7 @@ FAR void *mm_realloc(FAR struct mm_heap_s *heap, FAR void *oldmem,
 
           /* Extend the node into the next chunk */
 
-          oldnode->size = oldsize + takenext;
-          newnode       = (FAR struct mm_freenode_s *)
-                          ((FAR char *)oldnode + oldnode->size);
+          oldnode->size += takenext;
 
           /* Did we consume the entire preceding chunk? */
 
@@ -318,6 +313,8 @@ FAR void *mm_realloc(FAR struct mm_heap_s *heap, FAR void *oldmem,
                * the free nodelist.
                */
 
+              newnode              = (FAR struct mm_freenode_s *)
+                                     ((FAR char *)oldnode + oldnode->size);
               newnode->size        = nextsize - takenext;
               DEBUGASSERT(newnode->size >= SIZEOF_MM_FREENODE);
               newnode->preceding   = oldnode->size;
@@ -352,7 +349,7 @@ FAR void *mm_realloc(FAR struct mm_heap_s *heap, FAR void *oldmem,
        */
 
       mm_givesemaphore(heap);
-      newmem = (FAR void *)mm_malloc(heap, size);
+      newmem = mm_malloc(heap, size);
       if (newmem)
         {
           memcpy(newmem, oldmem, oldsize - SIZEOF_MM_ALLOCNODE);