Linux Input/HID development
 help / color / mirror / Atom feed
From: Benjamin Tissoires <bentiss@kernel.org>
To: sashiko-reviews@lists.linux.dev
Cc: Louis Clinckx <clinckx.louis@gmail.com>,
	linux-input@vger.kernel.org,  dmitry.torokhov@gmail.com
Subject: Re: [PATCH v2 1/2] HID: lenovo-go: reject non-USB transports in probe
Date: Thu, 21 May 2026 17:22:15 +0200	[thread overview]
Message-ID: <ag8ixPNLTlEpc9_c@beelink> (raw)
In-Reply-To: <20260515152059.D38D6C2BCB0@smtp.kernel.org>

On May 15 2026, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 6 potential issue(s) to consider:
> - [High] This problem wasn't introduced by this patch, but both drivers use a static global variable (`drvdata`) to store device state rather than allocating it per-device.
> - [High] This problem wasn't introduced by this patch, but multicolor LED configuration structs (`go_cdev_rgb` and `gos_cdev_rgb`) are declared as static global variables but are passed to `devm_led_classdev_multicolor_register()`.
> - [High] This problem wasn't introduced by this patch, but in `hid-lenovo-go.c`, the removal function `hid_go_cfg_remove()` fails to cancel the delayed workqueue `go_cfg_setup`.
> - [High] This problem wasn't introduced by this patch, but probe failures do not correctly unwind started hardware states and sysfs groups.
> - [High] This problem wasn't introduced by this patch, but a NULL pointer is passed to `memcpy` in `mcu_property_out()` when performing `GET_*` property requests.
> - [High] This problem wasn't introduced by this patch, but completion synchronization is broken in `mcu_property_out()` due to incorrect placement of `reinit_completion()`.
> --
> 
> commit 7a455849d3633575795dff10836095e31a4bbca3
> Author: Louis Clinckx <clinckx.louis@gmail.com>
> 
> HID: lenovo-go: reject non-USB transports in probe
> 
> These drivers only match HID_USB_DEVICE() entries and assume the
> underlying bus is USB. Make that explicit at probe by rejecting any
> non-USB hdev.
> 
> > diff --git a/drivers/hid/hid-lenovo-go-s.c b/drivers/hid/hid-lenovo-go-s.c
> > index 01c7bdd4fbe04..abf477e680428 100644
> > --- a/drivers/hid/hid-lenovo-go-s.c
> > +++ b/drivers/hid/hid-lenovo-go-s.c
> > @@ -1432,6 +1432,9 @@ static int hid_gos_probe(struct hid_device *hdev,
> >  {
> >  	int ret, ep;
> >  
> > +	if (!hid_is_usb(hdev))
> > +		return -EINVAL;
> > +
> 
> [ ... ]
> 
> >  	ret = hid_gos_cfg_probe(hdev, id);
> >  	if (ret)
> >  		dev_err_probe(&hdev->dev, ret, "Failed to start configuration interface");
> 
> This isn't a regression from this patch, but do these probe failures
> leave the hardware state active?
> 
> If hid_gos_cfg_probe() fails, the code returns the error immediately without
> calling hid_hw_close(hdev) and hid_hw_stop(hdev).
> 
> Additionally, does sysfs_create_groups() need to be rolled back if later
> steps in the config probe fail?
> 
> >  	dev_dbg(&hdev->dev, "Started interface %x as Go S configuration interface\n", ep);
> >  	return ret;
> >  }
> 
> [ ... ]
> 
> > diff --git a/drivers/hid/hid-lenovo-go.c b/drivers/hid/hid-lenovo-go.c
> > index d4d26c7833563..3fa1fe83f7e5e 100644
> > --- a/drivers/hid/hid-lenovo-go.c
> > +++ b/drivers/hid/hid-lenovo-go.c
> > @@ -2419,6 +2419,9 @@ static int hid_go_probe(struct hid_device *hdev, const struct hid_device_id *id)
> >  {
> >  	int ret, ep;
> >  
> > +	if (!hid_is_usb(hdev))
> > +		return -EINVAL;
> > +
> 
> [ ... ]
> 
> >  	ret = hid_go_cfg_probe(hdev, id);
> >  	if (ret)
> >  		dev_err_probe(&hdev->dev, ret, "Failed to start configuration interface\n");
> 
> This isn't a regression from this patch, but does this early return
> bypass hid_hw_close(hdev) and hid_hw_stop(hdev) as well?
> 
> >  	dev_dbg(&hdev->dev, "Started Legion Go HID Device: %x\n", ep);
> >  
> >  	return ret;
> >  }
> 
> [ ... ]
> 
> This isn't a regression from this patch, but does the use of a static
> global drvdata struct cause data races when multiple devices are connected?

I suspect this is relatively safe because of the nature of the device: a
handled one so the chances that 2 USB devices using the same driver are
low, but it would be nice to address sashiko's comments in a followup
series. Derek, could you have a depper look, please?

Cheers,
Benjamin

> 
> Since drvdata is shared, functions like mutex_init() and init_completion()
> called during probe() would re-execute on the same memory space. Could this
> cause type confusion over drvdata.hdev and memory corruption from concurrent
> sysfs accesses or input events?
> 
> This isn't a regression from this patch, but do the static global
> go_cdev_rgb and gos_cdev_rgb structs corrupt the kernel's global leds_list?
> 
> The led framework embeds a struct list_head into the led_classdev structure.
> If devm_led_classdev_multicolor_register() is called for multiple devices
> using the same static struct, it would double-add the list node.
> 
> Would unbinding one device then unlink the shared struct, leading to a
> use-after-free when the other device is later accessed or removed?
> 
> This isn't a regression from this patch, but does hid_go_cfg_remove()
> need to cancel the go_cfg_setup delayed workqueue?
> 
> If the controller is rapidly unplugged after hid_go_cfg_probe() schedules
> drvdata.go_cfg_setup, hid_go_cfg_remove() will tear down the device.
> Without calling cancel_delayed_work_sync(), could the workqueue execute
> and dereference the freed hdev pointer in mcu_property_out()?
> 
> This isn't a regression from this patch, but does mcu_property_out() pass
> a NULL pointer to memcpy() during get property commands?
> 
> Callers intentionally pass NULL as the data pointer and 0 as len for these
> commands. Since passing NULL to memcpy() is undefined behavior even when
> len is 0, could this trigger sanitizer violations?
> 
> This isn't a regression from this patch, but is the completion
> synchronization in mcu_property_out() susceptible to spontaneous hardware
> events?
> 
> Because reinit_completion() is called at the end of mcu_property_out(), if
> hid_go_raw_event() invokes complete() due to spontaneous events or multiple
> responses, the completion object could be left in a signaled state.
> 
> Would the next call to wait_for_completion_interruptible_timeout() then
> return instantly and provide stale or uninitialized memory to user-space?
> 
> -- 
> Sashiko AI review · https://sashiko.dev/#/patchset/cover.1778701376.git.clinckx.louis@gmail.com?part=1
> 

  reply	other threads:[~2026-05-21 15:22 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-15 14:57 [PATCH v2 0/2] HID: lenovo-go: clean up USB assumption Louis Clinckx
2026-05-15 14:57 ` [PATCH v2 1/2] HID: lenovo-go: reject non-USB transports in probe Louis Clinckx
2026-05-15 15:20   ` sashiko-bot
2026-05-21 15:22     ` Benjamin Tissoires [this message]
2026-05-15 14:57 ` [PATCH v2 2/2] HID: lenovo-go: drop dead NULL check on to_usb_interface() Louis Clinckx
2026-05-15 15:36   ` sashiko-bot
2026-05-15 16:11 ` [PATCH v2 0/2] HID: lenovo-go: clean up USB assumption Derek J. Clark
2026-05-21 15:23 ` Benjamin Tissoires

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=ag8ixPNLTlEpc9_c@beelink \
    --to=bentiss@kernel.org \
    --cc=clinckx.louis@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox