From 87fc6e1a11086b336fbfdfd186598a044be6e998 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8D=C3=B1igo=20Huguet?= Date: Fri, 17 Nov 2023 11:23:07 +0100 Subject: [PATCH] libnm/ipv4: properly assign address-labels, and report errors from them Report an error if the data type of the address-labels received via DBus is not the expected. Also, fix the assignment of the labels to their corresponding addresses. As they are matched by array position, if any invalid address was received, the array of addresses that we generate is shorter than the array of address-labels. We were not considering this so we were assigning the address-labels to incorrect addresses. Fix it by moving the assignment of the labels to _nm_utils_ip4_addresses_from_variant, where we still have the information of what the original position in the array the address had. --- src/libnm-core-impl/nm-setting-ip4-config.c | 22 ++++------ src/libnm-core-impl/nm-utils.c | 45 ++++++++++++++++++++- src/libnm-core-intern/nm-core-internal.h | 1 + 3 files changed, 51 insertions(+), 17 deletions(-) diff --git a/src/libnm-core-impl/nm-setting-ip4-config.c b/src/libnm-core-impl/nm-setting-ip4-config.c index 9bc6b1b081..09ce3a25df 100644 --- a/src/libnm-core-impl/nm-setting-ip4-config.c +++ b/src/libnm-core-impl/nm-setting-ip4-config.c @@ -425,32 +425,24 @@ ip4_addresses_from_dbus(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS _nm_nil) { gs_unref_ptrarray GPtrArray *addrs = NULL; gs_unref_variant GVariant *s_ip4 = NULL; - gs_free const char **labels = NULL; + gs_unref_variant GVariant *labels = NULL; gs_free char *gateway = NULL; bool strict = NM_FLAGS_HAS(parse_flags, NM_SETTING_PARSE_FLAGS_STRICT); - guint i; if (!_nm_setting_use_legacy_property(setting, connection_dict, "addresses", "address-data")) { *out_is_modified = FALSE; return TRUE; } - addrs = _nm_utils_ip4_addresses_from_variant(value, &gateway, strict, error); - if (!addrs) - return FALSE; - s_ip4 = g_variant_lookup_value(connection_dict, NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_VARIANT_TYPE_SETTING); - if (g_variant_lookup(s_ip4, "address-labels", "^a&s", &labels)) { - for (i = 0; i < addrs->len && labels[i]; i++) { - if (*labels[i]) { - nm_ip_address_set_attribute(addrs->pdata[i], - NM_IP_ADDRESS_ATTRIBUTE_LABEL, - g_variant_new_string(labels[i])); - } - } - } + + labels = g_variant_lookup_value(s_ip4, "address-labels", NULL); + + addrs = _nm_utils_ip4_addresses_from_variant(value, labels, &gateway, strict, error); + if (!addrs) + return FALSE; g_object_set(setting, NM_SETTING_IP_CONFIG_ADDRESSES, diff --git a/src/libnm-core-impl/nm-utils.c b/src/libnm-core-impl/nm-utils.c index 1f206337ab..ae8bc84194 100644 --- a/src/libnm-core-impl/nm-utils.c +++ b/src/libnm-core-impl/nm-utils.c @@ -1446,25 +1446,37 @@ nm_utils_ip4_addresses_to_variant(GPtrArray *addresses, const char *gateway) GPtrArray * nm_utils_ip4_addresses_from_variant(GVariant *value, char **out_gateway) { - return _nm_utils_ip4_addresses_from_variant(value, out_gateway, FALSE, NULL); + return _nm_utils_ip4_addresses_from_variant(value, NULL, out_gateway, FALSE, NULL); } /** * _nm_utils_ip4_addresses_from_variant: * @value: a #GVariant of type 'aau' + * @labels: (optional) (nullable): a #GVariant of the type 'as'. If not-NULL, + * each element must contain a string with the labels that corresponds to each + * IP address in @value. * @out_gateway: (out) (optional) (nullable) (transfer full): on return, will * contain the IP gateway * @strict: whether to parse in strict mode or best-effort mode * @error: the error location * * Like #nm_utils_ip4_addresses_from_variant, but allows to parse in strict mode. In - * strict mode, parsing is aborted on first error and %NULL is returned. + * strict mode, parsing is aborted on first error and %NULL is returned. It also + * allows to parse the address-labels at the same time than the addresses. + * + * The labels need to be processed at the same time than the addresses, inside + * this function, because if there are invalid addresses they are filtered out, + * and the returned array of addresses contains less elements than the original + * array. If that happens, the caller don't know what label corresponds to what + * address, because they are matched by position in the array. If you are not + * interested in the labels, just set @labels to NULL. * * Returns: (transfer full) (element-type NMIPAddress): a newly allocated * #GPtrArray of #NMIPAddress objects. In strict mode, %NULL is returned on error. */ GPtrArray * _nm_utils_ip4_addresses_from_variant(GVariant *value, + GVariant *labels, char **out_gateway, bool strict, GError **error) @@ -1475,6 +1487,8 @@ _nm_utils_ip4_addresses_from_variant(GVariant *value, const guint32 *addr_array; gsize length; NMIPAddress *addr; + const char *label; + gsize n_labels = 0; guint i; addresses = g_ptr_array_new_with_free_func((GDestroyNotify) nm_ip_address_unref); @@ -1492,6 +1506,21 @@ _nm_utils_ip4_addresses_from_variant(GVariant *value, return g_steal_pointer(&addresses); } + if (labels && !g_variant_is_of_type(labels, G_VARIANT_TYPE("as"))) { + if (strict) { + g_set_error_literal(error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("Expected \"address-labels\" of type \"as\"")); + return NULL; + } + /* We still can parse the addresses, without the labels */ + labels = NULL; + } + + if (labels) + n_labels = g_variant_n_children(labels); + g_variant_iter_init(&iter, value); for (i = 0; g_variant_iter_next(&iter, "@au", &item); i++) { @@ -1525,6 +1554,18 @@ _nm_utils_ip4_addresses_from_variant(GVariant *value, continue; } + /* We were accepting address-labels to be shorter than addresses, so + * let's continue doing so and not consider it as an error */ + if (labels && i < n_labels) { + g_variant_get_child(labels, i, "&s", &label); + + if (label && label[0]) { + nm_ip_address_set_attribute(addr, + NM_IP_ADDRESS_ATTRIBUTE_LABEL, + g_variant_new_string(label)); + } + } + g_ptr_array_add(addresses, addr); if (addr_array[2] && out_gateway && !*out_gateway) *out_gateway = nm_inet4_ntop_dup(addr_array[2]); diff --git a/src/libnm-core-intern/nm-core-internal.h b/src/libnm-core-intern/nm-core-internal.h index 2b486f8b88..16b03bc4dd 100644 --- a/src/libnm-core-intern/nm-core-internal.h +++ b/src/libnm-core-intern/nm-core-internal.h @@ -1086,6 +1086,7 @@ char **_nm_utils_ip4_dns_from_variant(GVariant *value, bool strict, GError **err GPtrArray *_nm_utils_ip4_routes_from_variant(GVariant *value, bool strict, GError **error); GPtrArray *_nm_utils_ip4_addresses_from_variant(GVariant *value, + GVariant *labels, char **out_gateway, bool strict, GError **error);