[PATCH v4 1/4] lxc: refactor lxcNetworkParseData pointers to use new structures

Julio Faracco jcfaracco at gmail.com
Thu Feb 6 01:52:32 UTC 2020


Em dom., 2 de fev. de 2020 às 22:28, Julio Faracco
<jcfaracco at gmail.com> escreveu:
>
> Struct lxcNetworkParseData is being used as a single pointer which
> iterates through LXC config lines. It means that it will be applied as a
> network each time that a new type appears. After, the same struct is
> used to populate a new network interface. This commit changes this logic
> to multiple lxcNetworkParseData to move this strcuture to an array. It
> makes more sense if we are using indexes to fill interface settings.
> This is better to improve code clarity.
>
> This commit still introduces *Legacy() functions to keep support of
> network old style definitions.
>
> Signed-off-by: Julio Faracco <jcfaracco at gmail.com>
> ---
>  src/lxc/lxc_native.c | 140 ++++++++++++++++++++++++-------------------
>  1 file changed, 77 insertions(+), 63 deletions(-)
>
> diff --git a/src/lxc/lxc_native.c b/src/lxc/lxc_native.c
> index dd2345c324..31aa666e38 100644
> --- a/src/lxc/lxc_native.c
> +++ b/src/lxc/lxc_native.c
> @@ -411,7 +411,9 @@ lxcCreateHostdevDef(int mode, int type, const char *data)
>      return hostdev;
>  }
>
> -typedef struct {
> +typedef struct _lxcNetworkParseData lxcNetworkParseData;
> +typedef lxcNetworkParseData *lxcNetworkParseDataPtr;
> +struct _lxcNetworkParseData {
>      virDomainDefPtr def;
>      char *type;
>      char *link;
> @@ -424,9 +426,14 @@ typedef struct {
>      size_t nips;
>      char *gateway_ipv4;
>      char *gateway_ipv6;
> -    bool privnet;
> -    size_t networks;
> -} lxcNetworkParseData;
> +    size_t index;
> +};
> +
> +typedef struct {
> +    size_t ndata;
> +    lxcNetworkParseDataPtr *parseData;
> +} lxcNetworkParseDataArray;
> +
>
>  static int
>  lxcAddNetworkRouteDefinition(const char *address,
> @@ -552,39 +559,6 @@ lxcAddNetworkDefinition(lxcNetworkParseData *data)
>  }
>
>
> -static int
> -lxcNetworkParseDataType(virConfValuePtr value,
> -                        lxcNetworkParseData *parseData)
> -{
> -    virDomainDefPtr def = parseData->def;
> -    size_t networks = parseData->networks;
> -    bool privnet = parseData->privnet;
> -    int status;
> -
> -    /* Store the previous NIC */
> -    status = lxcAddNetworkDefinition(parseData);
> -
> -    if (status < 0)
> -        return -1;
> -    else if (status > 0)
> -        networks++;
> -    else if (parseData->type != NULL && STREQ(parseData->type, "none"))
> -        privnet = false;
> -
> -    /* clean NIC to store a new one */
> -    memset(parseData, 0, sizeof(*parseData));
> -
> -    parseData->def = def;
> -    parseData->networks = networks;
> -    parseData->privnet = privnet;
> -
> -    /* Keep the new value */
> -    parseData->type = value->str;
> -
> -    return 0;
> -}
> -
> -
>  static int
>  lxcNetworkParseDataIPs(const char *name,
>                         virConfValuePtr value,
> @@ -633,8 +607,7 @@ lxcNetworkParseDataSuffix(const char *entry,
>
>      switch (elem) {
>      case VIR_LXC_NETWORK_CONFIG_TYPE:
> -        if (lxcNetworkParseDataType(value, parseData) < 0)
> -            return -1;
> +        parseData->type = value->str;
>          break;
>      case VIR_LXC_NETWORK_CONFIG_LINK:
>          parseData->link = value->str;
> @@ -676,12 +649,40 @@ lxcNetworkParseDataSuffix(const char *entry,
>  }
>
>
> +static lxcNetworkParseDataPtr
> +lxcNetworkGetParseDataByIndexLegacy(lxcNetworkParseDataArray *networks,
> +                                    const char *entry)
> +{
> +    int elem = virLXCNetworkConfigEntryTypeFromString(entry);
> +    size_t ndata = networks->ndata;
> +
> +    if (elem == VIR_LXC_NETWORK_CONFIG_TYPE) {
> +        /* Index was not found. So, it is time to add new *
> +         * interface and return this last position.       */
> +        if (VIR_EXPAND_N(networks->parseData, networks->ndata, 1) < 0)
> +            return NULL;
> +
> +        networks->parseData[ndata] = g_new0(lxcNetworkParseData, 1);
> +        networks->parseData[ndata]->index = networks->ndata;
> +
> +        return networks->parseData[ndata];
> +    }
> +
> +    /* Return last element added like a stack. */
> +    return networks->parseData[ndata - 1];

There is an issue here:
If someone accidentally inverts network settings sequence, libvirt
will crash with segfault due to invalid memory access. Variable @ndata
will be 0, so this function would return a pointer from index -1
(which is invalid obviously).

This example, `link` appears first instead of `type`
lxc.network.link = eth0
lxc.network.type = phys
lxc.network.name = eth1
lxc.network.ipv4 = 192.168.122.2/24
lxc.network.ipv4.gateway = 192.168.122.1

The funniest part, this issue is happening before patches.
Let me submit a fix/patch.

> +}
> +
> +
>  static int
> -lxcNetworkParseDataEntry(const char *name,
> -                         virConfValuePtr value,
> -                         lxcNetworkParseData *parseData)
> +lxcNetworkParseDataEntryLegacy(const char *name,
> +                               virConfValuePtr value,
> +                               lxcNetworkParseDataArray *networks)
>  {
>      const char *suffix = STRSKIP(name, "lxc.network.");
> +    lxcNetworkParseData *parseData;
> +
> +    if (!(parseData = lxcNetworkGetParseDataByIndexLegacy(networks, suffix)))
> +        return -1;
>
>      return lxcNetworkParseDataSuffix(suffix, value, parseData);
>  }
> @@ -690,10 +691,10 @@ lxcNetworkParseDataEntry(const char *name,
>  static int
>  lxcNetworkWalkCallback(const char *name, virConfValuePtr value, void *data)
>  {
> -    lxcNetworkParseData *parseData = data;
> +    lxcNetworkParseDataArray *networks = data;
>
>      if (STRPREFIX(name, "lxc.network."))
> -        return lxcNetworkParseDataEntry(name, value, parseData);
> +        return lxcNetworkParseDataEntryLegacy(name, value, networks);
>
>      return 0;
>  }
> @@ -702,36 +703,49 @@ static int
>  lxcConvertNetworkSettings(virDomainDefPtr def, virConfPtr properties)
>  {
>      int status;
> -    size_t i;
> -    lxcNetworkParseData data = {def, NULL, NULL, NULL, NULL,
> -                                NULL, NULL, NULL, NULL, 0,
> -                                NULL, NULL, true, 0};
> +    bool privnet = true;
> +    size_t i, j;
> +    lxcNetworkParseDataArray networks = {0, NULL};
> +    int ret = -1;
> +
> +    networks.parseData = g_new0(lxcNetworkParseDataPtr, 1);
>
> -    if (virConfWalk(properties, lxcNetworkWalkCallback, &data) < 0)
> +    if (virConfWalk(properties, lxcNetworkWalkCallback, &networks) < 0)
>          goto error;
>
> +    for (i = 0; i < networks.ndata; i++) {
> +        lxcNetworkParseDataPtr data = networks.parseData[i];
> +        data->def = def;
>
> -    /* Add the last network definition found */
> -    status = lxcAddNetworkDefinition(&data);
> +        status = lxcAddNetworkDefinition(data);
>
> -    if (status < 0)
> -        goto error;
> -    else if (status > 0)
> -        data.networks++;
> -    else if (data.type != NULL && STREQ(data.type, "none"))
> -        data.privnet = false;
> +        if (status < 0)
> +            goto error;
> +        else if (data->type != NULL && STREQ(data->type, "none"))
> +            privnet = false;
> +    }
>
> -    if (data.networks == 0 && data.privnet) {
> +    if (networks.ndata == 0 && privnet) {
>          /* When no network type is provided LXC only adds loopback */
>          def->features[VIR_DOMAIN_FEATURE_PRIVNET] = VIR_TRISTATE_SWITCH_ON;
>      }
> -    return 0;
> +
> +    ret = 0;
> +
> + cleanup:
> +    for (i = 0; i < networks.ndata; i++)
> +        VIR_FREE(networks.parseData[i]);
> +    VIR_FREE(networks.parseData);
> +    return ret;
>
>   error:
> -    for (i = 0; i < data.nips; i++)
> -        VIR_FREE(data.ips[i]);
> -    VIR_FREE(data.ips);
> -    return -1;
> +    for (i = 0; i < networks.ndata; i++) {
> +        lxcNetworkParseDataPtr data = networks.parseData[i];
> +        for (j = 0; j < data->nips; j++)
> +            VIR_FREE(data->ips[j]);
> +        VIR_FREE(data->ips);
> +    }
> +    goto cleanup;
>  }
>
>  static int
> --
> 2.20.1
>





More information about the libvir-list mailing list