]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: Add missing lock of virDomainObj before calling virDomainUnref
authorLaine Stump <laine@laine.org>
Thu, 3 Mar 2011 16:54:08 +0000 (11:54 -0500)
committerLaine Stump <laine@laine.org>
Fri, 4 Mar 2011 13:12:58 +0000 (08:12 -0500)
This was found while researching the root cause of:

https://bugzilla.redhat.com/show_bug.cgi?id=670848

virDomainUnref should only be called with the lock held for the
virDomainObj in question. However, when a transient qemu domain gets
EOF on its monitor socket, it queues an event which frees the monitor,
which unref's the virDomainObj without first locking it. If another
thread has already locked the virDomainObj, the modification of the
refcount could potentially be corrupted. In an extreme case, it could
also be potentially unlocked by virDomainObjFree, thus left open to
modification by anyone else who would have otherwise waited for the
lock (not to mention the fact that they would be accessing freed
data!).

The solution is to have qemuMonitorFree lock the domain object right
before unrefing it. Since the caller to qemuMonitorFree doesn't expect
this lock to be held, if the refcount doesn't go all the way to 0,
qemuMonitorFree must unlock it after the unref.

src/qemu/qemu_process.c

index c419c75e02de14056d002352d74f7b129b62b636..908472568cdfbaae607e420cebc4511c7209fd8c 100644 (file)
@@ -593,10 +593,14 @@ no_memory:
 static void qemuProcessHandleMonitorDestroy(qemuMonitorPtr mon,
                                             virDomainObjPtr vm)
 {
-    qemuDomainObjPrivatePtr priv = vm->privateData;
+    qemuDomainObjPrivatePtr priv;
+
+    virDomainObjLock(vm);
+    priv = vm->privateData;
     if (priv->mon == mon)
         priv->mon = NULL;
-    virDomainObjUnref(vm);
+    if (virDomainObjUnref(vm) > 0)
+        virDomainObjUnlock(vm);
 }
 
 static qemuMonitorCallbacks monitorCallbacks = {