Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [High] The probe function `universal_pidff_probe()` fails to call `hid_hw_stop()` when `hid_pidff_init_with_quirks()` returns an error, leading to leaked HID resources and an exploitable Use-After-Free.
- [High] Race condition in `hid_pidff_init_with_quirks` leading to a NULL pointer dereference when a malicious userspace process calls the `EVIOCSFF` ioctl between `input_ff_create()` and callback assignment.
--
--- Patch [1]: [PATCH] HID: pidff: fix OOB write when hid->inputs is empty ---
commit 3acaf40e184c8c11b91d10a3096b1beb8e9b142b
Author: Baul Lee <[email protected]>
HID: pidff: fix OOB write when hid->inputs is empty
This commit fixes an out-of-bounds write in hid_pidff_init_with_quirks()
by ensuring that the hid->inputs list is not empty before accessing it.
If the list is empty, the function now returns -ENODEV.
> Check for an empty list before deriving dev and return -ENODEV, as the
> other HID force-feedback drivers already do. universal_pidff_probe()
> propagates the error and unwinds.
[Severity: High]
This isn't a bug introduced by this patch, but does universal_pidff_probe()
actually fully unwind here?
Looking at universal_pidff_probe() in drivers/hid/hid-universal-pidff.c:
error = init_function(hdev, id->driver_data);
if (error) {
hid_warn(hdev, "Error initialising force feedback\n");
goto err;
}
...
err:
return error;
This error path propagates the initialization error but misses the necessary
hid_hw_stop() call to unwind hid_hw_start(). If universal_pidff_probe()
fails during force feedback initialization, it returns an error without
unwinding hid_hw_start().
This leaves the hidraw and hidinput structures registered but pointing to a
soon-to-be-driverless hid_device. When the physical device is unplugged,
the core skips calling hid_hw_stop() because hdev->driver is NULL.
Could this lead to an exploitable use-after-free condition if a local user
plugs in an untrusted USB device to trigger this -ENODEV return, and then
accesses the lingering /dev/hidrawX node?
> diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
> index 5f4395f7c6458..22951b7ecd174 100644
> --- a/drivers/hid/usbhid/hid-pidff.c
> +++ b/drivers/hid/usbhid/hid-pidff.c
> @@ -1539,13 +1539,20 @@ static int pidff_check_autocenter(struct pidff_device *pidff,
> int hid_pidff_init_with_quirks(struct hid_device *hid, u32 initial_quirks)
> {
> struct pidff_device *pidff;
> - struct hid_input *hidinput =
> - list_entry(hid->inputs.next, struct hid_input, list);
> - struct input_dev *dev = hidinput->input;
> + struct hid_input *hidinput;
> + struct input_dev *dev;
> struct ff_device *ff;
> int max_effects;
> int error;
>
> + if (list_empty(&hid->inputs)) {
> + hid_err(hid, "no inputs found\n");
> + return -ENODEV;
> + }
> +
> + hidinput = list_first_entry(&hid->inputs, struct hid_input, list);
> + dev = hidinput->input;
> +
[Severity: High]
This isn't a bug introduced by this patch, but is there a race condition
further down in this function during force feedback initialization?
The input device is already fully registered and visible to userspace (via
hidinput_connect()) before hid_pidff_init_with_quirks() is called. When
input_ff_create() is invoked later in this function, it sets the EV_FF bit
on the device and assigns dev->ff.
Immediately after it returns, but before ff->upload and other callbacks are
initialized, a userspace process can open the input node and issue an
EVIOCSFF ioctl:
error = input_ff_create(dev, max_effects);
if (error)
goto fail;
ff = dev->ff;
ff->private = pidff;
ff->upload = pidff_upload_effect;
Could a local unprivileged user trigger a null pointer dereference by
rapidly issuing ioctls on the newly created /dev/input/eventX node, causing
input_ff_upload() to invoke a null ff->upload function pointer?
--
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.