device property: fix of node refcount leak in fwnode_graph_get_next_endpoint()
authorYang Yingliang <yangyingliang@huawei.com>
Wed, 23 Nov 2022 02:25:42 +0000 (10:25 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 1 Feb 2023 07:34:26 +0000 (08:34 +0100)
[ Upstream commit 39af728649b05e88a2b40e714feeee6451c3f18e ]

The 'parent' returned by fwnode_graph_get_port_parent()
with refcount incremented when 'prev' is not NULL, it
needs be put when finish using it.

Because the parent is const, introduce a new variable to
store the returned fwnode, then put it before returning
from fwnode_graph_get_next_endpoint().

Fixes: b5b41ab6b0c1 ("device property: Check fwnode->secondary in fwnode_graph_get_next_endpoint()")
Signed-off-by: Yang Yingliang <yangyingliang@huawei.com>
Reviewed-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Reviewed-and-tested-by: Daniel Scally <djrscally@gmail.com>
Link: https://lore.kernel.org/r/20221123022542.2999510-1-yangyingliang@huawei.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/base/property.c

index 2a5a37f..7f338cb 100644 (file)
@@ -989,26 +989,32 @@ struct fwnode_handle *
 fwnode_graph_get_next_endpoint(const struct fwnode_handle *fwnode,
                               struct fwnode_handle *prev)
 {
+       struct fwnode_handle *ep, *port_parent = NULL;
        const struct fwnode_handle *parent;
-       struct fwnode_handle *ep;
 
        /*
         * If this function is in a loop and the previous iteration returned
         * an endpoint from fwnode->secondary, then we need to use the secondary
         * as parent rather than @fwnode.
         */
-       if (prev)
-               parent = fwnode_graph_get_port_parent(prev);
-       else
+       if (prev) {
+               port_parent = fwnode_graph_get_port_parent(prev);
+               parent = port_parent;
+       } else {
                parent = fwnode;
+       }
        if (IS_ERR_OR_NULL(parent))
                return NULL;
 
        ep = fwnode_call_ptr_op(parent, graph_get_next_endpoint, prev);
        if (ep)
-               return ep;
+               goto out_put_port_parent;
+
+       ep = fwnode_graph_get_next_endpoint(parent->secondary, NULL);
 
-       return fwnode_graph_get_next_endpoint(parent->secondary, NULL);
+out_put_port_parent:
+       fwnode_handle_put(port_parent);
+       return ep;
 }
 EXPORT_SYMBOL_GPL(fwnode_graph_get_next_endpoint);