[PATCH] extcon: lc824206xa: Use devm_work_autocancel() for detect work

Fan Wu <[email protected]>
Newsgroups org.kernel.vger.stable,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
The detect work is re-armed by the threaded IRQ handler but nothing drains
it on detach: devm frees the IRQ before kfree(data) without flushing the
workqueue, so a pending work item can run after data is freed, leading to a
use-after-free.

Use devm_work_autocancel() so devm LIFO order frees the IRQ before the work
is cancelled. Register it after the regulator, extcon and power_supply
the work callback dereferences, so those are not freed before the cancel
either.

This issue was found by an in-house static analysis tool.
Compile-tested only; runtime testing is appreciated.

Fixes: 9e1897cb9568 ("extcon: Add LC824206XA microUSB switch driver")
Cc: [email protected]
Assisted-by: Codex:gpt-5.6
Signed-off-by: Fan Wu <[email protected]>
---
 drivers/extcon/extcon-lc824206xa.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/extcon/extcon-lc824206xa.c b/drivers/extcon/extcon-lc824206xa.c
index 56938748aea8..adcea69ac221 100644
--- a/drivers/extcon/extcon-lc824206xa.c
+++ b/drivers/extcon/extcon-lc824206xa.c
@@ -19,6 +19,7 @@
 #include <linux/bits.h>
 #include <linux/delay.h>
 #include <linux/device.h>
+#include <linux/devm-helpers.h>
 #include <linux/extcon-provider.h>
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
@@ -424,7 +425,6 @@ static int lc824206xa_probe(struct i2c_client *client)
 		return -ENOMEM;
 
 	data->client = client;
-	INIT_WORK(&data->work, lc824206xa_work);
 	data->cable = EXTCON_NONE;
 	data->previous_cable = EXTCON_NONE;
 	data->usb_type = POWER_SUPPLY_USB_TYPE_UNKNOWN;
@@ -463,6 +463,11 @@ static int lc824206xa_probe(struct i2c_client *client)
 	if (IS_ERR(data->psy))
 		return dev_err_probe(dev, PTR_ERR(data->psy), "registering power supply\n");
 
+	/* After all resources lc824206xa_work() derefs; before the IRQ producer. */
+	ret = devm_work_autocancel(dev, &data->work, lc824206xa_work);
+	if (ret)
+		return ret;
+
 	ret = devm_request_threaded_irq(dev, client->irq, NULL, lc824206xa_irq,
 					IRQF_TRIGGER_LOW | IRQF_ONESHOT,
 					KBUILD_MODNAME, data);
-- 
2.39.5
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.