From fc453fef7708f65d4023ff63ebafe52c822229a1 Mon Sep 17 00:00:00 2001 From: Oleksandr Tyshchenko Date: Thu, 2 Apr 2026 20:38:35 +0200 Subject: [PATCH] xen/device-tree: Fix off-by-one bounds check in make_memory_node() When building Xen with CONFIG_STATIC_SHM=n, booting a hardware domain with exactly NR_MEM_BANKS (256) reserved-memory regions causes a panic: (XEN) Xen BUG at common/device-tree/domain-build.c:497 (XEN) Xen call trace: (XEN) [<00000a0000289aa8>] make_memory_node+0x178/0x234 (PC) This occurs due to an off-by-one error in the bounds checking of the reg array in make_memory_node(). The check: BUG_ON(nr_cells >= ARRAY_SIZE(reg)); incorrectly triggers when the array is exactly full (i.e., when nr_cells == ARRAY_SIZE(reg)), preventing the 256th and final valid memory region from being written. When CONFIG_STATIC_SHM=y, this bug is usually hidden because DT_MEM_NODE_REG_RANGE_SIZE adds extra space for SHM banks. This extra capacity prevents the array from reaching its maximum limit while processing the 256th memory region. However, if a domain is configured with exactly NR_MEM_BANKS and NR_SHMEM_BANKS, the array will completely fill up and trigger the same panic. Fix this by changing the condition to strictly greater than (>). Apply the exact same fix to shm_mem_node_fill_reg_range() to prevent the same error. Fixes: cd8015b634b0 ("ARM/dom0: Avoid using a variable length array in make_memory_node()") Fixes: 7846f7699fea ("xen/arm: List static shared memory regions as /memory nodes") Signed-off-by: Oleksandr Tyshchenko Reviewed-by: Michal Orzel --- xen/common/device-tree/domain-build.c | 2 +- xen/common/device-tree/static-shmem.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/xen/common/device-tree/domain-build.c b/xen/common/device-tree/domain-build.c index 6708c9dd66..540627b74e 100644 --- a/xen/common/device-tree/domain-build.c +++ b/xen/common/device-tree/domain-build.c @@ -494,7 +494,7 @@ int __init make_memory_node(const struct kernel_info *kinfo, int addrcells, continue; nr_cells += reg_size; - BUG_ON(nr_cells >= ARRAY_SIZE(reg)); + BUG_ON(nr_cells > ARRAY_SIZE(reg)); dt_child_set_range(&cells, addrcells, sizecells, start, size); } diff --git a/xen/common/device-tree/static-shmem.c b/xen/common/device-tree/static-shmem.c index 79f23caa77..4c4cc1b123 100644 --- a/xen/common/device-tree/static-shmem.c +++ b/xen/common/device-tree/static-shmem.c @@ -838,7 +838,7 @@ void __init shm_mem_node_fill_reg_range(const struct kernel_info *kinfo, paddr_t size = mem->bank[i].size; *nr_cells += addrcells + sizecells; - BUG_ON(*nr_cells >= DT_MEM_NODE_REG_RANGE_SIZE); + BUG_ON(*nr_cells > DT_MEM_NODE_REG_RANGE_SIZE); dt_child_set_range(&cells, addrcells, sizecells, start, size); } }