[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