From f9879086c4eb4b3b0f4baa80139a5720b99b229e Mon Sep 17 00:00:00 2001 From: Miles Krause Date: Thu, 10 Sep 2026 15:43:20 -0400 Subject: [PATCH] leds: lp8860: Fix device_node leak in lp8860_probe() lp8860_probe() looks up the driver's single LED child node with of_get_next_available_child() and hands it to the LED core as init_data.fwnode, but never drops the reference that lookup returned: child_node = of_get_next_available_child(np, NULL); if (!child_node) return -EINVAL; ... init_data.fwnode = of_fwnode_handle(child_node); of_get_next_available_child() returns the node with its refcount incremented, and the LED core does not take a reference of its own: led_classdev_register_ext() only reads properties out of init_data.fwnode and then stores the bare pointer with device_set_node(). The reference therefore stays owned by the driver for as long as it holds the node. Nothing in lp8860_probe() ever releases it, so it is leaked on every error return taken after the lookup - the enable GPIO, the vled regulator, devm_mutex_init(), the regmap allocation, the optional EEPROM programming and the LED class registration - and on a fully successful probe alike. A device that binds and unbinds repeatedly leaks one device_node reference per bind. Sibling drivers already get this right: leds-lm3692x.c, from the same TI LED family, calls fwnode_handle_put(init_data.fwnode) once after devm_led_classdev_register_ext() to cover both outcomes, while leds-ktd2692.c and leds-aat1290.c take the node with __free(device_node). Use __free(device_node) here too. Unlike a single of_node_put() at the end of probe it also covers the intermediate error returns, and it keeps the node alive for the whole function, which the LED core still needs when it reads the child's properties during registration. Fixes: 99ca0ea57309 ("leds: lp8860: Use generic support for composing LED names") Signed-off-by: Miles Krause Link: https://patch.msgid.link/20260910-leds-lp8860-of-node-leak-v1-1-d333cff4345b@gmail.com Signed-off-by: Lee Jones --- drivers/leds/leds-lp8860.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/leds/leds-lp8860.c b/drivers/leds/leds-lp8860.c index 69f064781f69..f6e4227de903 100644 --- a/drivers/leds/leds-lp8860.c +++ b/drivers/leds/leds-lp8860.c @@ -7,6 +7,7 @@ * Author: Dan Murphy */ +#include #include #include #include @@ -274,7 +275,6 @@ static int lp8860_probe(struct i2c_client *client) int ret; struct lp8860_led *led; struct device_node *np = dev_of_node(&client->dev); - struct device_node *child_node; struct led_init_data init_data = {}; struct gpio_desc *enable_gpio; @@ -282,7 +282,8 @@ static int lp8860_probe(struct i2c_client *client) if (!led) return -ENOMEM; - child_node = of_get_next_available_child(np, NULL); + struct device_node *child_node __free(device_node) = + of_get_next_available_child(np, NULL); if (!child_node) return -EINVAL;