]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: fix crash in qemuProcessAutoDestroy
authorMichael Chapman <mike@very.puzzling.org>
Mon, 30 Mar 2015 02:40:58 +0000 (13:40 +1100)
committerCole Robinson <crobinso@redhat.com>
Tue, 28 Apr 2015 15:09:47 +0000 (11:09 -0400)
The destination libvirt daemon in a migration may segfault if the client
disconnects immediately after the migration has begun:

  # virsh -c qemu+tls://remote/system list --all
   Id    Name                           State
  ----------------------------------------------------
  ...

  # timeout --signal KILL 1 \
      virsh migrate example qemu+tls://remote/system \
        --verbose --compressed --live --auto-converge \
        --abort-on-error --unsafe --persistent \
        --undefinesource --copy-storage-all --xml example.xml
  Killed

  # virsh -c qemu+tls://remote/system list --all
  error: failed to connect to the hypervisor
  error: unable to connect to server at 'remote:16514': Connection refused

The crash is in:

   1531 void
   1532 qemuDomainObjEndJob(virQEMUDriverPtr driver, virDomainObjPtr obj)
   1533 {
   1534     qemuDomainObjPrivatePtr priv = obj->privateData;
   1535     qemuDomainJob job = priv->job.active;
   1536
   1537     priv->jobs_queued--;

Backtrace:

  #0  at qemuDomainObjEndJob at qemu/qemu_domain.c:1537
  #1  in qemuDomainRemoveInactive at qemu/qemu_domain.c:2497
  #2  in qemuProcessAutoDestroy at qemu/qemu_process.c:5646
  #3  in virCloseCallbacksRun at util/virclosecallbacks.c:350
  #4  in qemuConnectClose at qemu/qemu_driver.c:1154
  ...

qemuDomainRemoveInactive calls virDomainObjListRemove, which in this
case is holding the last remaining reference to the domain.
qemuDomainRemoveInactive then calls qemuDomainObjEndJob, but the domain
object has been freed and poisoned by then.

This patch bumps the domain's refcount until qemuDomainRemoveInactive
has completed. We also ensure qemuProcessAutoDestroy does not return the
domain to virCloseCallbacksRun to be unlocked in this case. There is
similar logic in bhyveProcessAutoDestroy and lxcProcessAutoDestroy
(which call virDomainObjListRemove directly).

Signed-off-by: Michael Chapman <mike@very.puzzling.org>
(cherry picked from commit 7578cc17f58d7b2d582fffb118a077b73288d92b)

src/qemu/qemu_domain.c
src/qemu/qemu_process.c

index 20ac408d1528edd1c45e6a802ea83e31652fa1ff..bd7d8a4c6a828f24beb252a5d0c2627fa18ae728 100644 (file)
@@ -2426,11 +2426,16 @@ qemuDomainRemoveInactive(virQEMUDriverPtr driver,
             VIR_WARN("unable to remove snapshot directory %s", snapDir);
         VIR_FREE(snapDir);
     }
+
+    virObjectRef(vm);
+
     virDomainObjListRemove(driver->domains, vm);
     virObjectUnref(cfg);
 
     if (haveJob)
         qemuDomainObjEndJob(driver, vm);
+
+    virObjectUnref(vm);
 }
 
 void
index cd71741ab17d037fea01a170d926354b6bc474c0..46f02b5fde937d082fe36c508d3014463fcd01be 100644 (file)
@@ -5694,8 +5694,10 @@ qemuProcessAutoDestroy(virDomainObjPtr dom,
 
     qemuDomainObjEndJob(driver, dom);
 
-    if (!dom->persistent)
+    if (!dom->persistent) {
         qemuDomainRemoveInactive(driver, dom);
+        dom = NULL;
+    }
 
     if (event)
         qemuDomainEventQueue(driver, event);