]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
of: Add a helper to free property struct
authorRob Herring <robh@kernel.org>
Tue, 9 Apr 2024 18:59:39 +0000 (13:59 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 4 Sep 2025 13:30:18 +0000 (15:30 +0200)
[ Upstream commit 1c5e3d9bf33b811e1c6dd9081b322004acc4a1fd ]

Freeing a property struct is 3 kfree()'s which is duplicated in multiple
spots. Add a helper, __of_prop_free(), and replace all the open coded
cases in the DT code.

Reviewed-by: Saravana Kannan <saravanak@google.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Link: https://lore.kernel.org/r/20240409-dt-cleanup-free-v2-1-5b419a4af38d@kernel.org
Signed-off-by: Rob Herring <robh@kernel.org>
Stable-dep-of: 80af3745ca46 ("of: dynamic: Fix use after free in of_changeset_add_prop_helper()")
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/of/dynamic.c
drivers/of/of_private.h
drivers/of/overlay.c
drivers/of/unittest.c

index 7f78fba502ec49f733db021b7c79f5038d616da3..72531f44adf09b19d77f5b61f55262df254799a7 100644 (file)
@@ -306,15 +306,20 @@ int of_detach_node(struct device_node *np)
 }
 EXPORT_SYMBOL_GPL(of_detach_node);
 
+void __of_prop_free(struct property *prop)
+{
+       kfree(prop->name);
+       kfree(prop->value);
+       kfree(prop);
+}
+
 static void property_list_free(struct property *prop_list)
 {
        struct property *prop, *next;
 
        for (prop = prop_list; prop != NULL; prop = next) {
                next = prop->next;
-               kfree(prop->name);
-               kfree(prop->value);
-               kfree(prop);
+               __of_prop_free(prop);
        }
 }
 
@@ -427,9 +432,7 @@ struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags)
        return new;
 
  err_free:
-       kfree(new->name);
-       kfree(new->value);
-       kfree(new);
+       __of_prop_free(new);
        return NULL;
 }
 
@@ -471,9 +474,7 @@ struct device_node *__of_node_dup(const struct device_node *np,
                        if (!new_pp)
                                goto err_prop;
                        if (__of_add_property(node, new_pp)) {
-                               kfree(new_pp->name);
-                               kfree(new_pp->value);
-                               kfree(new_pp);
+                               __of_prop_free(new_pp);
                                goto err_prop;
                        }
                }
@@ -933,11 +934,8 @@ static int of_changeset_add_prop_helper(struct of_changeset *ocs,
                return -ENOMEM;
 
        ret = of_changeset_add_property(ocs, np, new_pp);
-       if (ret) {
-               kfree(new_pp->name);
-               kfree(new_pp->value);
-               kfree(new_pp);
-       }
+       if (ret)
+               __of_prop_free(new_pp);
 
        new_pp->next = np->deadprops;
        np->deadprops = new_pp;
index 21f8f5e80917d109a96dc3db15591c80b28d140f..73b55f4f84a3cc01be12b07cb912fcaed8751c75 100644 (file)
@@ -123,6 +123,7 @@ extern void *__unflatten_device_tree(const void *blob,
  * own the devtree lock or work on detached trees only.
  */
 struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags);
+void __of_prop_free(struct property *prop);
 struct device_node *__of_node_dup(const struct device_node *np,
                                  const char *full_name);
 
index a9a292d6d59b263ebcc7005511c01b42dbdc06f1..dc13299586414fcfeac68c2703dd5ac270584746 100644 (file)
@@ -262,9 +262,7 @@ static struct property *dup_and_fixup_symbol_prop(
        return new_prop;
 
 err_free_new_prop:
-       kfree(new_prop->name);
-       kfree(new_prop->value);
-       kfree(new_prop);
+       __of_prop_free(new_prop);
 err_free_target_path:
        kfree(target_path);
 
@@ -361,11 +359,8 @@ static int add_changeset_property(struct overlay_changeset *ovcs,
                pr_err("WARNING: memory leak will occur if overlay removed, property: %pOF/%s\n",
                       target->np, new_prop->name);
 
-       if (ret) {
-               kfree(new_prop->name);
-               kfree(new_prop->value);
-               kfree(new_prop);
-       }
+       if (ret)
+               __of_prop_free(new_prop);
        return ret;
 }
 
index 3b22c36bfb0b7c8f54de4b120f0a6f663c4ec18c..5bfec440b4fd700e774f4cc608d067dc1e39d4dc 100644 (file)
@@ -800,15 +800,11 @@ static void __init of_unittest_property_copy(void)
 
        new = __of_prop_dup(&p1, GFP_KERNEL);
        unittest(new && propcmp(&p1, new), "empty property didn't copy correctly\n");
-       kfree(new->value);
-       kfree(new->name);
-       kfree(new);
+       __of_prop_free(new);
 
        new = __of_prop_dup(&p2, GFP_KERNEL);
        unittest(new && propcmp(&p2, new), "non-empty property didn't copy correctly\n");
-       kfree(new->value);
-       kfree(new->name);
-       kfree(new);
+       __of_prop_free(new);
 #endif
 }
 
@@ -3665,9 +3661,7 @@ static __init void of_unittest_overlay_high_level(void)
                                goto err_unlock;
                        }
                        if (__of_add_property(of_symbols, new_prop)) {
-                               kfree(new_prop->name);
-                               kfree(new_prop->value);
-                               kfree(new_prop);
+                               __of_prop_free(new_prop);
                                /* "name" auto-generated by unflatten */
                                if (!strcmp(prop->name, "name"))
                                        continue;