Move try_module_get() and get_device() before input_ff_create() in hid_haptic_init(). The original order placed them after input_ff_create(), and failures went to input_free which called input_ff_destroy() without ever setting ret. The caller saw ret == 0 on failure and kept a dangling pointer to the haptic struct. With the references acquired first, all failure paths reach stop_buffer_free directly. The flush/event save/restore is no longer needed. Clear the EV_FF and FF_HAPTIC capability bits on failure so a masked error from the caller does not leave the input device advertising FF support without a dev->ff -- EVIOCGEFFECTS would NULL-deref otherwise. Fixes: 8d0bf7908b5a ("HID: multitouch: add haptic multitouch support") Cc: stable@vger.kernel.org Signed-off-by: Aldo Ariel Panzardo --- drivers/hid/hid-haptic.c | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/drivers/hid/hid-haptic.c b/drivers/hid/hid-haptic.c index 8760eeb..b8aa4bf 100644 --- a/drivers/hid/hid-haptic.c +++ b/drivers/hid/hid-haptic.c @@ -419,8 +419,6 @@ int hid_haptic_init(struct hid_device *hdev, }; const char *prefix = "hid-haptic"; char *name; - int (*flush)(struct input_dev *dev, struct file *file); - int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value); haptic->hdev = hdev; haptic->max_waveform_id = max(2u, haptic->max_waveform_id); @@ -501,12 +499,24 @@ int hid_haptic_init(struct hid_device *hdev, input_set_capability(dev, EV_FF, FF_HAPTIC); - flush = dev->flush; - event = dev->event; + if (!try_module_get(THIS_MODULE)) { + dev_err(&hdev->dev, "Failed to increase module count.\n"); + ret = -ENODEV; + goto ff_cap_clear; + } + if (!get_device(&hdev->dev)) { + dev_err(&hdev->dev, "Failed to get hdev device.\n"); + ret = -ENODEV; + module_put(THIS_MODULE); + goto ff_cap_clear; + } + ret = input_ff_create(dev, FF_MAX_EFFECTS); if (ret) { dev_err(&hdev->dev, "Failed to create ff device.\n"); - goto stop_buffer_free; + put_device(&hdev->dev); + module_put(THIS_MODULE); + goto ff_cap_clear; } ff = dev->ff; @@ -515,23 +525,11 @@ int hid_haptic_init(struct hid_device *hdev, ff->playback = hid_haptic_playback; ff->erase = hid_haptic_erase; ff->destroy = hid_haptic_destroy; - if (!try_module_get(THIS_MODULE)) { - dev_err(&hdev->dev, "Failed to increase module count.\n"); - goto input_free; - } - if (!get_device(&hdev->dev)) { - dev_err(&hdev->dev, "Failed to get hdev device.\n"); - module_put(THIS_MODULE); - goto input_free; - } return 0; -input_free: - input_ff_destroy(dev); - /* Restore dev flush and event */ - dev->flush = flush; - dev->event = event; - return ret; +ff_cap_clear: + __clear_bit(FF_HAPTIC, dev->ffbit); + __clear_bit(EV_FF, dev->evbit); stop_buffer_free: kfree(haptic->stop_effect.report_buf); haptic->stop_effect.report_buf = NULL; -- 2.53.0