render / rpms / libvirt

Forked from rpms/libvirt 9 months ago
Clone
43fe83
From 48d8b3b8088178e6b77e40379facbfd23f3154e8 Mon Sep 17 00:00:00 2001
43fe83
Message-Id: <48d8b3b8088178e6b77e40379facbfd23f3154e8.1377873640.git.jdenemar@redhat.com>
43fe83
From: Peter Krempa <pkrempa@redhat.com>
43fe83
Date: Wed, 21 Aug 2013 12:43:31 +0200
43fe83
Subject: [PATCH] virsh: Don't leak list of volumes when undefining domain with
43fe83
 storage
43fe83
43fe83
https://bugzilla.redhat.com/show_bug.cgi?id=999057 [7.0]
43fe83
43fe83
Use the new semantics of vshStringToArray to avoid leaking the array of
43fe83
volumes to be deleted. The array would be leaked in case the first
43fe83
volume was found in the domain definition. Also refactor the code a bit
43fe83
to sanitize naming of variables hoding arrays and dimensions of the
43fe83
arrays.
43fe83
43fe83
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=996050 [6.6]
43fe83
(cherry picked from commit 04898f60d2b509c4d106bf7e1ee269acc240b93d)
43fe83
---
43fe83
 tools/virsh-domain.c | 134 +++++++++++++++++++++++++--------------------------
43fe83
 1 file changed, 65 insertions(+), 69 deletions(-)
43fe83
43fe83
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
43fe83
index e2e4409..f35a3c5 100644
43fe83
--- a/tools/virsh-domain.c
43fe83
+++ b/tools/virsh-domain.c
43fe83
@@ -2928,24 +2928,23 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd)
43fe83
     int rc = -1;
43fe83
     int running;
43fe83
     /* list of volumes to remove along with this domain */
43fe83
-    vshUndefineVolume *vlist = NULL;
43fe83
-    int nvols = 0;
43fe83
-    const char *volumes = NULL;
43fe83
-    char **volume_tokens = NULL;
43fe83
-    char *volume_tok = NULL;
43fe83
-    int nvolume_tokens = 0;
43fe83
-    char *def = NULL;
43fe83
+    const char *vol_string = NULL;  /* string containing volumes to delete */
43fe83
+    char **vol_list = NULL;         /* tokenized vol_string */
43fe83
+    int nvol_list = 0;
43fe83
+    vshUndefineVolume *vols = NULL; /* info about the volumes to delete*/
43fe83
+    size_t nvols = 0;
43fe83
+    char *def = NULL;               /* domain def */
43fe83
+    xmlDocPtr doc = NULL;
43fe83
+    xmlXPathContextPtr ctxt = NULL;
43fe83
+    xmlNodePtr *vol_nodes = NULL;   /* XML nodes of volumes of the guest */
43fe83
+    int nvol_nodes;
43fe83
     char *source = NULL;
43fe83
     char *target = NULL;
43fe83
     size_t i;
43fe83
     size_t j;
43fe83
-    xmlDocPtr doc = NULL;
43fe83
-    xmlXPathContextPtr ctxt = NULL;
43fe83
-    xmlNodePtr *vol_nodes = NULL;
43fe83
-    int nvolumes = 0;
43fe83
-    bool vol_not_found = false;
43fe83
 
43fe83
-    ignore_value(vshCommandOptString(cmd, "storage", &volumes));
43fe83
+
43fe83
+    ignore_value(vshCommandOptString(cmd, "storage", &vol_string));
43fe83
 
43fe83
     if (managed_save) {
43fe83
         flags |= VIR_DOMAIN_UNDEFINE_MANAGED_SAVE;
43fe83
@@ -3013,14 +3012,17 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd)
43fe83
     }
43fe83
 
43fe83
     /* Stash domain description for later use */
