[PATCH 1/9] util: json: Fix freeing of objects appended to virJSONValue

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



It was not possible to determine whether virJSONValueObjectAddVArgs and
the functions using it would consume a virJSONValue or not when used
with the 'a' or 'A' modifier depending on when the loop failed.

Fix this by passing in a pointer to the pointer so that it can be
cleared once it's successfully consumed and the callers don't have to
second-guess leaving a chance of leaking or double freeing the value
depending on the ordering.

Fix all callers to pass a double pointer too.

Signed-off-by: Peter Krempa <pkrempa@xxxxxxxxxx>
---
 src/qemu/qemu_agent.c        |  7 ++-----
 src/qemu/qemu_block.c        | 22 ++++++----------------
 src/qemu/qemu_command.c      |  2 +-
 src/qemu/qemu_monitor_json.c | 36 ++++++++++--------------------------
 src/util/virjson.c           | 10 +++++++---
 tests/qemublocktest.c        |  4 +---
 6 files changed, 27 insertions(+), 54 deletions(-)

diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c
index 89183c3f76..b99d5b10e3 100644
--- a/src/qemu/qemu_agent.c
+++ b/src/qemu/qemu_agent.c
@@ -1336,14 +1336,13 @@ int qemuAgentFSFreeze(qemuAgentPtr mon, const char **mountpoints,
             return -1;

         cmd = qemuAgentMakeCommand("guest-fsfreeze-freeze-list",
-                                   "a:mountpoints", arg, NULL);
+                                   "a:mountpoints", &arg, NULL);
     } else {
         cmd = qemuAgentMakeCommand("guest-fsfreeze-freeze", NULL);
     }

     if (!cmd)
         goto cleanup;
-    arg = NULL;

     if (qemuAgentCommand(mon, cmd, &reply, true,
                          VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0)
@@ -1611,12 +1610,10 @@ qemuAgentSetVCPUsCommand(qemuAgentPtr mon,
     }

     if (!(cmd = qemuAgentMakeCommand("guest-set-vcpus",
-                                     "a:vcpus", cpus,
+                                     "a:vcpus", &cpus,
                                      NULL)))
         goto cleanup;

-    cpus = NULL;
-
     if (qemuAgentCommand(mon, cmd, &reply, true,
                          VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) < 0)
         goto cleanup;
diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index 6f81e9d96c..c0cf6a95ad 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -674,11 +674,9 @@ qemuBlockStorageSourceGetGlusterProps(virStorageSourcePtr src)
                                  "s:driver", "gluster",
                                  "s:volume", src->volume,
                                  "s:path", src->path,
-                                 "a:server", servers, NULL) < 0)
+                                 "a:server", &servers, NULL) < 0)
         goto cleanup;

-    servers = NULL;
-
     if (src->debug &&
         virJSONValueObjectAdd(props, "u:debug", src->debugLevel, NULL) < 0)
         goto cleanup;
@@ -719,7 +717,7 @@ qemuBlockStorageSourceGetVxHSProps(virStorageSourcePtr src)
                                  "s:driver", protocol,
                                  "S:tls-creds", src->tlsAlias,
                                  "s:vdisk-id", src->path,
-                                 "a:server", server, NULL) < 0)
+                                 "a:server", &server, NULL) < 0)
         virJSONValueFree(server);

     return ret;
@@ -867,14 +865,12 @@ qemuBlockStorageSourceGetNBDProps(virStorageSourcePtr src)

     if (virJSONValueObjectCreate(&ret,
                                  "s:driver", "nbd",
-                                 "a:server", serverprops,
+                                 "a:server", &serverprops,
                                  "S:export", src->path,
                                  "S:tls-creds", src->tlsAlias,
                                  NULL) < 0)
         goto cleanup;

-    serverprops = NULL;
-
  cleanup:
     virJSONValueFree(serverprops);
     return ret;
@@ -902,13 +898,11 @@ qemuBlockStorageSourceGetRBDProps(virStorageSourcePtr src)
                                  "s:image", src->path,
                                  "S:snapshot", src->snapshot,
                                  "S:conf", src->configFile,
