lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Message-ID: <20260127160512.577735-1-alexander.sverdlin@siemens.com>
Date: Tue, 27 Jan 2026 17:05:06 +0100
From: "A. Sverdlin" <alexander.sverdlin@...mens.com>
To: Vijai Kumar K <vijaikumar.kanagarajan@...il.com>,
	linux-kernel@...r.kernel.org
Cc: Alexander Sverdlin <alexander.sverdlin@...mens.com>,
	Krzysztof Kozlowski <krzk@...nel.org>,
	MyungJoo Ham <myungjoo.ham@...sung.com>,
	Chanwoo Choi <cw00.choi@...sung.com>,
	stable@...r.kernel.org
Subject: [PATCH] extcon: ptn5150: Avoid IRQ vs probe race and drop mutex

From: Alexander Sverdlin <alexander.sverdlin@...mens.com>

The IRQ is being requested quite early in probe sequence, where neither
mutex has been taken, nor info->edev has been set yet. From this point on
one shall expect the handler to be called. The corresponding test for
!info->edev looks pointless being not protected by the mutex.

Moving the IRQ request to the end of probe sequence avoids the race against
ptn5150_check_state() and other init steps (devm_extcon_dev_allocate(),
devm_extcon_dev_register()).

Finally it becomes obvious that the worker function doesn't run
concurrently with anything else and we can drop the mutex completely.

The change has been motivated by the following crash:

Unable to handle kernel paging request at virtual address 006c727400353434
CPU: 1 UID: 0 PID: 74 Comm: kworker/1:2 6.18.0-next-20251212
Workqueue: events ptn5150_irq_work [extcon_ptn5150]
pc : 0x6c727400353434
lr : notifier_call_chain+0x80
Call trace:
 0x6c727400353434 (P)
 raw_notifier_call_chain+0x20
 extcon_sync+0xd0
 extcon_set_state_sync+0x3c
 ptn5150_check_state+0xf8 [extcon_ptn5150]
 ptn5150_irq_work [extcon_ptn5150]
 process_one_work
 worker_thread
 kthread
 ret_from_fork
Kernel panic - not syncing: Oops: Fatal exception

Cc: stable@...r.kernel.org
Fixes: 4ed754de2d66 ("extcon: Add support for ptn5150 extcon driver")
Signed-off-by: Alexander Sverdlin <alexander.sverdlin@...mens.com>
---
 drivers/extcon/extcon-ptn5150.c | 38 ++++++++++-----------------------
 1 file changed, 11 insertions(+), 27 deletions(-)

diff --git a/drivers/extcon/extcon-ptn5150.c b/drivers/extcon/extcon-ptn5150.c
index eca1b140aeb0f..cb5646bf91c5e 100644
--- a/drivers/extcon/extcon-ptn5150.c
+++ b/drivers/extcon/extcon-ptn5150.c
@@ -57,7 +57,6 @@ struct ptn5150_info {
 	struct gpio_desc *vbus_gpiod;
 	int irq;
 	struct work_struct irq_work;
-	struct mutex mutex;
 	struct typec_switch *orient_sw;
 	struct usb_role_switch *role_sw;
 };
@@ -144,16 +143,10 @@ static void ptn5150_irq_work(struct work_struct *work)
 	int ret = 0;
 	unsigned int int_status;
 
-	if (!info->edev)
-		return;
-
-	mutex_lock(&info->mutex);
-
 	/* Clear interrupt. Read would clear the register */
 	ret = regmap_read(info->regmap, PTN5150_REG_INT_STATUS, &int_status);
 	if (ret) {
 		dev_err(info->dev, "failed to read INT STATUS %d\n", ret);
-		mutex_unlock(&info->mutex);
 		return;
 	}
 
@@ -188,14 +181,9 @@ static void ptn5150_irq_work(struct work_struct *work)
 	/* Clear interrupt. Read would clear the register */
 	ret = regmap_read(info->regmap, PTN5150_REG_INT_REG_STATUS,
 			&int_status);
-	if (ret) {
+	if (ret)
 		dev_err(info->dev,
 			"failed to read INT REG STATUS %d\n", ret);
-		mutex_unlock(&info->mutex);
-		return;
-	}
-
-	mutex_unlock(&info->mutex);
 }
 
 
@@ -281,8 +269,6 @@ static int ptn5150_i2c_probe(struct i2c_client *i2c)
 		}
 	}
 
-	mutex_init(&info->mutex);
-
 	INIT_WORK(&info->irq_work, ptn5150_irq_work);
 
 	info->regmap = devm_regmap_init_i2c(i2c, &ptn5150_regmap_config);
@@ -307,16 +293,6 @@ static int ptn5150_i2c_probe(struct i2c_client *i2c)
 		}
 	}
 
-	ret = devm_request_threaded_irq(dev, info->irq, NULL,
-					ptn5150_irq_handler,
-					IRQF_TRIGGER_FALLING |
-					IRQF_ONESHOT,
-					i2c->name, info);
-	if (ret < 0) {
-		dev_err(dev, "failed to request handler for INTB IRQ\n");
-		return ret;
-	}
-
 	/* Allocate extcon device */
 	info->edev = devm_extcon_dev_allocate(info->dev, ptn5150_extcon_cable);
 	if (IS_ERR(info->edev)) {
@@ -366,9 +342,17 @@ static int ptn5150_i2c_probe(struct i2c_client *i2c)
 	 * Update current extcon state if for example OTG connection was there
 	 * before the probe
 	 */
-	mutex_lock(&info->mutex);
 	ptn5150_check_state(info);
-	mutex_unlock(&info->mutex);
+
+	ret = devm_request_threaded_irq(dev, info->irq, NULL,
+					ptn5150_irq_handler,
+					IRQF_TRIGGER_FALLING |
+					IRQF_ONESHOT,
+					i2c->name, info);
+	if (ret < 0) {
+		dev_err(dev, "failed to request handler for INTB IRQ\n");
+		return ret;
+	}
 
 	return 0;
 }
-- 
2.52.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