drivers/base/component.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
component_match_add_release() accepts a release callback so callers can
transfer ownership of resources held by the match data. However,
__component_match_add() returns without invoking that callback when the
match is already an error pointer or when allocating the match or its
array fails.
This leaks resources acquired before the call. For example,
drm_of_component_match_add() takes a reference to its device node before
adding the match, and ERR_PTR-aware callers can return from probe with
that reference still held. Calls made after the first allocation failure
can leak further references.
Invoke the release callback whenever the match data cannot be added, and
document the failure-path ownership rule. Successful match lifetime
semantics remain unchanged.
This issue was found by a static analysis checker and confirmed by manual
source review.
Fixes: ce657b1cddf1 ("component: add support for releasing match data")
Signed-off-by: Ruoyu Wang <ruoyuw560@gmail.com>
---
drivers/base/component.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/drivers/base/component.c b/drivers/base/component.c
index 655d68deb590c..2b455d7499926 100644
--- a/drivers/base/component.c
+++ b/drivers/base/component.c
@@ -388,14 +388,14 @@ static void __component_match_add(struct device *parent,
struct component_match *match = *matchptr;
if (IS_ERR(match))
- return;
+ goto err_release;
if (!match) {
match = devres_alloc(devm_component_match_release,
sizeof(*match), GFP_KERNEL);
if (!match) {
*matchptr = ERR_PTR(-ENOMEM);
- return;
+ goto err_release;
}
devres_add(parent, match);
@@ -410,7 +410,7 @@ static void __component_match_add(struct device *parent,
ret = component_match_realloc(match, new_size);
if (ret) {
*matchptr = ERR_PTR(ret);
- return;
+ goto err_release;
}
}
@@ -420,6 +420,11 @@ static void __component_match_add(struct device *parent,
match->compare[match->num].data = compare_data;
match->compare[match->num].component = NULL;
match->num++;
+ return;
+
+err_release:
+ if (release)
+ release(parent, compare_data);
}
/**
@@ -438,7 +443,8 @@ static void __component_match_add(struct device *parent,
* The allocated match list in @matchptr is automatically released using devm
* actions, where upon @release will be called to free any references held by
* @compare_data, e.g. when @compare_data is a &device_node that must be
- * released with of_node_put().
+ * released with of_node_put(). @release is also called if the match cannot be
+ * added.
*
* See also component_match_add() and component_match_add_typed().
*/
--
2.51.0
© 2016 - 2026 Red Hat, Inc.