]> git.proxmox.com Git - pve-qemu.git/blob - debian/patches/extra/0002-virtio-serial-fix-segfault-on-disconnect.patch
05ed7e8ad2b1a413cf78b8792454a9f1f949b5f9
[pve-qemu.git] / debian / patches / extra / 0002-virtio-serial-fix-segfault-on-disconnect.patch
1 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 From: Stefan Hajnoczi <stefanha@redhat.com>
3 Date: Fri, 2 Jun 2017 10:54:24 +0100
4 Subject: [PATCH] virtio-serial: fix segfault on disconnect
5
6 Since commit d4c19cdeeb2f1e474bc426a6da261f1d7346eb5b ("virtio-serial:
7 add missing virtio_detach_element() call") the following commands may
8 cause QEMU to segfault:
9
10 $ qemu -M accel=kvm -cpu host -m 1G \
11 -drive if=virtio,file=test.img,format=raw \
12 -device virtio-serial-pci,id=virtio-serial0 \
13 -chardev socket,id=channel1,path=/tmp/chardev.sock,server,nowait \
14 -device virtserialport,chardev=channel1,bus=virtio-serial0.0,id=port1
15 $ nc -U /tmp/chardev.sock
16 ^C
17
18 (guest)$ cat /dev/zero >/dev/vport0p1
19
20 The segfault is non-deterministic: if the event loop notices the socket
21 has been closed then there is no crash. The disconnect has to happen
22 right before QEMU attempts to write data to the socket.
23
24 The backtrace is as follows:
25
26 Thread 1 "qemu-system-x86" received signal SIGSEGV, Segmentation fault.
27 0x00005555557e0698 in do_flush_queued_data (port=0x5555582cedf0, vq=0x7fffcc854290, vdev=0x55555807b1d0) at hw/char/virtio-serial-bus.c:180
28 180 for (i = port->iov_idx; i < port->elem->out_num; i++) {
29 #1 0x000055555580d363 in virtio_queue_notify_vq (vq=0x7fffcc854290) at hw/virtio/virtio.c:1524
30 #2 0x000055555580d363 in virtio_queue_host_notifier_read (n=0x7fffcc8542f8) at hw/virtio/virtio.c:2430
31 #3 0x0000555555b3482c in aio_dispatch_handlers (ctx=ctx@entry=0x5555566b8c80) at util/aio-posix.c:399
32 #4 0x0000555555b350d8 in aio_dispatch (ctx=0x5555566b8c80) at util/aio-posix.c:430
33 #5 0x0000555555b3212e in aio_ctx_dispatch (source=<optimized out>, callback=<optimized out>, user_data=<optimized out>) at util/async.c:261
34 #6 0x00007fffde71de52 in g_main_context_dispatch () at /lib64/libglib-2.0.so.0
35 #7 0x0000555555b34353 in glib_pollfds_poll () at util/main-loop.c:213
36 #8 0x0000555555b34353 in os_host_main_loop_wait (timeout=<optimized out>) at util/main-loop.c:261
37 #9 0x0000555555b34353 in main_loop_wait (nonblocking=<optimized out>) at util/main-loop.c:517
38 #10 0x0000555555773207 in main_loop () at vl.c:1917
39 #11 0x0000555555773207 in main (argc=<optimized out>, argv=<optimized out>, envp=<optimized out>) at vl.c:4751
40
41 The do_flush_queued_data() function does not anticipate chardev close
42 events during vsc->have_data(). It expects port->elem to remain
43 non-NULL for the duration its for loop.
44
45 The fix is simply to return from do_flush_queued_data() if the port
46 closes because the close event already frees port->elem and drains the
47 virtqueue - there is nothing left for do_flush_queued_data() to do.
48
49 Reported-by: Sitong Liu <siliu@redhat.com>
50 Reported-by: Min Deng <mdeng@redhat.com>
51 Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
52 Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
53 Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
54 ---
55 hw/char/virtio-serial-bus.c | 3 +++
56 1 file changed, 3 insertions(+)
57
58 diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c
59 index aa9c11ae92..f5bc173844 100644
60 --- a/hw/char/virtio-serial-bus.c
61 +++ b/hw/char/virtio-serial-bus.c
62 @@ -186,6 +186,9 @@ static void do_flush_queued_data(VirtIOSerialPort *port, VirtQueue *vq,
63 port->elem->out_sg[i].iov_base
64 + port->iov_offset,
65 buf_size);
66 + if (!port->elem) { /* bail if we got disconnected */
67 + return;
68 + }
69 if (port->throttled) {
70 port->iov_idx = i;
71 if (ret > 0) {
72 --
73 2.11.0
74