-                                 "A:server", servers,
+                                 "A:server", &servers,
                                  "S:user", username,
                                  NULL) < 0)
         goto cleanup;

-    servers = NULL;
-
  cleanup:
     virJSONValueFree(servers);
     return ret;
@@ -935,13 +929,11 @@ qemuBlockStorageSourceGetSheepdogProps(virStorageSourcePtr src)
     /* libvirt does not support the 'snap-id' and 'tag' properties */
     if (virJSONValueObjectCreate(&ret,
                                  "s:driver", "sheepdog",
-                                 "a:server", serverprops,
+                                 "a:server", &serverprops,
                                  "s:vdi", src->path,
                                  NULL) < 0)
         goto cleanup;

-    serverprops = NULL;
-
  cleanup:
     virJSONValueFree(serverprops);
     return ret;
@@ -971,13 +963,11 @@ qemuBlockStorageSourceGetSshProps(virStorageSourcePtr src)
     if (virJSONValueObjectCreate(&ret,
                                  "s:driver", "ssh",
                                  "s:path", src->path,
-                                 "a:server", serverprops,
+                                 "a:server", &serverprops,
                                  "S:user", username,
                                  NULL) < 0)
         goto cleanup;

-    serverprops = NULL;
-
  cleanup:
     virJSONValueFree(serverprops);
     return ret;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 89fd08b642..3d4130d3c0 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -1505,7 +1505,7 @@ qemuDiskSourceGetProps(virStorageSourcePtr src)
     if (!(props = qemuBlockStorageSourceGetBackendProps(src)))
         return NULL;

