All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Derek J. Clark" <derekjohn.clark@gmail.com>
Cc: linux-input@vger.kernel.org, dmitry.torokhov@gmail.com
Subject: Re: [PATCH v12 3/4] HID: hid-msi: Add RGB control interface
Date: Tue, 14 Jul 2026 10:42:19 +0000	[thread overview]
Message-ID: <20260714104219.AEAE31F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260714102640.18075-4-derekjohn.clark@gmail.com>

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] The `rgb_queue` delayed work accesses a freed device pointer `led_cdev.dev` on its error path due to incorrect teardown order in `claw_remove`.
- [High] Missing cancellation of `cfg_setup` and `cfg_resume` delayed works in `claw_remove()`.
- [Medium] RGB configuration states and LED class properties are modified and read concurrently without proper synchronization.
--

--- Patch [3]: [PATCH v12 3/4] HID: hid-msi: Add RGB control interface ---
commit 2d837d4907cf2b48e7866a46da8d35b754a9f9a6
Author: Derek J. Clark <derekjohn.clark@gmail.com>

HID: hid-msi: Add RGB control interface

Adds RGB control interface for MSI Claw devices. The MSI Claw uses a
fairly unique RGB interface. It has 9 total zones (4 per joystick ring
and 1 for the ABXY buttons), and supports up to 8 sequential frames of
RGB zone data.

Link: https://patch.msgid.link/20260529072111.7565-4-derekjohn.clark@gmail.com

