From: sashiko-bot@kernel.org
To: "Vicki Pfau" <vi@endrift.com>
Cc: linux-input@vger.kernel.org, dmitry.torokhov@gmail.com
Subject: Re: [PATCH v5 05/11] HID: steam: Coalesce rumble packets
Date: Thu, 30 Jul 2026 04:33:46 +0000 [thread overview]
Message-ID: <20260730043346.84BD01F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260730041251.1659029-6-vi@endrift.com>
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
New issues:
- [High] Dynamic device unregistration fails to cancel `coalesce_rumble_work`, causing an infinite loop and resource leak.
- [Medium] Lockless `delayed_work_pending()` check bypasses rate limiting, causing haptic reset bugs.
Pre-existing issues:
- [High] Teardown order in `steam_remove()` causes Use-After-Free by cancelling work items before unregistering the input device.
--
--- Patch [5]: [PATCH v5 05/11] HID: steam: Coalesce rumble packets ---
commit d8418fccc5859b59417d02482c0b768383aa61ef
Author: Vicki Pfau <vi@endrift.com>
HID: steam: Coalesce rumble packets
This commit introduces a 20Hz rate limit for rumble packets sent to the Steam
Deck to prevent the hardware from resetting haptic patterns on every packet.
It implements this rate limiting by using a delayed work queue to coalesce
rumble updates.
> diff --git a/drivers/hid/hid-steam.c b/drivers/hid/hid-steam.c
> --- a/drivers/hid/hid-steam.c
> +++ b/drivers/hid/hid-steam.c
[ ... ]
> @@ -603,10 +604,24 @@ static void steam_haptic_rumble_cb(struct work_struct *work)
> {
> struct steam_device *steam = container_of(work, struct steam_device,
> rumble_work);
> +
> steam_haptic_rumble(steam, 0, steam->rumble_left,
> steam->rumble_right, 2, 0);
> }
>
> +static void steam_coalesce_rumble_cb(struct work_struct *work)
> +{
> + struct steam_device *steam = container_of(to_delayed_work(work),
> + struct steam_device,
> + coalesce_rumble_work);
> +
> + steam_haptic_rumble(steam, 0, steam->rumble_left,
> + steam->rumble_right, 2, 0);
> +
> + if (steam->rumble_left || steam->rumble_right)
> + schedule_delayed_work(&steam->coalesce_rumble_work, HZ / 20);
> +}
[Severity: High]
Will this work item reschedule itself indefinitely if the device is dynamically
unregistered while a haptic effect is playing?
When the device is dynamically unregistered, such as during a wireless
disconnect or a mode switch, steam_unregister() destroys the input device
via steam_input_unregister().
However, steam_unregister() does not cancel coalesce_rumble_work, and the
input core does not proactively clear the rumble_left and rumble_right
magnitudes when an input device is destroyed. Because the input device is
gone, userspace can never send a 0-magnitude effect to stop the rumble,
leaving this worker to loop indefinitely every 50ms and leak CPU cycles
and USB bandwidth.
> +
> #ifdef CONFIG_STEAM_FF
> static int steam_play_effect(struct input_dev *dev, void *data,
> struct ff_effect *effect)
> @@ -616,6 +631,14 @@ static int steam_play_effect(struct input_dev *dev, void *data,
> steam->rumble_left = effect->u.rumble.strong_magnitude;
> steam->rumble_right = effect->u.rumble.weak_magnitude;
>
> + /*
> + * The interface gets somewhat overloaded when too many rumble
> + * packets are sent in a row, so Steam throttles it to 20 Hz
> + */
> + if (delayed_work_pending(&steam->coalesce_rumble_work))
> + return 0;
> +
> + schedule_delayed_work(&steam->coalesce_rumble_work, HZ / 20);
> + return schedule_work(&steam->rumble_work);
> }
[Severity: Medium]
Could this lockless check of delayed_work_pending() defeat the intended
rate limiting?
The workqueue core clears the pending bit immediately before executing the
worker callback. Because steam_coalesce_rumble_cb() acquires a mutex and
performs synchronous USB I/O, its execution time can be relatively large.
If a userspace process updates force feedback effects while the callback is
actively executing, delayed_work_pending() will evaluate to false. This
causes steam_play_effect() to immediately queue another rumble_work, which
then executes right after the callback finishes, sending two packets
back-to-back and bypassing the 50ms throttle.
[ ... ]
> @@ -1444,6 +1469,7 @@ static void steam_remove(struct hid_device *hdev)
> cancel_delayed_work_sync(&steam->mode_switch);
> cancel_work_sync(&steam->work_connect);
> cancel_work_sync(&steam->rumble_work);
> + cancel_delayed_work_sync(&steam->coalesce_rumble_work);
> cancel_work_sync(&steam->unregister_work);
> steam->client_hdev = NULL;
> steam->client_opened = 0;
[Severity: High]
This is a pre-existing issue, but does the teardown order in steam_remove()
allow a use-after-free?
The works are cancelled before the input device is unregistered:
steam_remove() {
...
cancel_work_sync(&steam->rumble_work);
cancel_delayed_work_sync(&steam->coalesce_rumble_work);
...
steam_unregister(steam);
}
If a userspace process continuously calls the EVIOCSFF ioctl to play
force-feedback effects while the device is being removed, the ioctl
path in steam_play_effect() can queue new rumble_work and
coalesce_rumble_work items after they have been cancelled.
Once steam_remove() completes, the devm-managed steam structure is freed,
but the newly queued work items will eventually execute and dereference
the freed memory.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260730041251.1659029-1-vi@endrift.com?part=5
next prev parent reply other threads:[~2026-07-30 4:33 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-30 4:12 [PATCH v5 00/10] HID: steam: General cleanup and improvements Vicki Pfau
2026-07-30 4:12 ` [PATCH v5 01/11] HID: steam: Update documentation Vicki Pfau
2026-07-30 4:12 ` [PATCH v5 02/11] HID: steam: Refactor and clean up report parsing Vicki Pfau
2026-07-30 4:52 ` sashiko-bot
2026-07-30 4:12 ` [PATCH v5 03/11] HID: steam: Rename some constants that got renamed upstream Vicki Pfau
2026-07-30 4:12 ` [PATCH v5 04/11] HID: steam: Add support for sensor events on the Steam Controller (2015) Vicki Pfau
2026-07-30 4:37 ` sashiko-bot
2026-07-30 4:12 ` [PATCH v5 05/11] HID: steam: Coalesce rumble packets Vicki Pfau
2026-07-30 4:33 ` sashiko-bot [this message]
2026-07-30 4:12 ` [PATCH v5 06/11] HID: steam: Fully unregister controller when hidraw is opened Vicki Pfau
2026-07-30 4:34 ` sashiko-bot
2026-07-30 4:12 ` [PATCH v5 07/11] HID: steam: Rearrange teardown sequence Vicki Pfau
2026-07-30 4:39 ` sashiko-bot
2026-07-30 4:12 ` [PATCH v5 08/11] HID: steam: Improve logging and other cleanup Vicki Pfau
2026-07-30 4:34 ` sashiko-bot
2026-07-30 4:12 ` [PATCH v5 09/11] HID: steam: Zero-initialize reply in serial lookup Vicki Pfau
2026-07-30 4:12 ` [PATCH v5 10/11] HID: steam: Reject short reads Vicki Pfau
2026-07-30 4:12 ` [PATCH v5 11/11] HID: steam: Retry send/recv reports if stale Vicki Pfau
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=20260730043346.84BD01F000E9@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=dmitry.torokhov@gmail.com \
--cc=linux-input@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=vi@endrift.com \
/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.