[PATCH v2] MIPS: mm: Fix out-of-bounds write in maar_res_walk()

Yadan Fan posted 1 patch 1 week, 6 days ago
There is a newer version of this series
arch/mips/mm/init.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
[PATCH v2] MIPS: mm: Fix out-of-bounds write in maar_res_walk()
Posted by Yadan Fan 1 week, 6 days ago
From 6496b7e4d61ce77ff3723054f807888f1bffddc4 Mon Sep 17 00:00:00 2001
From: Yadan Fan <ydfan@suse.com>
Date: Mon, 25 May 2026 12:04:36 +0800
Subject: [PATCH] MIPS: mm: Fix out-of-bounds write in maar_res_walk()

maar_res_walk() uses wi->num_cfg as the index into the fixed-size
wi->cfg array, but checks whether the array is full only after it has
filled the selected entry. If walk_system_ram_range() reports more than
16 memory ranges, the overflow call writes one struct maar_config past
the end of the array before WARN_ON() prevents num_cfg from advancing.

Move the full-array check before taking the array slot and use
WARN_ON_ONCE(), since the guard now runs before every later range once
the scratch array is full. After the array fills, further ranges are
ignored instead of attempting to store them. The previous code
effectively tried to keep overwriting an out-of-bounds slot, which could
not preserve those ranges safely.

Fixes: a5718fe8f70f ("MIPS: mm: Drop boot_mem_map")

Signed-off-by: Yadan Fan <ydfan@suse.com>
---
Changes in v2:
  - Use WARN_ON_ONCE() for the full-array guard.
  - Update the commit log to state that later ranges are ignored once the
    scratch array is full, instead of claiming unchanged behavior.

 arch/mips/mm/init.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index 55b25e85122a..4b7db3f7c8a7 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -272,9 +272,15 @@ static int maar_res_walk(unsigned long start_pfn, unsigned long nr_pages,
 			 void *data)
 {
 	struct maar_walk_info *wi = data;
-	struct maar_config *cfg = &wi->cfg[wi->num_cfg];
+	struct maar_config *cfg;
 	unsigned int maar_align;
 
+	/* Ensure we don't overflow the cfg array */
+	if (WARN_ON_ONCE(wi->num_cfg >= ARRAY_SIZE(wi->cfg)))
+		return 0;
+
+	cfg = &wi->cfg[wi->num_cfg];
+
 	/* MAAR registers hold physical addresses right shifted by 4 bits */
 	maar_align = BIT(MIPS_MAAR_ADDR_SHIFT + 4);
 
@@ -283,9 +289,7 @@ static int maar_res_walk(unsigned long start_pfn, unsigned long nr_pages,
 	cfg->upper = ALIGN_DOWN(PFN_PHYS(start_pfn + nr_pages), maar_align) - 1;
 	cfg->attrs = MIPS_MAAR_S;
 
-	/* Ensure we don't overflow the cfg array */
-	if (!WARN_ON(wi->num_cfg >= ARRAY_SIZE(wi->cfg)))
-		wi->num_cfg++;
+	wi->num_cfg++;
 
 	return 0;
 }
-- 
2.51.0