[libvirt] [PATCH] libxl: unref objects in error paths

Jim Fehlig jfehlig at suse.com
Thu Feb 25 18:51:12 UTC 2016


Michal Privoznik wrote:
> On 24.02.2016 23:55, Jim Fehlig wrote:
>> libxlMakeNic opens a virConnect object and takes a reference on a
>> virNetwork object, but doesn't drop the references on all error
>> paths. Rework the function to follow the standard libvirt pattern
>> of using a local 'ret' variable to hold the function return value,
>> performing all cleanup and returning 'ret' at a 'cleanup' label.
>>
>> Signed-off-by: Jim Fehlig <jfehlig at suse.com>
>> ---
>>
>> I noticed these leaks while trying to rework the code to use a
>> common virConnect object. That task has turned into quite an
>> effort [1], but in the meantime the leaks in the current code
>> should be plugged.
>>
>> [1] https://www.redhat.com/archives/libvir-list/2016-February/msg01188.html
>>
>>  src/libxl/libxl_conf.c | 57 ++++++++++++++++++++++++--------------------------
>>  1 file changed, 27 insertions(+), 30 deletions(-)
>>
>> diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c
>> index b20df29..763f4c5 100644
>> --- a/src/libxl/libxl_conf.c
>> +++ b/src/libxl/libxl_conf.c
>> @@ -1286,7 +1286,11 @@ libxlMakeNic(virDomainDefPtr def,
>>  {
>>      bool ioemu_nic = def->os.type == VIR_DOMAIN_OSTYPE_HVM;
>>      virDomainNetType actual_type = virDomainNetGetActualType(l_nic);
>> +    char *brname = NULL;
>> +    virNetworkPtr network = NULL;
>> +    virConnectPtr conn = NULL;
>>      virNetDevBandwidthPtr actual_bw;
>> +    int ret = -1;
>>  
>>      /* TODO: Where is mtu stored?
>>       *
>> @@ -1312,64 +1316,50 @@ libxlMakeNic(virDomainDefPtr def,
>>  
>>      if (l_nic->model) {
>>          if (VIR_STRDUP(x_nic->model, l_nic->model) < 0)
>> -            return -1;
>> +            goto cleanup;
>>          if (STREQ(l_nic->model, "netfront"))
>>              x_nic->nictype = LIBXL_NIC_TYPE_VIF;
>>      }
>>  
>>      if (VIR_STRDUP(x_nic->ifname, l_nic->ifname) < 0)
>> -        return -1;
>> +        goto cleanup;
>>  
>>      switch (actual_type) {
>>          case VIR_DOMAIN_NET_TYPE_BRIDGE:
>>              if (VIR_STRDUP(x_nic->bridge,
>>                             virDomainNetGetActualBridgeName(l_nic)) < 0)
>> -                return -1;
>> +                goto cleanup;
>>              /* fallthrough */
>>          case VIR_DOMAIN_NET_TYPE_ETHERNET:
>>              if (VIR_STRDUP(x_nic->script, l_nic->script) < 0)
>> -                return -1;
>> +                goto cleanup;
>>              if (l_nic->nips > 0) {
>>                  x_nic->ip = virSocketAddrFormat(&l_nic->ips[0]->address);
>>                  if (!x_nic->ip)
>> -                    return -1;
>> +                    goto cleanup;
>>              }
>>              break;
>>          case VIR_DOMAIN_NET_TYPE_NETWORK:
>>          {
>> -            bool fail = false;
>> -            char *brname = NULL;
>> -            virNetworkPtr network;
>> -            virConnectPtr conn;
>> -
>>              if (!(conn = virConnectOpen("xen:///system")))
>> -                return -1;
>> +                goto cleanup;
>>  
>>              if (!(network =
>>                    virNetworkLookupByName(conn, l_nic->data.network.name))) {
>> -                virObjectUnref(conn);
>> -                return -1;
>> +                goto cleanup;
>>              }
>>  
>>              if (l_nic->nips > 0) {
>>                  x_nic->ip = virSocketAddrFormat(&l_nic->ips[0]->address);
>>                  if (!x_nic->ip)
>> -                    return -1;
>> +                    goto cleanup;
>>              }
>>  
>> -            if ((brname = virNetworkGetBridgeName(network))) {
>> -                if (VIR_STRDUP(x_nic->bridge, brname) < 0)
>> -                    fail = true;
>> -            } else {
>> -                fail = true;
>> -            }
>> -
>> -            VIR_FREE(brname);
>> +            if (!(brname = virNetworkGetBridgeName(network)))
>> +                goto cleanup;
>>  
>> -            virObjectUnref(network);
>> -            virObjectUnref(conn);
>> -            if (fail)
>> -                return -1;
>> +            if (VIR_STRDUP(x_nic->bridge, brname) < 0)
>> +                    goto cleanup;
> 
> How about switching pointers instead of yet another strdup?

Ah, good point. In fact, the brname local can be dropped and the result of
virNetworkGetBridgeName assigned directly to x_nic->bridge. E.g.

  if (!(x_nic->bridge = virNetworkGetBridgeName(network)))
      goto cleanup;

> x_nic->bridge = brname;
> brname = NULL;
> 
> And as Joao already pointed out, the indentation of 'goto' is a bit off.
> Otherwise looking good. ACK and safe for the freeze.

I've made the above change and pushed the patch. Thanks!

Regards,
Jim




More information about the libvir-list mailing list