On Mon, Sep 28, 2026 at 07:26:48PM +0400, [email protected] wrote:
> From: Marc-AndrĂ© Lureau <[email protected]>
> 
> When the host chardev disconnects while the output queue is throttled,
> virtio_serial_close() calls discard_throttle_data() which detaches the
> in-flight element with virtqueue_detach_element(). This silently removes
> the descriptor without placing it on the used ring, so the guest never
> sees the write complete and the descriptor leaks.
> 
> Add return_throttle_data(), which pushes the element back via
> virtqueue_push() instead of detaching it, and call it from
> virtio_serial_close().

Thanks for fixing this!
> 
> Fixes: d4c19cdeeb2f ("virtio-serial: add missing virtio_detach_element() 
> call")
> Signed-off-by: Marc-AndrĂ© Lureau <[email protected]>
> ---
>  hw/char/virtio-serial-bus.c | 16 +++++++++++++++-
>  1 file changed, 15 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c
> index 623e9f17a83e..008cad1b625c 100644
> --- a/hw/char/virtio-serial-bus.c
> +++ b/hw/char/virtio-serial-bus.c
> @@ -158,6 +158,20 @@ static void discard_throttle_data(VirtIOSerialPort *port)
>      }
>  }
>  
> +/*
> + * Return a partial element held back by throttling to the guest via
> + * the used ring, so the guest driver can reclaim the descriptor.
> + * Unlike discard_throttle_data() this must be used when the virtqueue
> + * stays live (port close) rather than being reset.
> + */
> +static void return_throttle_data(VirtIOSerialPort *port)
> +{
> +    if (port->elem) {
> +        virtqueue_push(port->ovq, port->elem, 0);

virtio_notify() is missing here. discard_vq_data() calls virtio_notify()
as long as the vq is set up, so in practice the guest will receive a
notification. However, this is a latent bug and the code isn't
performance-critical, so I suggest adding an explicit virtio_notify()
call to prevent future issues.

Reviewed-by: Stefan Hajnoczi <[email protected]>


Reply via email to