]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
MIPS: mm: Fix out-of-bounds write in maar_res_walk()
authorYadan Fan <ydfan@suse.com>
Mon, 25 May 2026 04:04:36 +0000 (12:04 +0800)
committerThomas Bogendoerfer <tsbogend@alpha.franken.de>
Mon, 15 Jun 2026 10:16:12 +0000 (12:16 +0200)
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 return non-zero
when the scratch array is full, so walk_system_ram_range() terminates the
walk instead of invoking the callback for further ranges.

Fixes: a5718fe8f70f ("MIPS: mm: Drop boot_mem_map")
Signed-off-by: Yadan Fan <ydfan@suse.com>
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
arch/mips/mm/init.c

index 55b25e85122a3201fe6149d2e1cb7c171eeed0a9..1c07ca84ee21415ffab63b70814b7a9de8416e46 100644 (file)
@@ -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(wi->num_cfg >= ARRAY_SIZE(wi->cfg)))
+               return -1;
+
+       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;
 }