[PATCH v2 4/4] mfd: tps65217: Fix NULL pointer dereference in remove callback

Жамбакиев Радий Рикардинович <[email protected]>
Newsgroups org.kernel.vger.linux-omap,dev.linux.lists.mfd,org.kernel.vger.linux-kernel,org.kernel.vger.stable
Message-ID <[email protected]>
When the device is probed without an interrupt, tps65217_irq_init() is
never called and tps->irq_domain remains NULL. The remove callback
still looks up IRQ mappings and calls irq_domain_remove(), which
dereferences the NULL domain and crashes the kernel. The mapping
lookup with a NULL domain falls back to the default IRQ domain and can
dispose mappings belonging to other devices.

Quiesce the parent interrupt before tearing down the domain: the
devres-managed interrupt is only freed after the remove callback
returns, so an interrupt firing in that window would run the threaded
handler with a NULL irq_domain. Also call disable_irq_wake() to balance
the enable_irq_wake() done in tps65217_irq_init().

Fixes: 6556bdacf646fcaa ("mfd: tps65217: Add support for IRQs")
Cc: [email protected]
Signed-off-by: Radiy Zhambakiev <[email protected]>
---
 drivers/mfd/tps65217.c | 21 ++++++++++++---------
 1 file changed, 12 insertions(+), 9 deletions(-)

diff --git a/drivers/mfd/tps65217.c b/drivers/mfd/tps65217.c
index d535d140c2e9..9f4afbaa6524 100644
--- a/drivers/mfd/tps65217.c
+++ b/drivers/mfd/tps65217.c
@@ -403,17 +403,20 @@ static int tps65217_probe(struct i2c_client *client)
 static void tps65217_remove(struct i2c_client *client)
 {
 	struct tps65217 *tps = i2c_get_clientdata(client);
-	unsigned int virq;
-	int i;
 
-	for (i = 0; i < TPS65217_NUM_IRQ; i++) {
-		virq = irq_find_mapping(tps->irq_domain, i);
-		if (virq)
-			irq_dispose_mapping(virq);
-	}
+	if (!tps->irq_domain)
+		return;
 
-	irq_domain_remove(tps->irq_domain);
-	tps->irq_domain = NULL;
+	/*
+	 * The interrupt is only freed by devres after this callback
+	 * returns, so make sure no handler can run while the domain
+	 * is being torn down.
+	 */
+	disable_irq(tps->irq);
+	synchronize_irq(tps->irq);
+	disable_irq_wake(tps->irq);
+
+	tps65217_irq_cleanup(tps);
 }
 
 static const struct i2c_device_id tps65217_id_table[] = {
-- 
2.53.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.