43fe83
-    if (volumes || remove_all_storage) {
43fe83
+    if (vol_string || remove_all_storage) {
43fe83
         if (running) {
43fe83
-            vshError(ctl, _("Storage volume deletion is supported only on stopped domains"));
43fe83
+            vshError(ctl,
43fe83
+                     _("Storage volume deletion is supported only on "
43fe83
+                       "stopped domains"));
43fe83
             goto cleanup;
43fe83
         }
43fe83
 
43fe83
-        if (volumes && remove_all_storage) {
43fe83
-            vshError(ctl, _("Specified both --storage and --remove-all-storage"));
43fe83
+        if (vol_string && remove_all_storage) {
43fe83
+            vshError(ctl,
43fe83
+                     _("Specified both --storage and --remove-all-storage"));
43fe83
             goto cleanup;
43fe83
         }
43fe83
 
43fe83
@@ -3034,20 +3036,17 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd)
43fe83
             goto error;
43fe83
 
43fe83
         /* tokenize the string from user and save it's parts into an array */
43fe83
-        if (volumes) {
43fe83
-            if ((nvolume_tokens = vshStringToArray(volumes, &volume_tokens)) < 0)
43fe83
-                goto cleanup;
43fe83
-        }
43fe83
-
43fe83
-        if ((nvolumes = virXPathNodeSet("./devices/disk", ctxt,
43fe83
-                                        &vol_nodes)) < 0)
43fe83
+        if (vol_string &&
43fe83
+            (nvol_list = vshStringToArray(vol_string, &vol_list)) < 0)
43fe83
             goto error;
43fe83
 
43fe83
-        if (nvolumes > 0)
43fe83
-            vlist = vshCalloc(ctl, nvolumes, sizeof(*vlist));
43fe83
+        if ((nvol_nodes = virXPathNodeSet("./devices/disk", ctxt,
43fe83
+                                          &vol_nodes)) < 0)
43fe83
+            goto error;
43fe83
 
43fe83
-        for (i = 0; i < nvolumes; i++) {
43fe83
+        for (i = 0; i < nvol_nodes; i++) {
43fe83
             ctxt->node = vol_nodes[i];
43fe83
+            vshUndefineVolume vol;
43fe83
             VIR_FREE(source);
43fe83
             VIR_FREE(target);
43fe83
 
43fe83
@@ -3059,56 +3058,53 @@ cmdUndefine(vshControl *ctl, const vshCmd *cmd)
43fe83
                                           "./source/@file|"
43fe83
                                           "./source/@dir|"
43fe83
                                           "./source/@name|"
43fe83
-                                          "./source/@dev)", ctxt))) {
43fe83
-                if (last_error && last_error->code != VIR_ERR_OK)
43fe83
-                    goto error;
43fe83
-                else
43fe83
-                    continue;
43fe83
-            }
43fe83
+                                          "./source/@dev)", ctxt)))
43fe83
+                continue;
43fe83
 
43fe83
             /* lookup if volume was selected by user */
