of: dynamic: fix memory leak related to properties of __of_node_dup
authorLixin Wang <alan.1.wang@nokia-sbell.com>
Mon, 23 Oct 2017 03:19:53 +0000 (11:19 +0800)
committerRob Herring <robh@kernel.org>
Mon, 23 Oct 2017 16:18:44 +0000 (11:18 -0500)
If a node with no properties is dynamically added, then a property is
dynamically added to the node, then the property is dynamically removed,
the result will be node->properties == NULL and node->deadprops != NULL.

Add a separate function to release the properties in both lists.

Signed-off-by: Lixin Wang <alan.1.wang@nokia-sbell.com>
Reviewed-by: Frank Rowand <frank.rowand@sony.com>
Signed-off-by: Rob Herring <robh@kernel.org>
drivers/of/dynamic.c

index 747d876..c454941 100644 (file)
@@ -298,6 +298,18 @@ int of_detach_node(struct device_node *np)
 }
 EXPORT_SYMBOL_GPL(of_detach_node);
 
+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_node_release() - release a dynamically allocated node
  * @kref: kref element of the node to be released
@@ -307,7 +319,6 @@ EXPORT_SYMBOL_GPL(of_detach_node);
 void of_node_release(struct kobject *kobj)
 {
        struct device_node *node = kobj_to_device_node(kobj);
-       struct property *prop = node->properties;
 
        /* We should never be releasing nodes that haven't been detached. */
        if (!of_node_check_flag(node, OF_DETACHED)) {
@@ -318,18 +329,9 @@ void of_node_release(struct kobject *kobj)
        if (!of_node_check_flag(node, OF_DYNAMIC))
                return;
 
-       while (prop) {
-               struct property *next = prop->next;
-               kfree(prop->name);
-               kfree(prop->value);
-               kfree(prop);
-               prop = next;
+       property_list_free(node->properties);
+       property_list_free(node->deadprops);
 
-               if (!prop) {
-                       prop = node->deadprops;
-                       node->deadprops = NULL;
-               }
-       }
        kfree(node->full_name);
        kfree(node->data);
        kfree(node);