]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drivers/of: fdt: validate flat DT string properties before string use
authorPengpeng Hou <pengpeng@iscas.ac.cn>
Fri, 3 Apr 2026 05:59:47 +0000 (13:59 +0800)
committerRob Herring (Arm) <robh@kernel.org>
Mon, 13 Apr 2026 20:01:26 +0000 (15:01 -0500)
Firmware-supplied flat DT properties are raw byte sequences. Several
early FDT helpers fetch properties such as status, model, compatible,
and device_type and then use them as C strings with strcmp(), strlen(),
or pr_info() without first proving that the property is NUL-terminated
within its declared length.

Use fdt_stringlist_get() for these string properties instead. That
preserves the existing behavior for valid DTBs while rejecting malformed
unterminated properties before they are passed to C string helpers.

Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
Link: https://patch.msgid.link/20260403164501.1-drivers-of-fdt-v2-pengpeng@iscas.ac.cn
Signed-off-by: Rob Herring (Arm) <robh@kernel.org>
drivers/of/fdt.c

index 9e4131f0e9b2e7936e07b5581761df4c09b54617..becc855ff8b544ab5e7915603edc572351fe16be 100644 (file)
@@ -68,7 +68,7 @@ void __init of_fdt_limit_memory(int limit)
 
 bool of_fdt_device_is_available(const void *blob, unsigned long node)
 {
-       const char *status = fdt_getprop(blob, node, "status", NULL);
+       const char *status = fdt_stringlist_get(blob, node, "status", 0, NULL);
 
        if (!status)
                return true;
@@ -677,22 +677,15 @@ void __init of_flat_dt_read_addr_size(const __be32 *prop, int entry_index,
  * specific compatible values.
  */
 static int of_fdt_is_compatible(const void *blob,
-                     unsigned long node, const char *compat)
+                             unsigned long node, const char *compat)
 {
        const char *cp;
-       int cplen;
-       unsigned long l, score = 0;
+       int idx = 0, score = 0;
 
-       cp = fdt_getprop(blob, node, "compatible", &cplen);
-       if (cp == NULL)
-               return 0;
-       while (cplen > 0) {
+       while ((cp = fdt_stringlist_get(blob, node, "compatible", idx++, NULL))) {
                score++;
                if (of_compat_cmp(cp, compat, strlen(compat)) == 0)
                        return score;
-               l = strlen(cp) + 1;
-               cp += l;
-               cplen -= l;
        }
 
        return 0;
@@ -741,9 +734,10 @@ const char * __init of_flat_dt_get_machine_name(void)
        const char *name;
        unsigned long dt_root = of_get_flat_dt_root();
 
-       name = of_get_flat_dt_prop(dt_root, "model", NULL);
+       name = fdt_stringlist_get(initial_boot_params, dt_root, "model", 0, NULL);
        if (!name)
-               name = of_get_flat_dt_prop(dt_root, "compatible", NULL);
+               name = fdt_stringlist_get(initial_boot_params, dt_root,
+                                         "compatible", 0, NULL);
        return name;
 }
 
@@ -775,19 +769,14 @@ const void * __init of_flat_dt_match_machine(const void *default_match,
        }
        if (!best_data) {
                const char *prop;
-               int size;
+               int idx = 0, size;
 
                pr_err("\n unrecognized device tree list:\n[ ");
 
-               prop = of_get_flat_dt_prop(dt_root, "compatible", &size);
-               if (prop) {
-                       while (size > 0) {
-                               printk("'%s' ", prop);
-                               size -= strlen(prop) + 1;
-                               prop += strlen(prop) + 1;
-                       }
-               }
-               printk("]\n\n");
+               while ((prop = fdt_stringlist_get(initial_boot_params, dt_root,
+                                                 "compatible", idx++, &size)))
+                       pr_err("'%s' ", prop);
+               pr_err("]\n\n");
                return NULL;
        }
 
@@ -1032,7 +1021,8 @@ int __init early_init_dt_scan_memory(void)
        const void *fdt = initial_boot_params;
 
        fdt_for_each_subnode(node, fdt, 0) {
-               const char *type = of_get_flat_dt_prop(node, "device_type", NULL);
+               const char *type = fdt_stringlist_get(fdt, node,
+                                                     "device_type", 0, NULL);
                const __be32 *reg;
                int i, l;
                bool hotpluggable;