[libvirt] [PATCH] qemu: monitor: Fix a memory leak in qemuMonitorJSONAttachCharDevCommand
Erik Skultety
eskultet at redhat.com
Wed Jun 14 07:07:49 UTC 2017
On Tue, Jun 13, 2017 at 06:17:55PM +0200, Pavel Hrdina wrote:
> On Tue, Jun 13, 2017 at 06:01:17PM +0200, Erik Skultety wrote:
> > With the current logic, we only free @tlsalias as part of the error
> > label and would have to free it explicitly earlier in the code. Convert
> > the error label to cleanup, so that we have only one sink, where we
> > handle all frees. In order to do that we need to clear some JSON obj
> > pointers down the success road to avoid SIGSEGV, since JSON object
> > append operation consumes pointers.
> >
> > Signed-off-by: Erik Skultety <eskultet at redhat.com>
> > ---
> > src/qemu/qemu_monitor_json.c | 47 ++++++++++++++++++++++----------------------
> > 1 file changed, 23 insertions(+), 24 deletions(-)
> >
> > diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
> > index f208dd05a..b8b73926f 100644
> > --- a/src/qemu/qemu_monitor_json.c
> > +++ b/src/qemu/qemu_monitor_json.c
> > @@ -6430,8 +6430,8 @@ static virJSONValuePtr
> > qemuMonitorJSONAttachCharDevCommand(const char *chrID,
> > const virDomainChrSourceDef *chr)
> > {
> > - virJSONValuePtr ret;
> > - virJSONValuePtr backend;
> > + virJSONValuePtr ret = NULL;
> > + virJSONValuePtr backend = NULL;
> > virJSONValuePtr data = NULL;
> > virJSONValuePtr addr = NULL;
> > const char *backend_type = NULL;
> > @@ -6440,7 +6440,7 @@ qemuMonitorJSONAttachCharDevCommand(const char *chrID,
> >
> > if (!(backend = virJSONValueNewObject()) ||
> > !(data = virJSONValueNewObject())) {
> > - goto error;
> > + goto cleanup;
> > }
> >
> > switch ((virDomainChrType) chr->type) {
> > @@ -6456,14 +6456,14 @@ qemuMonitorJSONAttachCharDevCommand(const char *chrID,
> > case VIR_DOMAIN_CHR_TYPE_FILE:
> > backend_type = "file";
> > if (virJSONValueObjectAppendString(data, "out", chr->data.file.path) < 0)
> > - goto error;
> > + goto cleanup;
> > break;
> >
> > case VIR_DOMAIN_CHR_TYPE_DEV:
> > backend_type = STRPREFIX(chrID, "parallel") ? "parallel" : "serial";
> > if (virJSONValueObjectAppendString(data, "device",
> > chr->data.file.path) < 0)
> > - goto error;
> > + goto cleanup;
> > break;
> >
> > case VIR_DOMAIN_CHR_TYPE_TCP:
> > @@ -6472,21 +6472,20 @@ qemuMonitorJSONAttachCharDevCommand(const char *chrID,
> > chr->data.tcp.service);
> > if (!addr ||
> > virJSONValueObjectAppend(data, "addr", addr) < 0)
> > - goto error;
> > - addr = NULL;
> > + goto cleanup;
> >
> > telnet = chr->data.tcp.protocol == VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET;
> >
> > if (virJSONValueObjectAppendBoolean(data, "wait", false) < 0 ||
> > virJSONValueObjectAppendBoolean(data, "telnet", telnet) < 0 ||
> > virJSONValueObjectAppendBoolean(data, "server", chr->data.tcp.listen) < 0)
> > - goto error;
> > + goto cleanup;
> > if (chr->data.tcp.tlscreds) {
> > if (!(tlsalias = qemuAliasTLSObjFromSrcAlias(chrID)))
> > - goto error;
> > + goto cleanup;
> >
> > if (virJSONValueObjectAppendString(data, "tls-creds", tlsalias) < 0)
> > - goto error;
> > + goto cleanup;
> > }
> > break;
> >
> > @@ -6496,16 +6495,15 @@ qemuMonitorJSONAttachCharDevCommand(const char *chrID,
> > chr->data.udp.connectService);
> > if (!addr ||
> > virJSONValueObjectAppend(data, "remote", addr) < 0)
> > - goto error;
> > + goto cleanup;
> >
> > if (chr->data.udp.bindHost) {
> > addr = qemuMonitorJSONBuildInetSocketAddress(chr->data.udp.bindHost,
> > chr->data.udp.bindService);
> > if (!addr ||
> > virJSONValueObjectAppend(data, "local", addr) < 0)
> > - goto error;
> > + goto cleanup;
> > }
> > - addr = NULL;
> > break;
> >
> > case VIR_DOMAIN_CHR_TYPE_UNIX:
> > @@ -6514,12 +6512,11 @@ qemuMonitorJSONAttachCharDevCommand(const char *chrID,
> >
> > if (!addr ||
> > virJSONValueObjectAppend(data, "addr", addr) < 0)
> > - goto error;
> > - addr = NULL;
> > + goto cleanup;
> >
> > if (virJSONValueObjectAppendBoolean(data, "wait", false) < 0 ||
> > virJSONValueObjectAppendBoolean(data, "server", chr->data.nix.listen) < 0)
> > - goto error;
> > + goto cleanup;
> > break;
> >
> > case VIR_DOMAIN_CHR_TYPE_SPICEVMC:
> > @@ -6527,7 +6524,7 @@ qemuMonitorJSONAttachCharDevCommand(const char *chrID,
> >
> > if (virJSONValueObjectAppendString(data, "type",
> > virDomainChrSpicevmcTypeToString(chr->data.spicevmc)) < 0)
> > - goto error;
> > + goto cleanup;
> > break;
> >
> > case VIR_DOMAIN_CHR_TYPE_SPICEPORT:
> > @@ -6544,28 +6541,30 @@ qemuMonitorJSONAttachCharDevCommand(const char *chrID,
> > _("Hotplug unsupported for char device type '%d'"),
> > chr->type);
> > }
> > - goto error;
> > + goto cleanup;
> > }
> >
> > if (virJSONValueObjectAppendString(backend, "type", backend_type) < 0 ||
> > virJSONValueObjectAppend(backend, "data", data) < 0)
> > - goto error;
> > - data = NULL;
> > + goto cleanup;
> >
> > if (!(ret = qemuMonitorJSONMakeCommand("chardev-add",
> > "s:id", chrID,
> > "a:backend", backend,
> > NULL)))
> > - goto error;
> > + goto cleanup;
> >
> > - return ret;
> > + /* we must not free the following pointers as they've been collectively
> > + * consumed by @ret, so clear them first
> > + */
> > + addr = data = backend = NULL;
>
> Eww, this is not a good idea, just leave the clearing at the original
Since you didn't elaborate more on ^^why, I'll just add it here for reference -
it might happen that @addr or @data would be both freed --> double free, so I'll
drop this hunk in v2 and clear only @backend as suggested.
Erik
> place. You should clear only @backend here.
>
> Pavel
More information about the libvir-list
mailing list