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
The following commit(s) were added to refs/heads/master by this push:
new 54779ca360b arch: Refuse a program that does not fit in the fixed
address windows.
54779ca360b is described below
commit 54779ca360b1695d2a85d46f9c86983d047012ac
Author: Marco Casaroli <[email protected]>
AuthorDate: Sun Nov 1 11:52:21 2026 +0100
arch: Refuse a program that does not fit in the fixed address windows.
With CONFIG_ARCH_TEXT_VBASE, CONFIG_ARCH_DATA_VBASE and
CONFIG_ARCH_HEAP_VBASE set, up_addrenv_create() maps the text at the
text base, the data after the reserved page at the data base, and the
heap at the heap base, whatever their sizes. A text larger than its
window is mapped over the reserved page and the data, a data region
larger than its window over the heap. The loader then writes into the
wrong pages, and exec() does not fail: two regions use the same
virtual addresses. For example, on rv-virt:knsh64 (1 MiB data
window) a program with 1280 KiB of .bss shares pages with its own heap
and stops on an assertion in mm_free().
Return -ENOMEM from up_addrenv_create() of arm64, RISC-V and x86_64 when
the text does not end before the data base or the data before the heap
base, so that exec() fails with ENOMEM. The heap is already limited to
its window. ARMv7-A and the ESP32-S3 check the size of each region
against its window already.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <[email protected]>
---
arch/arm64/src/common/arm64_addrenv_mmu.c | 18 ++++++++++++++++++
arch/risc-v/src/common/riscv_addrenv.c | 18 ++++++++++++++++++
arch/x86_64/src/common/x86_64_addrenv.c | 18 ++++++++++++++++++
3 files changed, 54 insertions(+)
diff --git a/arch/arm64/src/common/arm64_addrenv_mmu.c
b/arch/arm64/src/common/arm64_addrenv_mmu.c
index 784b2d79f6d..db847d34758 100644
--- a/arch/arm64/src/common/arm64_addrenv_mmu.c
+++ b/arch/arm64/src/common/arm64_addrenv_mmu.c
@@ -467,6 +467,24 @@ int up_addrenv_create(size_t textsize, size_t datasize,
size_t heapsize,
heapbase = database + MM_PGALIGNUP(datasize);
#endif
+#if (CONFIG_ARCH_TEXT_VBASE != 0x0) && (CONFIG_ARCH_HEAP_VBASE != 0x0) && \
+ (CONFIG_ARCH_TEXT_VBASE < CONFIG_ARCH_DATA_VBASE) && \
+ (CONFIG_ARCH_DATA_VBASE < CONFIG_ARCH_HEAP_VBASE)
+ /* The regions have fixed windows: the text up to the data, the data up to
+ * the heap. A region past its window would be mapped over the next one,
+ * so a program that does not fit cannot run.
+ */
+
+ if (textbase + MM_PGALIGNUP(textsize) > CONFIG_ARCH_DATA_VBASE ||
+ database + MM_PGALIGNUP(datasize) > CONFIG_ARCH_HEAP_VBASE)
+ {
+ berr("ERROR: text %zu or data %zu bytes do not fit\n",
+ textsize, datasize);
+ ret = -ENOMEM;
+ goto errout;
+ }
+#endif
+
/* Allocate 1 extra page for heap, temporary fix for #5811 */
heapsize = heapsize + MM_PGALIGNUP(4*CONFIG_DEFAULT_TASK_STACKSIZE);
diff --git a/arch/risc-v/src/common/riscv_addrenv.c
b/arch/risc-v/src/common/riscv_addrenv.c
index cb740938245..463dd8bf4ba 100644
--- a/arch/risc-v/src/common/riscv_addrenv.c
+++ b/arch/risc-v/src/common/riscv_addrenv.c
@@ -453,6 +453,24 @@ int up_addrenv_create(size_t textsize, size_t datasize,
size_t heapsize,
heapbase = database + MM_PGALIGNUP(datasize);
#endif
+#if (CONFIG_ARCH_TEXT_VBASE != 0x0) && (CONFIG_ARCH_HEAP_VBASE != 0x0) && \
+ (CONFIG_ARCH_TEXT_VBASE < CONFIG_ARCH_DATA_VBASE) && \
+ (CONFIG_ARCH_DATA_VBASE < CONFIG_ARCH_HEAP_VBASE)
+ /* The regions have fixed windows: the text up to the data, the data up to
+ * the heap. A region past its window would be mapped over the next one,
+ * so a program that does not fit cannot run.
+ */
+
+ if (textbase + MM_PGALIGNUP(textsize) > CONFIG_ARCH_DATA_VBASE ||
+ database + MM_PGALIGNUP(datasize) > CONFIG_ARCH_HEAP_VBASE)
+ {
+ berr("ERROR: text %zu or data %zu bytes do not fit\n",
+ textsize, datasize);
+ ret = -ENOMEM;
+ goto errout;
+ }
+#endif
+
/* Allocate 1 extra page for heap, temporary fix for #5811 */
heapsize = heapsize + MM_PGALIGNUP(CONFIG_DEFAULT_TASK_STACKSIZE);
diff --git a/arch/x86_64/src/common/x86_64_addrenv.c
b/arch/x86_64/src/common/x86_64_addrenv.c
index 81fd7e0bbcd..51a442192d2 100644
--- a/arch/x86_64/src/common/x86_64_addrenv.c
+++ b/arch/x86_64/src/common/x86_64_addrenv.c
@@ -417,6 +417,24 @@ int up_addrenv_create(size_t textsize, size_t datasize,
size_t heapsize,
heapbase = database + MM_PGALIGNUP(datasize);
#endif
+#if (CONFIG_ARCH_TEXT_VBASE != 0x0) && (CONFIG_ARCH_HEAP_VBASE != 0x0) && \
+ (CONFIG_ARCH_TEXT_VBASE < CONFIG_ARCH_DATA_VBASE) && \
+ (CONFIG_ARCH_DATA_VBASE < CONFIG_ARCH_HEAP_VBASE)
+ /* The regions have fixed windows: the text up to the data, the data up to
+ * the heap. A region past its window would be mapped over the next one,
+ * so a program that does not fit cannot run.
+ */
+
+ if (textbase + MM_PGALIGNUP(textsize) > CONFIG_ARCH_DATA_VBASE ||
+ database + MM_PGALIGNUP(datasize) > CONFIG_ARCH_HEAP_VBASE)
+ {
+ berr("ERROR: text %zu or data %zu bytes do not fit\n",
+ textsize, datasize);
+ ret = -ENOMEM;
+ goto errout;
+ }
+#endif
+
/* Map the reserved area */
ret = x86_64_create_region(addrenv, resvbase, resvsize, MMU_UDATA_FLAGS);