]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
of: reserved_mem: prevent OOB when too many dynamic regions are defined
authorSang-Heon Jeon <ekffu200098@gmail.com>
Sun, 14 Jun 2026 13:38:06 +0000 (22:38 +0900)
committerRob Herring (Arm) <robh@kernel.org>
Mon, 20 Jul 2026 20:52:39 +0000 (15:52 -0500)
On boot, fdt_scan_reserved_mem() saves each dynamically-placed
/reserved-memory subnode into a local array of size
MAX_RESERVED_REGIONS.

If the device tree defines more than MAX_RESERVED_REGIONS
dynamically-placed regions, fdt_scan_reserved_mem() writes past the
end of the local array.

Add a bounds check that logs an error and skips the excess regions,
restoring the original behavior.

Fixes: 8a6e02d0c00e ("of: reserved_mem: Restructure how the reserved memory regions are processed")
Signed-off-by: Sang-Heon Jeon <ekffu200098@gmail.com>
Link: https://patch.msgid.link/20260614133807.2165124-2-ekffu200098@gmail.com
Signed-off-by: Rob Herring (Arm) <robh@kernel.org>
drivers/of/of_reserved_mem.c

index 82222bd45ac66f33baa3b2c80c3fe8b078952154..42e3e2d8a2b83ae00ad117b02563894a65917986 100644 (file)
@@ -359,6 +359,7 @@ int __init fdt_scan_reserved_mem(void)
                err = __reserved_mem_reserve_reg(child, uname);
                if (!err)
                        count++;
+
                /*
                 * Save the nodes for the dynamically-placed regions
                 * into an array which will be used for allocation right
@@ -366,10 +367,17 @@ int __init fdt_scan_reserved_mem(void)
                 * or marked as no-map. This is done to avoid dynamically
                 * allocating from one of the statically-placed regions.
                 */
-               if (err == -ENOENT && of_get_flat_dt_prop(child, "size", NULL)) {
-                       dynamic_nodes[dynamic_nodes_cnt] = child;
-                       dynamic_nodes_cnt++;
+               if (err != -ENOENT || !of_get_flat_dt_prop(child, "size", NULL))
+                       continue;
+
+               if (dynamic_nodes_cnt == MAX_RESERVED_REGIONS) {
+                       pr_err("too many defined dynamic regions, skip '%s'\n",
+                              uname);
+                       continue;
                }
+
+               dynamic_nodes[dynamic_nodes_cnt] = child;
+               dynamic_nodes_cnt++;
        }
        for (int i = 0; i < dynamic_nodes_cnt; i++) {
                const char *uname;