3e5111
From 2122aadba5eb30ae466a3e825bbe9ed75b8d9735 Mon Sep 17 00:00:00 2001
3e5111
Message-Id: <2122aadba5eb30ae466a3e825bbe9ed75b8d9735@dist-git>
3e5111
From: Erik Skultety <eskultet@redhat.com>
3e5111
Date: Thu, 4 May 2017 13:50:00 +0200
3e5111
Subject: [PATCH] mdev: Fix daemon crash on domain shutdown after reconnect
3e5111
3e5111
The problem resides in virHostdevUpdateActiveMediatedDevices which gets
3e5111
called during qemuProcessReconnect. The issue here is that
3e5111
virMediatedDeviceListAdd takes a pointer to the item to be added to the
3e5111
list to which VIR_APPEND_ELEMENT is used, which also clears the pointer.
3e5111
However, in this case only the local copy of the pointer got cleared,
3e5111
leaving the original pointing to valid memory. To sum it up, during
3e5111
cleanup phase, the original pointer is freed and the daemon crashes
3e5111
basically any time it would access it.
3e5111
3e5111
Backtrace:
3e5111
0x00007ffff3ccdeba in __strcmp_sse2_unaligned
3e5111
0x00007ffff72a444a in virMediatedDeviceListFindIndex
3e5111
0x00007ffff7241446 in virHostdevReAttachMediatedDevices
3e5111
0x00007fffc60215d9 in qemuHostdevReAttachMediatedDevices
3e5111
0x00007fffc60216dc in qemuHostdevReAttachDomainDevices
3e5111
0x00007fffc6046e6f in qemuProcessStop
3e5111
0x00007fffc6091596 in processMonitorEOFEvent
3e5111
0x00007fffc6091793 in qemuProcessEventHandler
3e5111
0x00007ffff7294bf5 in virThreadPoolWorker
3e5111
0x00007ffff7294184 in virThreadHelper
3e5111
0x00007ffff3fdc3c4 in start_thread () from /lib64/libpthread.so.0
3e5111
0x00007ffff3d269cf in clone () from /lib64/libc.so.6
3e5111
3e5111
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1446455
3e5111
3e5111
Signed-off-by: Erik Skultety <eskultet@redhat.com>
3e5111
Reviewed-by: Laine Stump <laine@laine.org>
3e5111
(cherry picked from commit 92e30a4dace54d06433f763e1acba0a81bb5c82e)
3e5111
Signed-off-by: Erik Skultety <eskultet@redhat.com>
3e5111
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
3e5111
---
3e5111
 src/util/virhostdev.c |  4 ++--
3e5111
 src/util/virmdev.c    | 13 ++++++++-----
3e5111
 src/util/virmdev.h    |  2 +-
3e5111
 3 files changed, 11 insertions(+), 8 deletions(-)
3e5111
3e5111
diff --git a/src/util/virhostdev.c b/src/util/virhostdev.c
3e5111
index 2c557f5bb..579563c3f 100644
3e5111
--- a/src/util/virhostdev.c
3e5111
+++ b/src/util/virhostdev.c
3e5111
@@ -1294,7 +1294,7 @@ virHostdevUpdateActiveMediatedDevices(virHostdevManagerPtr mgr,
3e5111
 
3e5111
         virMediatedDeviceSetUsedBy(mdev, drv_name, dom_name);
3e5111
 
3e5111
-        if (virMediatedDeviceListAdd(mgr->activeMediatedHostdevs, mdev) < 0)
3e5111
+        if (virMediatedDeviceListAdd(mgr->activeMediatedHostdevs, &mdev) < 0)
3e5111
             goto cleanup;
3e5111
     }
3e5111
 
3e5111
@@ -1790,7 +1790,7 @@ virHostdevPrepareMediatedDevices(virHostdevManagerPtr mgr,
3e5111
         if (!(mdev = virMediatedDeviceNew(src->uuidstr, src->model)))
3e5111
             goto cleanup;
3e5111
 
3e5111
-        if (virMediatedDeviceListAdd(list, mdev) < 0) {
3e5111
+        if (virMediatedDeviceListAdd(list, &mdev) < 0) {
3e5111
             virMediatedDeviceFree(mdev);
3e5111
             goto cleanup;
3e5111
         }
3e5111
diff --git a/src/util/virmdev.c b/src/util/virmdev.c
3e5111
index c1499d238..c861d21c9 100644
3e5111
--- a/src/util/virmdev.c
3e5111
+++ b/src/util/virmdev.c
3e5111
@@ -312,16 +312,19 @@ virMediatedDeviceListDispose(void *obj)
3e5111
 }
3e5111
 
3e5111
 
3e5111
+/* The reason for @dev to be double pointer is that VIR_APPEND_ELEMENT clears
3e5111
+ * the pointer and we need to clear the original not a copy on the stack
3e5111
+ */
3e5111
 int
3e5111
 virMediatedDeviceListAdd(virMediatedDeviceListPtr list,
3e5111
-                         virMediatedDevicePtr dev)
3e5111
+                         virMediatedDevicePtr *dev)
3e5111
 {
3e5111
-    if (virMediatedDeviceListFind(list, dev)) {
3e5111
+    if (virMediatedDeviceListFind(list, *dev)) {
3e5111
         virReportError(VIR_ERR_INTERNAL_ERROR,
3e5111
-                       _("device %s is already in use"), dev->path);
3e5111
+                       _("device %s is already in use"), (*dev)->path);
3e5111
         return -1;
3e5111
     }
3e5111
-    return VIR_APPEND_ELEMENT(list->devs, list->count, dev);
3e5111
+    return VIR_APPEND_ELEMENT(list->devs, list->count, *dev);
3e5111
 }
3e5111
 
3e5111
 
3e5111
@@ -457,7 +460,7 @@ virMediatedDeviceListMarkDevices(virMediatedDeviceListPtr dst,
3e5111
          * - caller is responsible for NOT freeing devices in @src on success
3e5111
          * - we're responsible for performing a rollback on failure
3e5111
          */
3e5111
-        if (virMediatedDeviceListAdd(dst, mdev) < 0)
3e5111
+        if (virMediatedDeviceListAdd(dst, &mdev) < 0)
3e5111
             goto rollback;
3e5111
 
3e5111
         VIR_DEBUG("'%s' added to list of active mediated devices used by '%s'",
3e5111
diff --git a/src/util/virmdev.h b/src/util/virmdev.h
3e5111
index 2f3d6bb84..8bb46b9c5 100644
3e5111
--- a/src/util/virmdev.h
3e5111
+++ b/src/util/virmdev.h
3e5111
@@ -86,7 +86,7 @@ virMediatedDeviceListNew(void);
3e5111
 
3e5111
 int
3e5111
 virMediatedDeviceListAdd(virMediatedDeviceListPtr list,
3e5111
-                         virMediatedDevicePtr dev);
3e5111
+                         virMediatedDevicePtr *dev);
3e5111
 
3e5111
 virMediatedDevicePtr
3e5111
 virMediatedDeviceListGet(virMediatedDeviceListPtr list,
3e5111
-- 
3e5111
2.13.0
3e5111