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

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

commit 2b1cd241da4406388cc3dac505d700b95823c92a
Author: Marco Casaroli <[email protected]>
AuthorDate: Mon Oct 12 16:54:23 2026 +0200

    mm/umm_heap: Do not set errno in the kernel copy of the user heap.
    
    In a kernel build, the kernel allocates from the user heap through
    kumm_*(), also while the address environment of another process is
    selected: up_create_stack() allocates the stack of a new process in
    its heap.  When that heap could not grow, sbrk() and memalign() set
    errno, which is in the TLS of the calling thread, at an address that
    is not mapped in the new process.  The kernel took a data abort (or
    wrote into the memory of the new process).
    
    As kmm_*(), do not set errno in the kernel copy of the user heap.
    
    Assisted-by: Claude Code:claude-opus-5-5
    Signed-off-by: Marco Casaroli <[email protected]>
---
 mm/umm_heap/umm_calloc.c   |  2 +-
 mm/umm_heap/umm_heap.h     | 14 ++++++++++++++
 mm/umm_heap/umm_malloc.c   |  2 +-
 mm/umm_heap/umm_memalign.c |  2 +-
 mm/umm_heap/umm_realloc.c  |  2 +-
 mm/umm_heap/umm_sbrk.c     |  2 +-
 mm/umm_heap/umm_zalloc.c   |  2 +-
 7 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/mm/umm_heap/umm_calloc.c b/mm/umm_heap/umm_calloc.c
index 5913bd2d32d..2564f0860f7 100644
--- a/mm/umm_heap/umm_calloc.c
+++ b/mm/umm_heap/umm_calloc.c
@@ -77,7 +77,7 @@ FAR void *calloc(size_t n, size_t elem_size)
 
   if (mem == NULL)
     {
-      set_errno(ENOMEM);
+      umm_set_errno(ENOMEM);
     }
   else
     {
diff --git a/mm/umm_heap/umm_heap.h b/mm/umm_heap/umm_heap.h
index c2b5de12c18..10487df22fa 100644
--- a/mm/umm_heap/umm_heap.h
+++ b/mm/umm_heap/umm_heap.h
@@ -29,6 +29,8 @@
 
 #include <nuttx/config.h>
 
+#include <errno.h>
+
 #include <nuttx/addrenv.h>
 #include <nuttx/mm/mm.h>
 
@@ -36,6 +38,18 @@
  * Pre-processor Definitions
  ****************************************************************************/
 
+/* errno is in the TLS of the calling thread.  The kernel uses the user heap
+ * through kumm_*(), also while the address environment of another process
+ * is selected, where that TLS is not mapped.  As kmm_*(), the kernel copy
+ * of the user heap does not set errno.
+ */
+
+#if defined(CONFIG_BUILD_FLAT) || !defined(__KERNEL__)
+#  define umm_set_errno(e) set_errno(e)
+#else
+#  define umm_set_errno(e) ((void)(e))
+#endif
+
 /****************************************************************************
  * Public Function Prototypes
  ****************************************************************************/
diff --git a/mm/umm_heap/umm_malloc.c b/mm/umm_heap/umm_malloc.c
index 22cf89bb163..5977f373550 100644
--- a/mm/umm_heap/umm_malloc.c
+++ b/mm/umm_heap/umm_malloc.c
@@ -66,7 +66,7 @@ FAR void *malloc(size_t size)
   ret = mm_malloc(USR_HEAP, size);
   if (ret == NULL)
     {
-      set_errno(ENOMEM);
+      umm_set_errno(ENOMEM);
     }
   else
     {
diff --git a/mm/umm_heap/umm_memalign.c b/mm/umm_heap/umm_memalign.c
index 11a2f47f44e..f8ba7e27488 100644
--- a/mm/umm_heap/umm_memalign.c
+++ b/mm/umm_heap/umm_memalign.c
@@ -93,7 +93,7 @@ FAR void *memalign(size_t alignment, size_t size)
   ret = mm_memalign(USR_HEAP, alignment, size);
   if (ret == NULL)
     {
-      set_errno(ENOMEM);
+      umm_set_errno(ENOMEM);
     }
   else
     {
diff --git a/mm/umm_heap/umm_realloc.c b/mm/umm_heap/umm_realloc.c
index 677e2249d2d..a69a6191ee6 100644
--- a/mm/umm_heap/umm_realloc.c
+++ b/mm/umm_heap/umm_realloc.c
@@ -95,7 +95,7 @@ FAR void *realloc(FAR void *oldmem, size_t size)
   ret = mm_realloc(USR_HEAP, oldmem, size);
   if (ret == NULL)
     {
-      set_errno(ENOMEM);
+      umm_set_errno(ENOMEM);
     }
   else
     {
diff --git a/mm/umm_heap/umm_sbrk.c b/mm/umm_heap/umm_sbrk.c
index 5d338b5f431..fee74490575 100644
--- a/mm/umm_heap/umm_sbrk.c
+++ b/mm/umm_heap/umm_sbrk.c
@@ -121,6 +121,6 @@ FAR void *sbrk(intptr_t incr)
   return (FAR void *)brkaddr;
 
 errout:
-  set_errno(errcode);
+  umm_set_errno(errcode);
   return (FAR void *)-1;
 }
diff --git a/mm/umm_heap/umm_zalloc.c b/mm/umm_heap/umm_zalloc.c
index a8327db7ca0..8b466a3bc44 100644
--- a/mm/umm_heap/umm_zalloc.c
+++ b/mm/umm_heap/umm_zalloc.c
@@ -73,7 +73,7 @@ FAR void *zalloc(size_t size)
   ret = mm_zalloc(USR_HEAP, size);
   if (ret == NULL)
     {
-      set_errno(ENOMEM);
+      umm_set_errno(ENOMEM);
     }
   else
     {

Reply via email to