qemu-e2k/hw/char
Stefan Hajnoczi 46764fe09c virtio-serial: fix segfault on disconnect
Since commit d4c19cdeeb ("virtio-serial:
add missing virtio_detach_element() call") the following commands may
cause QEMU to segfault:

  $ qemu -M accel=kvm -cpu host -m 1G \
         -drive if=virtio,file=test.img,format=raw \
         -device virtio-serial-pci,id=virtio-serial0 \
         -chardev socket,id=channel1,path=/tmp/chardev.sock,server,nowait \
         -device virtserialport,chardev=channel1,bus=virtio-serial0.0,id=port1
  $ nc -U /tmp/chardev.sock
  ^C

  (guest)$ cat /dev/zero >/dev/vport0p1

The segfault is non-deterministic: if the event loop notices the socket
has been closed then there is no crash.  The disconnect has to happen
right before QEMU attempts to write data to the socket.

The backtrace is as follows:

  Thread 1 "qemu-system-x86" received signal SIGSEGV, Segmentation fault.
  0x00005555557e0698 in do_flush_queued_data (port=0x5555582cedf0, vq=0x7fffcc854290, vdev=0x55555807b1d0) at hw/char/virtio-serial-bus.c:180
  180           for (i = port->iov_idx; i < port->elem->out_num; i++) {
  #1  0x000055555580d363 in virtio_queue_notify_vq (vq=0x7fffcc854290) at hw/virtio/virtio.c:1524
  #2  0x000055555580d363 in virtio_queue_host_notifier_read (n=0x7fffcc8542f8) at hw/virtio/virtio.c:2430
  #3  0x0000555555b3482c in aio_dispatch_handlers (ctx=ctx@entry=0x5555566b8c80) at util/aio-posix.c:399
  #4  0x0000555555b350d8 in aio_dispatch (ctx=0x5555566b8c80) at util/aio-posix.c:430
  #5  0x0000555555b3212e in aio_ctx_dispatch (source=<optimized out>, callback=<optimized out>, user_data=<optimized out>) at util/async.c:261
  #6  0x00007fffde71de52 in g_main_context_dispatch () at /lib64/libglib-2.0.so.0
  #7  0x0000555555b34353 in glib_pollfds_poll () at util/main-loop.c:213
  #8  0x0000555555b34353 in os_host_main_loop_wait (timeout=<optimized out>) at util/main-loop.c:261
  #9  0x0000555555b34353 in main_loop_wait (nonblocking=<optimized out>) at util/main-loop.c:517
  #10 0x0000555555773207 in main_loop () at vl.c:1917
  #11 0x0000555555773207 in main (argc=<optimized out>, argv=<optimized out>, envp=<optimized out>) at vl.c:4751

The do_flush_queued_data() function does not anticipate chardev close
events during vsc->have_data().  It expects port->elem to remain
non-NULL for the duration its for loop.

The fix is simply to return from do_flush_queued_data() if the port
closes because the close event already frees port->elem and drains the
virtqueue - there is nothing left for do_flush_queued_data() to do.

Reported-by: Sitong Liu <siliu@redhat.com>
Reported-by: Min Deng <mdeng@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2017-06-02 18:57:17 +03:00
..
bcm2835_aux.c char: remove explicit_fe_open, use a set_handlers argument 2016-10-24 15:46:10 +02:00
cadence_uart.c cadence_uart: Check if receiver timeout counter is disabled 2016-12-27 14:59:23 +00:00
debugcon.c char: remove explicit_fe_open, use a set_handlers argument 2016-10-24 15:46:10 +02:00
digic-uart.c char: remove explicit_fe_open, use a set_handlers argument 2016-10-24 15:46:10 +02:00
escc.c char: rename CharDriverState Chardev 2017-01-27 18:07:59 +01:00
etraxfs_ser.c char: remove explicit_fe_open, use a set_handlers argument 2016-10-24 15:46:10 +02:00
exynos4210_uart.c hw/char/exynos4210_uart: Constify static array and few arguments 2017-04-20 17:39:17 +01:00
grlib_apbuart.c char: remove explicit_fe_open, use a set_handlers argument 2016-10-24 15:46:10 +02:00
imx_serial.c char: rename CharDriverState Chardev 2017-01-27 18:07:59 +01:00
ipoctal232.c char: remove explicit_fe_open, use a set_handlers argument 2016-10-24 15:46:10 +02:00
lm32_juart.c char: remove explicit_fe_open, use a set_handlers argument 2016-10-24 15:46:10 +02:00
lm32_uart.c char: remove explicit_fe_open, use a set_handlers argument 2016-10-24 15:46:10 +02:00
Makefile.objs s390x/3270: Mark non-migratable and enable the device 2017-05-04 10:34:37 +02:00
mcf_uart.c hw/char/mcf_uart: QOMify the ColdFire UART 2017-02-16 14:06:56 +01:00
milkymist-uart.c char: remove explicit_fe_open, use a set_handlers argument 2016-10-24 15:46:10 +02:00
omap_uart.c char: rename CharDriverState Chardev 2017-01-27 18:07:59 +01:00
parallel.c char: rename CharDriverState Chardev 2017-01-27 18:07:59 +01:00
pl011.c char: remove explicit_fe_open, use a set_handlers argument 2016-10-24 15:46:10 +02:00
sclpconsole-lm.c char: remove explicit_fe_open, use a set_handlers argument 2016-10-24 15:46:10 +02:00
sclpconsole.c char: remove explicit_fe_open, use a set_handlers argument 2016-10-24 15:46:10 +02:00
serial-isa.c char: rename CharDriverState Chardev 2017-01-27 18:07:59 +01:00
serial-pci.c include/qemu/osdep.h: Don't include qapi/error.h 2016-03-22 22:20:15 +01:00
serial.c char: rename CharDriverState Chardev 2017-01-27 18:07:59 +01:00
sh_serial.c char: rename CharDriverState Chardev 2017-01-27 18:07:59 +01:00
spapr_vty.c char: rename CharDriverState Chardev 2017-01-27 18:07:59 +01:00
stm32f2xx_usart.c char: remove explicit_fe_open, use a set_handlers argument 2016-10-24 15:46:10 +02:00
terminal3270.c s390x/3270: Mark non-migratable and enable the device 2017-05-04 10:34:37 +02:00
trace-events hw/char/pl011: Add trace events 2016-10-17 19:32:44 +01:00
virtio-console.c char: rename CharDriverState Chardev 2017-01-27 18:07:59 +01:00
virtio-serial-bus.c virtio-serial: fix segfault on disconnect 2017-06-02 18:57:17 +03:00
xen_console.c xen: Rename xen_be_send_notify 2016-10-28 17:54:21 -07:00
xilinx_uartlite.c char: remove explicit_fe_open, use a set_handlers argument 2016-10-24 15:46:10 +02:00