[PATCH] Input: ff-core - clear flush and event hooks in input_ff_destroy()

From: Nguyen Ngoc Thang

Date: Sat Oct 17 2026 - 01:33:27 EST


input_ff_create() installs input_ff_flush() and input_ff_event() in the
input device, but input_ff_destroy() only clears EV_FF and frees dev->ff,
leaving both hooks dangling.

Callers use input_ff_destroy() in their probe error paths, after which
the input device is still registered. Closing an evdev node then reaches
input_flush_device() -> dev->flush() -> input_ff_flush(), which takes
ff->mutex through the now NULL dev->ff:

Oops: general protection fault, probably for non-canonical address 0xdffffc0000000015
KASAN: null-ptr-deref in range [0x00000000000000a8-0x00000000000000af]
RIP: 0010:__mutex_lock+0x149/0x1550
input_ff_flush+0x5e/0x170 drivers/input/ff-core.c:231
input_flush_device+0xd6/0x130 drivers/input/input.c:685
evdev_release+0xda/0x7f0 drivers/input/evdev.c:440

This is reachable with hid-logitech-hidpp, where hidpp_ff_init() calls
input_ff_destroy() when a later allocation fails.

Reset the hooks in input_ff_destroy(), but only if they are still the
ones installed by input_ff_create(), so that a driver-provided handler
is left alone.

Reported-by: syzbot+788733b16e87faa63deb@xxxxxxxxxxxxxxxxxxxxxxxxx
Closes: https://syzkaller.appspot.com/bug?extid=788733b16e87faa63deb
Fixes: 509ca1a93836 ("Input: implement new force feedback interface")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Nguyen Ngoc Thang <ngocthang2710.1999@xxxxxxxxx>
---
Reproduced in QEMU (7.3-rc5, KASAN) with the syzbot raw-gadget reproducer:
GPF in input_ff_flush() on the first evdev close after hidpp_ff_init()
fails past input_ff_create(); with this patch 392 evdev open/close cycles
are clean. (The emulated G920 does not answer every HID++ command, so the
allocation failure was forced with a temporary local hack.)

An alternative is to test EV_FF in input_ff_flush() as in the syzbot test
patch from matheus.aalmeida@xxxxxxxxxxxx; I prefer fixing the stale hooks
at the source so that flush and event stay consistent.

drivers/input/ff-core.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/drivers/input/ff-core.c b/drivers/input/ff-core.c
index 0e5d1d1ceb46..086a6ddf2b5f 100644
--- a/drivers/input/ff-core.c
+++ b/drivers/input/ff-core.c
@@ -345,6 +345,10 @@ void input_ff_destroy(struct input_dev *dev)
struct ff_device *ff = dev->ff;

__clear_bit(EV_FF, dev->evbit);
+ if (dev->flush == input_ff_flush)
+ dev->flush = NULL;
+ if (dev->event == input_ff_event)
+ dev->event = NULL;
if (ff) {
if (ff->destroy)
ff->destroy(ff);
--
2.43.0