[PATCH net v5 6/6] net: phy: avoid double-free after LED trigger registration failure

Xuanqiang Luo <[email protected]>
Newsgroups org.kernel.vger.netdev,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
From: Xuanqiang Luo <[email protected]>

phy_led_triggers_register() frees phy_led_triggers when a speed trigger
registration fails, but leaves the pointer set to the freed allocation
before clearing phy_num_led_triggers.

phy_probe() ignores the registration error. If a later probe step fails,
its error path calls phy_led_triggers_unregister(); normal teardown during
an unbind or MDIO bus removal calls the same helper from phy_remove().
In either case, the trigger count is zero, so the per-trigger unregister
loop is skipped, but the dangling pointer is still freed unconditionally.

Clear the pointer when partial registration cleanup frees the array, and
make phy_led_triggers_unregister() free the array only when its pointer is
non-NULL.

Fixes: b7f0ee992adf ("net: phy: leds: fix memory leak")
Signed-off-by: Xuanqiang Luo <[email protected]>
---
 drivers/net/phy/phy_led_triggers.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/net/phy/phy_led_triggers.c b/drivers/net/phy/phy_led_triggers.c
index 4eb7716bb9d6c..ff6e518395be0 100644
--- a/drivers/net/phy/phy_led_triggers.c
+++ b/drivers/net/phy/phy_led_triggers.c
@@ -126,6 +126,7 @@ int phy_led_triggers_register(struct phy_device *phy)
 	while (i--)
 		phy_led_trigger_unregister(&phy->phy_led_triggers[i]);
 	kfree(phy->phy_led_triggers);
+	phy->phy_led_triggers = NULL;
 out_unreg_link:
 	phy_led_trigger_unregister(phy->led_link_trigger);
 out_free_link:
@@ -141,10 +142,12 @@ void phy_led_triggers_unregister(struct phy_device *phy)
 {
 	int i;
 
-	for (i = 0; i < phy->phy_num_led_triggers; i++)
-		phy_led_trigger_unregister(&phy->phy_led_triggers[i]);
-	kfree(phy->phy_led_triggers);
-	phy->phy_led_triggers = NULL;
+	if (phy->phy_led_triggers) {
+		for (i = 0; i < phy->phy_num_led_triggers; i++)
+			phy_led_trigger_unregister(&phy->phy_led_triggers[i]);
+		kfree(phy->phy_led_triggers);
+		phy->phy_led_triggers = NULL;
+	}
 
 	if (phy->led_link_trigger) {
 		phy_led_trigger_unregister(phy->led_link_trigger);
-- 
2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.