43fe83
-            if (volumes) {
43fe83
-                volume_tok = NULL;
43fe83
-                for (j = 0; j < nvolume_tokens; j++) {
43fe83
-                    if (volume_tokens[j] &&
43fe83
-                        (STREQ(volume_tokens[j], target) ||
43fe83
-                         STREQ(volume_tokens[j], source))) {
43fe83
-                        volume_tok = volume_tokens[j];
43fe83
-                        volume_tokens[j] = NULL;
43fe83
+            if (vol_list) {
43fe83
+                bool found = false;
43fe83
+                for (j = 0; j < nvol_list; j++) {
43fe83
+                    if (STREQ_NULLABLE(vol_list[j], target) ||
43fe83
+                        STREQ_NULLABLE(vol_list[j], source)) {
43fe83
+                        VIR_FREE(vol_list[j]);
43fe83
+                        found = true;
43fe83
                         break;
43fe83
                     }
43fe83
                 }
43fe83
-                if (!volume_tok)
43fe83
+                if (!found)
43fe83
                     continue;
43fe83
             }
43fe83
 
43fe83
-            if (!(vlist[nvols].vol = virStorageVolLookupByPath(ctl->conn,
43fe83
-                                                               source))) {
43fe83
+            if (!(vol.vol = virStorageVolLookupByPath(ctl->conn, source))) {
43fe83
                 vshPrint(ctl,
43fe83
                          _("Storage volume '%s'(%s) is not managed by libvirt. "
43fe83
                            "Remove it manually.\n"), target, source);
43fe83
                 vshResetLibvirtError();
43fe83
                 continue;
43fe83
             }
43fe83
-            vlist[nvols].source = source;
43fe83
-            vlist[nvols].target = target;
43fe83
+
43fe83
+            vol.source = source;
43fe83
+            vol.target = target;
43fe83
             source = NULL;
43fe83
             target = NULL;
43fe83
-            nvols++;
43fe83
+            if (VIR_APPEND_ELEMENT(vols, nvols, vol) < 0)
43fe83
+                goto cleanup;
43fe83
         }
43fe83
 
43fe83
         /* print volumes specified by user that were not found in domain definition */
43fe83
-        if (volumes) {
43fe83
-            for (j = 0; j < nvolume_tokens; j++) {
43fe83
-                if (volume_tokens[j]) {
43fe83
-                    vshError(ctl, _("Volume '%s' was not found in domain's "
43fe83
-                                    "definition.\n"),
43fe83
-                             volume_tokens[j]);
43fe83
-                    vol_not_found = true;
43fe83
+        if (vol_list) {
43fe83
+            bool found = false;
43fe83
+            for (i = 0; i < nvol_list; i++) {
43fe83
+                if (vol_list[i]) {
43fe83
+                    vshError(ctl,
43fe83
+                             _("Volume '%s' was not found in domain's "
43fe83
+                               "definition.\n"), vol_list[i]);
43fe83
+                    found = true;
43fe83
                 }
43fe83
             }
43fe83
 
43fe83
-            if (vol_not_found)
43fe83
+            if (found)
43fe83
                 goto cleanup;
43fe83
         }
43fe83
     }
43fe83
@@ -3169,9 +3165,9 @@ out:
43fe83
         for (i = 0; i < nvols; i++) {
43fe83
             if (wipe_storage) {
43fe83
                 vshPrint(ctl, _("Wiping volume '%s'(%s) ... "),
43fe83
-                         vlist[i].target, vlist[i].source);
43fe83
+                         vols[i].target, vols[i].source);
43fe83
                 fflush(stdout);
43fe83
-                if (virStorageVolWipe(vlist[i].vol, 0) < 0) {
43fe83
+                if (virStorageVolWipe(vols[i].vol, 0) < 0) {
43fe83
                     vshError(ctl, _("Failed! Volume not removed."));
43fe83
                     ret = false;
43fe83
                     continue;
43fe83
@@ -3181,13 +3177,13 @@ out:
43fe83
             }
43fe83
 
43fe83
             /* delete the volume */
43fe83
-            if (virStorageVolDelete(vlist[i].vol, 0) < 0) {
43fe83
+            if (virStorageVolDelete(vols[i].vol, 0) < 0) {
43fe83
                 vshError(ctl, _("Failed to remove storage volume '%s'(%s)"),
43fe83
-                         vlist[i].target, vlist[i].source);
43fe83
+                         vols[i].target, vols[i].source);
43fe83
                 ret = false;
43fe83
             } else {
43fe83
                 vshPrint(ctl, _("Volume '%s'(%s) removed.\n"),
43fe83
-                         vlist[i].target, vlist[i].source);
43fe83
+                         vols[i].target, vols[i].source);
43fe83
             }
43fe83
         }
43fe83
     }
43fe83
@@ -3196,17 +3192,17 @@ cleanup:
43fe83
     VIR_FREE(source);
43fe83
     VIR_FREE(target);
43fe83
     for (i = 0; i < nvols; i++) {
43fe83
-        VIR_FREE(vlist[i].source);
43fe83
-        VIR_FREE(vlist[i].target);
43fe83
-        if (vlist[i].vol)
43fe83
-            virStorageVolFree(vlist[i].vol);
43fe83
+        VIR_FREE(vols[i].source);
43fe83
+        VIR_FREE(vols[i].target);
43fe83
+        if (vols[i].vol)
43fe83
+            virStorageVolFree(vols[i].vol);
43fe83
     }
43fe83
-    VIR_FREE(vlist);
43fe83
+    VIR_FREE(vols);
43fe83
+
43fe83
+    for (i = 0; i < nvol_list; i++)
43fe83
+        VIR_FREE(vol_list[i]);
43fe83
+    VIR_FREE(vol_list);
43fe83
 
43fe83
-    if (volume_tokens) {
43fe83
-        VIR_FREE(*volume_tokens);
43fe83
-        VIR_FREE(volume_tokens);
43fe83
-    }
43fe83
     VIR_FREE(def);
43fe83
     VIR_FREE(vol_nodes);
43fe83
     xmlFreeDoc(doc);
43fe83
-- 
43fe83
1.8.3.2
43fe83