> diff --git a/drivers/hid/hid-msi.c b/drivers/hid/hid-msi.c
> index 9d3249fa50291..ddb64adb08b9c 100644
> --- a/drivers/hid/hid-msi.c
> +++ b/drivers/hid/hid-msi.c
> @@ -406,6 +406,38 @@ static int claw_profile_event(struct claw_drvdata *drvdata, struct claw_command_
>  		for (i = 0; i < CLAW_KEYS_MAX; i++)
>  			codes[i] = (mkeys->codes[i]);
>  		break;
> +	case CLAW_RGB_PENDING:
> +		frame = (struct claw_rgb_report *)cmd_rep->data;
> +		rgb_addr = drvdata->rgb_addr;
> +		read_addr = be16_to_cpu(frame->read_addr);
> +
> +		if (read_addr < drvdata->rgb_addr)
> +			return -EAGAIN;
> +
> +		frame_calc = (read_addr - rgb_addr) / CLAW_RGB_FRAME_OFFSET;
> +		if (frame_calc >= CLAW_RGB_MAX_FRAMES) {
> +			dev_err(&drvdata->hdev->dev, "Got unsupported frame index: %x\n",
> +				frame_calc);
> +			return -EAGAIN;
> +		}
> +		f_idx = frame_calc;
> +
> +		scoped_guard(spinlock_irqsave, &drvdata->frame_lock) {
> +			memcpy(&drvdata->rgb_frames[f_idx], &frame->zone_data,
> +			       sizeof(struct rgb_frame));
> +
> +			/* Only use frame 0 for remaining variable assignment */
> +			if (f_idx != 0)
> +				break;
> +
> +			drvdata->rgb_speed = frame->speed;
> +			drvdata->led_mc.led_cdev.brightness = frame->brightness;

[Severity: Medium]
Are there missing locks around rgb_speed and led_cdev.brightness?

Here in claw_profile_event(), drvdata->rgb_speed and
drvdata->led_mc.led_cdev.brightness are written to under the frame_lock.
However, they appear to be read locklessly in claw_write_rgb_state() outside
of frame_lock. Similarly, speed_store() modifies drvdata->rgb_speed locklessly
from userspace.

Could this inconsistent locking lead to torn reads or data races between
sysfs operations, hardware events, and the workqueue?

[ ... ]

> +static void claw_rgb_queue_fn(struct work_struct *work)
> +{
> +	struct delayed_work *dwork = container_of(work, struct delayed_work, work);
> +	struct claw_drvdata *drvdata = container_of(dwork, struct claw_drvdata, rgb_queue);
> +	int ret;
> +
> +	if (!drvdata)
> +		return;
> +
> +	scoped_guard(spinlock_irqsave, &drvdata->registration_lock) {
> +		/* Pairs with smp_store_release from cfg_setup_fn in system_wq context */
> +		if (!smp_load_acquire(&drvdata->rgb_registered))
> +			return;
> +	}
> +
> +	ret = claw_apply_rgb_state(drvdata);
> +	if (ret)
> +		dev_err(drvdata->led_mc.led_cdev.dev,
> +			"Failed to apply RGB state: %d\n", ret);

[Severity: High]
Could this dev_err() access a freed device pointer?

If claw_rgb_queue_fn() starts executing and passes the rgb_registered check,
but the device is concurrently removed, claw_remove() will set rgb_registered
to false and call led_classdev_multicolor_unregister(). This drops the final
reference and frees led_cdev.dev.

If claw_apply_rgb_state() subsequently fails, this error path will log using
drvdata->led_mc.led_cdev.dev, which might trigger a use-after-free since the
work was not canceled prior to unregistration.

[ ... ]

> @@ -1084,6 +1721,7 @@ static void claw_remove(struct hid_device *hdev)
>  {
>  	struct claw_drvdata *drvdata = hid_get_drvdata(hdev);
>  	bool gp_registered;
> +	bool rgb_registered;
>  
>  	if (!drvdata)
>  		return;
> @@ -1096,11 +1734,21 @@ static void claw_remove(struct hid_device *hdev)
>  		gp_registered = smp_load_acquire(&drvdata->gp_registered);
>  		/* Pairs with smp_load_acquire in attribute show/store functions */
>  		smp_store_release(&drvdata->gp_registered, false);
> +		/* Pairs with smp_store_release from cfg_setup_fn in system_wq context */
> +		rgb_registered = smp_load_acquire(&drvdata->rgb_registered);
> +		/* Pairs with smp_load_acquire in attribute show/store functions */
> +		smp_store_release(&drvdata->rgb_registered, false);
>  	}
>  
>  	if (gp_registered)
>  		device_remove_group(&hdev->dev, &claw_gamepad_attr_group);
>  
> +	if (rgb_registered) {
> +		device_remove_group(drvdata->led_mc.led_cdev.dev, &claw_rgb_attr_group);
> +		led_classdev_multicolor_unregister(&drvdata->led_mc);
> +	}
> +	cancel_delayed_work_sync(&drvdata->rgb_queue);

[Severity: High]
Should cancel_delayed_work_sync() for rgb_queue happen before
led_classdev_multicolor_unregister()?

Canceling the work after unregistering the LED device creates a window
where the executing work can access freed led_cdev.dev memory (as noted
in claw_rgb_queue_fn).

>  	hid_hw_close(hdev);
>  }

[Severity: High]
Are we missing the cancellation of the cfg_setup and cfg_resume delayed works?

The driver schedules cfg_setup and cfg_resume, but does not seem to explicitly
cancel them here in claw_remove(). If the device is disconnected while either
work is pending, could they execute after drvdata has been freed by devres,
resulting in a use-after-free?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260714102640.18075-1-derekjohn.clark@gmail.com?part=3

  reply	other threads:[~2026-07-14 10:42 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-14 10:26 [PATCH v12 0/4] Add MSI Claw HID Configuration Driver Derek J. Clark
2026-07-14 10:26 ` [PATCH v12 1/4] HID: hid-msi: Add MSI Claw configuration driver Derek J. Clark
2026-07-14 10:38   ` sashiko-bot
2026-07-14 10:26 ` [PATCH v12 2/4] HID: hid-msi: Add M-key mapping attributes Derek J. Clark
2026-07-14 10:44   ` sashiko-bot
2026-07-14 10:26 ` [PATCH v12 3/4] HID: hid-msi: Add RGB control interface Derek J. Clark
2026-07-14 10:42   ` sashiko-bot [this message]
2026-07-14 11:43     ` Derek J. Clark
2026-07-14 10:26 ` [PATCH v12 4/4] HID: hid-msi: Add Rumble Intensity Attributes Derek J. Clark

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260714104219.AEAE31F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=derekjohn.clark@gmail.com \
    --cc=dmitry.torokhov@gmail.com \
    --cc=linux-input@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.