-    if (virJSONValueObjectCreate(&ret, "a:file", props, NULL) < 0) {
+    if (virJSONValueObjectCreate(&ret, "a:file", &props, NULL) < 0) {
         virJSONValueFree(props);
         return NULL;
     }
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index d80c4f18d1..f38d04f663 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -3950,14 +3950,11 @@ int qemuMonitorJSONAddObject(qemuMonitorPtr mon,
     cmd = qemuMonitorJSONMakeCommand("object-add",
                                      "s:qom-type", type,
                                      "s:id", objalias,
-                                     "A:props", props,
+                                     "A:props", &props,
                                      NULL);
     if (!cmd)
         goto cleanup;

-    /* @props is part of @cmd now. Avoid double free */
-    props = NULL;
-
     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
         goto cleanup;

@@ -4133,12 +4130,13 @@ qemuMonitorJSONTransaction(qemuMonitorPtr mon, virJSONValuePtr actions)
     int ret = -1;
     virJSONValuePtr cmd;
     virJSONValuePtr reply = NULL;
+    virJSONValuePtr act = actions;
     bool protect = actions->protect;

     /* We do NOT want to free actions when recursively freeing cmd.  */
     actions->protect = true;
     cmd = qemuMonitorJSONMakeCommand("transaction",
-                                     "a:actions", actions,
+                                     "a:actions", &act,
                                      NULL);
     if (!cmd)
         goto cleanup;
@@ -4425,15 +4423,12 @@ int qemuMonitorJSONSendKey(qemuMonitorPtr mon,
     }

     cmd = qemuMonitorJSONMakeCommand("send-key",
-                                     "a:keys", keys,
+                                     "a:keys", &keys,
                                      "p:hold-time", holdtime,
                                      NULL);
     if (!cmd)
         goto cleanup;

-    /* @keys is part of @cmd now. Avoid double free */
-    keys = NULL;
-
     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
         goto cleanup;

@@ -5390,15 +5385,10 @@ qemuMonitorJSONGetCPUModelExpansion(qemuMonitorPtr mon,

     if (!(cmd = qemuMonitorJSONMakeCommand("query-cpu-model-expansion",
                                            "s:type", typeStr,
-                                           "a:model", model,
+                                           "a:model", &model,
                                            NULL)))
         goto cleanup;

-    /* model will be freed when cmd is freed. we set model
-     * to NULL to avoid double freeing.
-     */
-    model = NULL;
-
     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
         goto cleanup;

@@ -6263,13 +6253,11 @@ qemuMonitorJSONSetMigrationCapability(qemuMonitorPtr mon,
     cap = NULL;

     cmd = qemuMonitorJSONMakeCommand("migrate-set-capabilities",
-                                     "a:capabilities", caps,
+                                     "a:capabilities", &caps,
                                      NULL);
     if (!cmd)
         goto cleanup;

-    caps = NULL;
-
     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
         goto cleanup;

@@ -6410,7 +6398,7 @@ qemuMonitorJSONBuildInetSocketAddress(const char *host,
         return NULL;

     if (virJSONValueObjectCreate(&addr, "s:type", "inet",
-                                        "a:data", data, NULL) < 0) {
+                                        "a:data", &data, NULL) < 0) {
         virJSONValueFree(data);
         return NULL;
     }
@@ -6428,7 +6416,7 @@ qemuMonitorJSONBuildUnixSocketAddress(const char *path)
         return NULL;

     if (virJSONValueObjectCreate(&addr, "s:type", "unix",
-                                        "a:data", data, NULL) < 0) {
+                                        "a:data", &data, NULL) < 0) {
         virJSONValueFree(data);
         return NULL;
     }
@@ -6454,13 +6442,10 @@ qemuMonitorJSONNBDServerStart(qemuMonitorPtr mon,
         return ret;

     if (!(cmd = qemuMonitorJSONMakeCommand("nbd-server-start",
-                                           "a:addr", addr,
+                                           "a:addr", &addr,
                                            NULL)))
         goto cleanup;

-    /* From now on, @addr is part of @cmd */
-    addr = NULL;
-
     if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
         goto cleanup;

@@ -6763,10 +6748,9 @@ qemuMonitorJSONAttachCharDevCommand(const char *chrID,

     if (!(ret = qemuMonitorJSONMakeCommand("chardev-add",
                                            "s:id", chrID,
-                                           "a:backend", backend,
+                                           "a:backend", &backend,
                                            NULL)))
         goto cleanup;
-    backend = NULL;

  cleanup:
     VIR_FREE(tlsalias);
diff --git a/src/util/virjson.c b/src/util/virjson.c
index 6a02ddf0cc..212c158da0 100644
--- a/src/util/virjson.c
+++ b/src/util/virjson.c
@@ -109,8 +109,11 @@ virJSONValueGetType(const virJSONValue *value)
  * d: double precision floating point number
  * n: json null value
  *
+ * The following two cases take a pointer to a pointer to a virJSONValuePtr. The
+ * pointer is cleared when the virJSONValuePtr is stolen into the object.
  * a: json object, must be non-NULL
  * A: json object, omitted if NULL
+ *
  * m: a bitmap represented as a JSON array, must be non-NULL
  * M: a bitmap represented as a JSON array, omitted if NULL
  *
@@ -241,9 +244,9 @@ virJSONValueObjectAddVArgs(virJSONValuePtr obj,

         case 'A':
         case 'a': {
-            virJSONValuePtr val = va_arg(args, virJSONValuePtr);
+            virJSONValuePtr *val = va_arg(args, virJSONValuePtr *);

-            if (!val) {
+            if (!(*val)) {
                 if (type == 'A')
                     continue;

@@ -253,7 +256,8 @@ virJSONValueObjectAddVArgs(virJSONValuePtr obj,
                 goto cleanup;
             }

-            rc = virJSONValueObjectAppend(obj, key, val);
+            if ((rc = virJSONValueObjectAppend(obj, key, *val)) == 0)
+                *val = NULL;
         }   break;

         case 'M':
diff --git a/tests/qemublocktest.c b/tests/qemublocktest.c
index e8fac100dd..99584c759c 100644
--- a/tests/qemublocktest.c
+++ b/tests/qemublocktest.c
@@ -67,11 +67,9 @@ testBackingXMLjsonXML(const void *args)
         goto cleanup;
     }

-    if (virJSONValueObjectCreate(&wrapper, "a:file", backendprops, NULL) < 0)
+    if (virJSONValueObjectCreate(&wrapper, "a:file", &backendprops, NULL) < 0)
         goto cleanup;

-    backendprops = NULL;
-
     if (!(propsstr = virJSONValueToString(wrapper, false)))
         goto cleanup;

-- 
2.16.2

--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list



[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]

  Powered by Linux