On Sat, Sep 05, 2026 at 05:20:58PM +0200, Karl Mehltretter wrote:
> virtinput_remove() unregisters the input device before resetting the
> virtio device. virtinput_recv_events() drops vi->lock around input_event(),
> so clearing vi->ready does not stop a callback that passed the entry check.
> It can still use vi->idev, requeue buffers and kick the queue.
> 
> Reset first, as virtinput_freeze() already does. With the preceding core
> change, reset waits for callbacks before input_unregister_device() can
> free vi->idev. Recheck vi->ready after taking the lock again: keep draining
> completed events so an input packet is not truncated, but stop requeueing
> buffers and kicking the queue.
> 
> With evdev attached, input_unregister_handle() currently waits for an RCU
> grace period, which also waits out IRQ callbacks. This masks the lifetime
> bug on PCI and MMIO, but does not protect sleepable callbacks on other
> transports.


And now I am completely confused. So it is other transports you are
worried about? Which ones did you test? And why don't you worry about
fixing other transports in 1/3?


> Fixes: 271c865161c5 ("Add virtio-input driver.")
> Assisted-by: LLM
> Signed-off-by: Karl Mehltretter <[email protected]>



> ---
>  drivers/virtio/virtio_input.c | 8 ++++++--
>  1 file changed, 6 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/virtio/virtio_input.c b/drivers/virtio/virtio_input.c
> index deec24e8e682..7b654af0a42c 100644
> --- a/drivers/virtio/virtio_input.c
> +++ b/drivers/virtio/virtio_input.c
> @@ -49,9 +49,12 @@ static void virtinput_recv_events(struct virtqueue *vq)
>                                   le16_to_cpu(event->code),
>                                   le32_to_cpu(event->value));
>                       spin_lock_irqsave(&vi->lock, flags);
> +                     if (!vi->ready)
> +                             continue;
>                       virtinput_queue_evtbuf(vi, event);
>               }
> -             virtqueue_kick(vq);
> +             if (vi->ready)
> +                     virtqueue_kick(vq);
>       }
>       spin_unlock_irqrestore(&vi->lock, flags);
>  }
> @@ -350,8 +353,9 @@ static void virtinput_remove(struct virtio_device *vdev)
>       vi->ready = false;
>       spin_unlock_irqrestore(&vi->lock, flags);
>  
> -     input_unregister_device(vi->idev);
> +     /* Callbacks use vi->idev. */
>       virtio_reset_device(vdev);
> +     input_unregister_device(vi->idev);
>       while ((buf = virtqueue_detach_unused_buf(vi->sts)) != NULL)
>               kfree(buf);
>       vdev->config->del_vqs(vdev);
> -- 
> 2.39.5 (Apple Git-154)


Reply via email to