[PATCH] mei: vsc: Initialize mutexes and event work before requesting the IRQ

Wentao Guan posted 1 patch 3 weeks, 3 days ago
drivers/misc/mei/vsc-tp.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
[PATCH] mei: vsc: Initialize mutexes and event work before requesting the IRQ
Posted by Wentao Guan 3 weeks, 3 days ago
vsc_tp_isr() schedules tp->event_work, whose handler
vsc_tp_event_work() unconditionally locks tp->event_notify_mutex, but
vsc_tp_probe() initializes both mutexes and the work item only after
request_threaded_irq() has succeeded. A pending wake interrupt during
probe can therefore schedule an uninitialized work item, which then
runs mutex_lock() on zeroed, uninitialized mutex state.

Move the mutex_init() and INIT_WORK() calls before
request_threaded_irq() and destroy the mutexes if IRQ registration
fails.

Fixes: de88b02c94db7 ("mei: vsc: Run event callback from a workqueue")
Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
---
 drivers/misc/mei/vsc-tp.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/misc/mei/vsc-tp.c b/drivers/misc/mei/vsc-tp.c
index 5ecf99883996b..e2f65e60e4892 100644
--- a/drivers/misc/mei/vsc-tp.c
+++ b/drivers/misc/mei/vsc-tp.c
@@ -496,16 +496,16 @@ static int vsc_tp_probe(struct spi_device *spi)
 	init_waitqueue_head(&tp->xfer_wait);
 	tp->spi = spi;
 
+	mutex_init(&tp->mutex);
+	mutex_init(&tp->event_notify_mutex);
+	INIT_WORK(&tp->event_work, vsc_tp_event_work);
+
 	irq_set_status_flags(spi->irq, IRQ_DISABLE_UNLAZY);
 	ret = request_threaded_irq(spi->irq, NULL, vsc_tp_isr,
 				   IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
 				   dev_name(dev), tp);
 	if (ret)
-		return ret;
-
-	mutex_init(&tp->mutex);
-	mutex_init(&tp->event_notify_mutex);
-	INIT_WORK(&tp->event_work, vsc_tp_event_work);
+		goto err_destroy_mutex;
 
 	/* only one child acpi device */
 	ret = acpi_dev_for_each_child(ACPI_COMPANION(dev),
@@ -531,6 +531,7 @@ static int vsc_tp_probe(struct spi_device *spi)
 	free_irq(spi->irq, tp);
 
 	cancel_work_sync(&tp->event_work);
+err_destroy_mutex:
 	mutex_destroy(&tp->event_notify_mutex);
 	mutex_destroy(&tp->mutex);
 
-- 
2.30.2
RE: [PATCH] mei: vsc: Initialize mutexes and event work before requesting the IRQ
Posted by Usyskin, Alexander 3 weeks, 3 days ago
> Subject: [PATCH] mei: vsc: Initialize mutexes and event work before requesting
> the IRQ
> 
> vsc_tp_isr() schedules tp->event_work, whose handler
> vsc_tp_event_work() unconditionally locks tp->event_notify_mutex, but
> vsc_tp_probe() initializes both mutexes and the work item only after
> request_threaded_irq() has succeeded. A pending wake interrupt during
> probe can therefore schedule an uninitialized work item, which then
> runs mutex_lock() on zeroed, uninitialized mutex state.
> 
> Move the mutex_init() and INIT_WORK() calls before
> request_threaded_irq() and destroy the mutexes if IRQ registration
> fails.
> 

Acked-by: Alexander Usyskin <alexander.usyskin@intel.com>

> Fixes: de88b02c94db7 ("mei: vsc: Run event callback from a workqueue")
> Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
> ---
>  drivers/misc/mei/vsc-tp.c | 11 ++++++-----
>  1 file changed, 6 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/misc/mei/vsc-tp.c b/drivers/misc/mei/vsc-tp.c
> index 5ecf99883996b..e2f65e60e4892 100644
> --- a/drivers/misc/mei/vsc-tp.c
> +++ b/drivers/misc/mei/vsc-tp.c
> @@ -496,16 +496,16 @@ static int vsc_tp_probe(struct spi_device *spi)
>  	init_waitqueue_head(&tp->xfer_wait);
>  	tp->spi = spi;
> 
> +	mutex_init(&tp->mutex);
> +	mutex_init(&tp->event_notify_mutex);
> +	INIT_WORK(&tp->event_work, vsc_tp_event_work);
> +
>  	irq_set_status_flags(spi->irq, IRQ_DISABLE_UNLAZY);
>  	ret = request_threaded_irq(spi->irq, NULL, vsc_tp_isr,
>  				   IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
>  				   dev_name(dev), tp);
>  	if (ret)
> -		return ret;
> -
> -	mutex_init(&tp->mutex);
> -	mutex_init(&tp->event_notify_mutex);
> -	INIT_WORK(&tp->event_work, vsc_tp_event_work);
> +		goto err_destroy_mutex;
> 
>  	/* only one child acpi device */
>  	ret = acpi_dev_for_each_child(ACPI_COMPANION(dev),
> @@ -531,6 +531,7 @@ static int vsc_tp_probe(struct spi_device *spi)
>  	free_irq(spi->irq, tp);
> 
>  	cancel_work_sync(&tp->event_work);
> +err_destroy_mutex:
>  	mutex_destroy(&tp->event_notify_mutex);
>  	mutex_destroy(&tp->mutex);
> 
> --
> 2.30.2