forked from pool/libvirt
a026aabb02
- qemu: avoid denial of service reading from QEMU guest agent CVE-2018-1064 fbf31e1a-CVE-2018-1064.patch bsc#1083625 - virtlockd: fix loosing lock on re-exec 464889ff-rpc-aquire-ref-dispatch.patch, c6f1d519-rpc-simplify-dispatch.patch, 06e7ebb6-rpc-invoke-dispatch-unlocked.patch, 86cae503-rpc-fix-pre-exec.patch, eefabb38-rpc-virtlockd-virtlogd-single-thread.patch bsc#1076861 - libvirtd: fix potential deadlock when reloading 33c6eb96-fix-libvirtd-reload-deadlock.patch bsc#1079150 OBS-URL: https://build.opensuse.org/request/show/586966 OBS-URL: https://build.opensuse.org/package/show/Virtualization/libvirt?expand=0&rev=676
116 lines
4.7 KiB
Diff
116 lines
4.7 KiB
Diff
commit 33c6eb9689eb51dfe31dd05b24b3b6b1c948c267
|
|
Author: Jim Fehlig <jfehlig@suse.com>
|
|
Date: Thu Mar 8 15:04:48 2018 -0700
|
|
|
|
libvirtd: fix potential deadlock when reloading
|
|
|
|
It is possible to deadlock libvirtd when concurrently starting a domain
|
|
and restarting the daemon. Threads involved in the deadlock are
|
|
|
|
Thread 4 (Thread 0x7fc13b53e700 (LWP 64084)):
|
|
/lib64/libpthread.so.0
|
|
at util/virthread.c:154
|
|
at qemu/qemu_monitor.c:1083
|
|
cmd=0x7fc110017700, scm_fd=-1, reply=0x7fc13b53d318) at
|
|
qemu/qemu_monitor_json.c:305
|
|
cmd=0x7fc110017700,
|
|
reply=0x7fc13b53d318) at qemu/qemu_monitor_json.c:335
|
|
at qemu/qemu_monitor_json.c:1298
|
|
at qemu/qemu_monitor.c:1697
|
|
vm=0x7fc110003d00, asyncJob=QEMU_ASYNC_JOB_START) at qemu/qemu_process.c:1763
|
|
vm=0x7fc110003d00,
|
|
asyncJob=6, logCtxt=0x7fc1100089c0) at qemu/qemu_process.c:1835
|
|
vm=0x7fc110003d00, asyncJob=6, logCtxt=0x7fc1100089c0) at
|
|
qemu/qemu_process.c:2180
|
|
driver=0x7fc12004e1e0,
|
|
vm=0x7fc110003d00, asyncJob=QEMU_ASYNC_JOB_START, incoming=0x0, snapshot=0x0,
|
|
vmop=VIR_NETDEV_VPORT_PROFILE_OP_CREATE, flags=17) at qemu/qemu_process.c:6111
|
|
driver=0x7fc12004e1e0,
|
|
vm=0x7fc110003d00, updatedCPU=0x0, asyncJob=QEMU_ASYNC_JOB_START,
|
|
migrateFrom=0x0,
|
|
migrateFd=-1, migratePath=0x0, snapshot=0x0,
|
|
vmop=VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
|
|
flags=17) at qemu/qemu_process.c:6334
|
|
xml=0x7fc110000ed0 "<!--\nWARNING: THIS IS AN AUTO-GENERATED FILE.
|
|
CHANGES TO IT ARE LIKELY TO BE\nOVERWRITTEN AND LOST. Changes to this xml
|
|
configuration should be made using:\n virsh edit testvv\nor other
|
|
applicati"..., flags=0) at qemu/qemu_driver.c:1776
|
|
...
|
|
|
|
Thread 1 (Thread 0x7fc143c66880 (LWP 64081)):
|
|
/lib64/libpthread.so.0
|
|
at util/virthread.c:122
|
|
conf/nwfilter_conf.c:159
|
|
sig=0x7ffe0a831e30,
|
|
opaque=0x0) at remote/remote_daemon.c:724
|
|
opaque=0x558c5328b230) at rpc/virnetdaemon.c:654
|
|
at util/vireventpoll.c:508
|
|
rpc/virnetdaemon.c:858
|
|
remote/remote_daemon.c:1496
|
|
(gdb) thr 1
|
|
[Switching to thread 1 (Thread 0x7fc143c66880 (LWP 64081))]
|
|
/lib64/libpthread.so.0
|
|
(gdb) f 1
|
|
at util/virthread.c:122
|
|
122 pthread_rwlock_wrlock(&m->lock);
|
|
(gdb) p updateLock
|
|
$1 = {lock = {__data = {__lock = 0, __nr_readers = 1, __readers_wakeup = 0,
|
|
__writer_wakeup = 0, __nr_readers_queued = 0, __nr_writers_queued = 1,
|
|
__writer = 0,
|
|
__shared = 0, __rwelision = 0 '\000', __pad1 = "\000\000\000\000\000\000",
|
|
__pad2 = 0, __flags = 0},
|
|
__size = "\000\000\000\000\001", '\000' <repeats 15 times>, "\001",
|
|
'\000' <repeats 34 times>, __align = 4294967296}}
|
|
|
|
Reloading of the nwfilter driver is stuck waiting for a write lock, which
|
|
already has a reader (from qemuDomainCreateXML) in the critical section.
|
|
Since the reload occurs in the context of the main event loop thread,
|
|
libvirtd becomes deadlocked. The deadlock can be avoided by offloading
|
|
the reload work to a thread.
|
|
|
|
Signed-off-by: Jim Fehlig <jfehlig@suse.com>
|
|
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
|
|
|
|
Index: libvirt-4.1.0/src/remote/remote_daemon.c
|
|
===================================================================
|
|
--- libvirt-4.1.0.orig/src/remote/remote_daemon.c
|
|
+++ libvirt-4.1.0/src/remote/remote_daemon.c
|
|
@@ -709,20 +709,32 @@ static void daemonShutdownHandler(virNet
|
|
virNetDaemonQuit(dmn);
|
|
}
|
|
|
|
+static void daemonReloadHandlerThread(void *opague ATTRIBUTE_UNUSED)
|
|
+{
|
|
+ VIR_INFO("Reloading configuration on SIGHUP");
|
|
+ virHookCall(VIR_HOOK_DRIVER_DAEMON, "-",
|
|
+ VIR_HOOK_DAEMON_OP_RELOAD, SIGHUP, "SIGHUP", NULL, NULL);
|
|
+ if (virStateReload() < 0)
|
|
+ VIR_WARN("Error while reloading drivers");
|
|
+}
|
|
+
|
|
static void daemonReloadHandler(virNetDaemonPtr dmn ATTRIBUTE_UNUSED,
|
|
siginfo_t *sig ATTRIBUTE_UNUSED,
|
|
void *opaque ATTRIBUTE_UNUSED)
|
|
{
|
|
+ virThread thr;
|
|
+
|
|
if (!driversInitialized) {
|
|
VIR_WARN("Drivers are not initialized, reload ignored");
|
|
return;
|
|
}
|
|
|
|
- VIR_INFO("Reloading configuration on SIGHUP");
|
|
- virHookCall(VIR_HOOK_DRIVER_DAEMON, "-",
|
|
- VIR_HOOK_DAEMON_OP_RELOAD, SIGHUP, "SIGHUP", NULL, NULL);
|
|
- if (virStateReload() < 0)
|
|
- VIR_WARN("Error while reloading drivers");
|
|
+ if (virThreadCreate(&thr, false, daemonReloadHandlerThread, NULL) < 0) {
|
|
+ /*
|
|
+ * Not much we can do on error here except log it.
|
|
+ */
|
|
+ VIR_ERROR(_("Failed to create thread to handle daemon restart"));
|
|
+ }
|
|
}
|
|
|
|
static int daemonSetupSignals(virNetDaemonPtr dmn)
|