[PATCH] Input: cyapa - fix missing input->mutex when calling input_device_enabled()

Ziyi Guo posted 1 patch 6 days, 12 hours ago
drivers/input/mouse/cyapa.c | 27 ++++++++++++++++++++++++---
1 file changed, 24 insertions(+), 3 deletions(-)
[PATCH] Input: cyapa - fix missing input->mutex when calling input_device_enabled()
Posted by Ziyi Guo 6 days, 12 hours ago
cyapa_enable_irq_for_cmd()/cyapa_disable_irq_for_cmd() and
cyapa_reinitialize call input_device_enabled() without holding
input->mutex. However, input_device_enabled() has
lockdep_assert_held(&dev->mutex).

Add mutex_lock()/mutex_unlock() around the input_device_enabled()
call to properly protect access to the input device state.

Signed-off-by: Ziyi Guo <n7l8m4@u.northwestern.edu>
---
 drivers/input/mouse/cyapa.c | 27 ++++++++++++++++++++++++---
 1 file changed, 24 insertions(+), 3 deletions(-)

diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c
index 00c87c0532a6..e5fe3b8b6548 100644
--- a/drivers/input/mouse/cyapa.c
+++ b/drivers/input/mouse/cyapa.c
@@ -525,8 +525,15 @@ static int cyapa_create_input_dev(struct cyapa *cyapa)
 static void cyapa_enable_irq_for_cmd(struct cyapa *cyapa)
 {
 	struct input_dev *input = cyapa->input;
+	bool input_enabled = false;
 
-	if (!input || !input_device_enabled(input)) {
+	if (input) {
+		mutex_lock(&input->mutex);
+		input_enabled = input_device_enabled(input);
+		mutex_unlock(&input->mutex);
+	}
+
+	if (!input || !input_enabled) {
 		/*
 		 * When input is NULL, TP must be in deep sleep mode.
 		 * In this mode, later non-power I2C command will always failed
@@ -545,8 +552,15 @@ static void cyapa_enable_irq_for_cmd(struct cyapa *cyapa)
 static void cyapa_disable_irq_for_cmd(struct cyapa *cyapa)
 {
 	struct input_dev *input = cyapa->input;
+	bool input_enabled = false;
+
+	if (input) {
+		mutex_lock(&input->mutex);
+		input_enabled = input_device_enabled(input);
+		mutex_unlock(&input->mutex);
+	}
 
-	if (!input || !input_device_enabled(input)) {
+	if (!input || !input_enabled) {
 		if (cyapa->gen >= CYAPA_GEN5)
 			disable_irq(cyapa->client->irq);
 		if (!input || cyapa->operational)
@@ -628,6 +642,7 @@ static int cyapa_reinitialize(struct cyapa *cyapa)
 {
 	struct device *dev = &cyapa->client->dev;
 	struct input_dev *input = cyapa->input;
+	bool input_enabled = false;
 	int error;
 
 	if (pm_runtime_enabled(dev))
@@ -652,7 +667,13 @@ static int cyapa_reinitialize(struct cyapa *cyapa)
 	}
 
 out:
-	if (!input || !input_device_enabled(input)) {
+	if (input) {
+		mutex_lock(&input->mutex);
+		input_enabled = input_device_enabled(input);
+		mutex_unlock(&input->mutex);
+	}
+
+	if (!input || !input_enabled) {
 		/* Reset to power OFF state to save power when no user open. */
 		if (cyapa->operational)
 			cyapa->ops->set_power_mode(cyapa,
-- 
2.34.1
Re: [PATCH] Input: cyapa - fix missing input->mutex when calling input_device_enabled()
Posted by Dmitry Torokhov 6 days ago
Hi Ziyi,

On Mon, Feb 02, 2026 at 10:02:23PM +0000, Ziyi Guo wrote:
> cyapa_enable_irq_for_cmd()/cyapa_disable_irq_for_cmd() and
> cyapa_reinitialize call input_device_enabled() without holding
> input->mutex. However, input_device_enabled() has
> lockdep_assert_held(&dev->mutex).
> 
> Add mutex_lock()/mutex_unlock() around the input_device_enabled()
> call to properly protect access to the input device state.
> 
> Signed-off-by: Ziyi Guo <n7l8m4@u.northwestern.edu>
> ---
>  drivers/input/mouse/cyapa.c | 27 ++++++++++++++++++++++++---
>  1 file changed, 24 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c
> index 00c87c0532a6..e5fe3b8b6548 100644
> --- a/drivers/input/mouse/cyapa.c
> +++ b/drivers/input/mouse/cyapa.c
> @@ -525,8 +525,15 @@ static int cyapa_create_input_dev(struct cyapa *cyapa)
>  static void cyapa_enable_irq_for_cmd(struct cyapa *cyapa)
>  {
>  	struct input_dev *input = cyapa->input;
> +	bool input_enabled = false;
>  
> -	if (!input || !input_device_enabled(input)) {
> +	if (input) {
> +		mutex_lock(&input->mutex);
> +		input_enabled = input_device_enabled(input);
> +		mutex_unlock(&input->mutex);

This solves absolutely nothing. The value of input_enabled becomes stale
the very moment you release the mutex.

The driver requires much more through conversion to handle potential
races with opening and closing the input device.

Thanks.

-- 
Dmitry
Re: [PATCH] Input: cyapa - fix missing input->mutex when calling input_device_enabled()
Posted by Ziyi Guo 3 hours ago
On Tue, Feb 3, 2026 at 3:52 AM Dmitry Torokhov
<dmitry.torokhov@gmail.com> wrote:
>
> The driver requires much more through conversion to handle potential
> races with opening and closing the input device.
>
> Thanks.
>
> --
> Dmitry

Hi Dmitry,

Thank you for your time and comments.

How about we go with an alternative approach, add a bool input_opened
field to struct cyapa, set it in cyapa_open() and clear it in
cyapa_close(), then replace input_device_enabled(input) with
cyapa->input_opened.

I guess this work because

- The input core calls dev->open() exactly when input_device_enabled()
transitions to true (first user open, uninhibit with users), and
dev->close()
   exactly when it transitions to false (last user close, inhibit with
users). So the flag mirrors input_device_enabled().

- cyapa_open() and cyapa_close() both hold state_sync_lock when
setting the flag. All callers of cyapa_enable_irq_for_cmd(),
cyapa_disable_irq_for_cmd(), and cyapa_reinitialize() that can
  reach the flag also hold state_sync_lock, so the check and the
subsequent action (power mode change, IRQ enable/disable) are atomic,
no TOCTOU window.

Thank you again!