drivers/misc/mei/vsc-tp.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
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
> 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
© 2016 - 2026 Red Hat, Inc.