Commit 4cda78d
Input: uinput - fix circular locking dependency with ff-core
A lockdep circular locking dependency warning can be triggered
reproducibly when using a force-feedback gamepad with uinput (for
example, playing ELDEN RING under Wine with a Flydigi Vader 5
controller):
ff->mutex -> udev->mutex -> input_mutex -> dev->mutex -> ff->mutex
The cycle is caused by four lock acquisition paths:
1. ff upload: input_ff_upload() holds ff->mutex and calls
uinput_dev_upload_effect() -> uinput_request_submit() ->
uinput_request_send(), which acquires udev->mutex.
2. device create: uinput_ioctl_handler() holds udev->mutex and calls
uinput_create_device() -> input_register_device(), which acquires
input_mutex.
3. device register: input_register_device() holds input_mutex and
calls kbd_connect() -> input_register_handle(), which acquires
dev->mutex.
4. evdev release: evdev_release() calls input_flush_device() under
dev->mutex, which calls input_ff_flush() acquiring ff->mutex.
Fix this by introducing a new state_lock spinlock to protect
udev->state and udev->dev access in uinput_request_send() instead of
acquiring udev->mutex. The function only needs to atomically check
device state and queue an input event into the ring buffer via
uinput_dev_event() -- both operations are safe under a spinlock
(ktime_get_ts64() and wake_up_interruptible() do not sleep). This
breaks the ff->mutex -> udev->mutex link since a spinlock is a leaf in
the lock ordering and cannot form cycles with mutexes.
To keep state transitions visible to uinput_request_send(), protect
writes to udev->state in uinput_create_device() and
uinput_destroy_device() with the same state_lock spinlock.
Additionally, move init_completion(&request->done) from
uinput_request_send() to uinput_request_submit() before
uinput_request_reserve_slot(). Once the slot is allocated,
uinput_flush_requests() may call complete() on it at any time from
the destroy path, so the completion must be initialised before the
request becomes visible.
Lock ordering after the fix:
ff->mutex -> state_lock (spinlock, leaf)
udev->mutex -> state_lock (spinlock, leaf)
udev->mutex -> input_mutex -> dev->mutex -> ff->mutex (no back-edge)
Fixes: ff46255 ("Input: uinput - switch to the new FF interface")
Cc: [email protected]
Link: https://lore.kernel.org/all/CABXGCsMoxag+kEwHhb7KqhuyxfmGGd0P=tHZyb1uKE0pLr8Hkg@mail.gmail.com/
Signed-off-by: Mikhail Gavrilov <[email protected]>
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Dmitry Torokhov <[email protected]>1 parent 0d9363a commit 4cda78d
1 file changed
Lines changed: 21 additions & 7 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
57 | 57 | | |
58 | 58 | | |
59 | 59 | | |
| 60 | + | |
60 | 61 | | |
61 | 62 | | |
62 | 63 | | |
| |||
146 | 147 | | |
147 | 148 | | |
148 | 149 | | |
149 | | - | |
| 150 | + | |
150 | 151 | | |
151 | | - | |
152 | | - | |
153 | | - | |
| 152 | + | |
154 | 153 | | |
155 | 154 | | |
156 | 155 | | |
157 | 156 | | |
158 | 157 | | |
159 | 158 | | |
160 | | - | |
161 | | - | |
162 | 159 | | |
163 | 160 | | |
164 | 161 | | |
165 | 162 | | |
166 | 163 | | |
167 | 164 | | |
168 | 165 | | |
169 | | - | |
| 166 | + | |
170 | 167 | | |
171 | 168 | | |
172 | 169 | | |
| |||
175 | 172 | | |
176 | 173 | | |
177 | 174 | | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
178 | 182 | | |
179 | 183 | | |
180 | 184 | | |
| |||
289 | 293 | | |
290 | 294 | | |
291 | 295 | | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
292 | 302 | | |
| 303 | + | |
293 | 304 | | |
294 | 305 | | |
295 | 306 | | |
| |||
366 | 377 | | |
367 | 378 | | |
368 | 379 | | |
| 380 | + | |
369 | 381 | | |
| 382 | + | |
370 | 383 | | |
371 | 384 | | |
372 | 385 | | |
| |||
384 | 397 | | |
385 | 398 | | |
386 | 399 | | |
| 400 | + | |
387 | 401 | | |
388 | 402 | | |
389 | 403 | | |
| |||
0 commit comments