libnm: validate settings in _nm_connection_verify() in defined order

Fully sort the settings in _nm_connection_verify(). Previously, only the
NMSettingConnection instance was sorted first (as required). The remaining
settings were in undefined order. That means, we would validate settings
in undefined order, and if multiple settings have an issue, the reported
error would be undefined.

Instead, use nm_connection_get_settings() which fully sorts the settings
(and of course, sorts NMSettingConnection first as we require it).

Also, this way we no longer need to allocate multiple GSList instances
but only malloc() one array large enough to contain all settings.
This commit is contained in:
Thomas Haller
2020-02-17 17:27:27 +01:00
parent 0718098dcb
commit f3dd41ad7e

View File

@@ -1404,24 +1404,19 @@ nm_connection_verify (NMConnection *connection, GError **error)
NMSettingVerifyResult
_nm_connection_verify (NMConnection *connection, GError **error)
{
NMConnectionPrivate *priv;
NMSettingConnection *s_con;
NMSettingIPConfig *s_ip4, *s_ip6;
NMSettingProxy *s_proxy;
GHashTableIter iter;
gpointer value;
GSList *all_settings = NULL, *setting_i;
gs_free NMSetting **settings = NULL;
gs_free_error GError *normalizable_error = NULL;
NMSettingVerifyResult normalizable_error_type = NM_SETTING_VERIFY_SUCCESS;
guint i;
g_return_val_if_fail (NM_IS_CONNECTION (connection), NM_SETTING_VERIFY_ERROR);
g_return_val_if_fail (!error || !*error, NM_SETTING_VERIFY_ERROR);
priv = NM_CONNECTION_GET_PRIVATE (connection);
/* First, make sure there's at least 'connection' setting */
s_con = nm_connection_get_setting_connection (connection);
if (!s_con) {
settings = nm_connection_get_settings (connection, NULL);
if ( !settings
|| !NM_IS_SETTING_CONNECTION (settings[0])) {
g_set_error_literal (error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_MISSING_SETTING,
@@ -1430,25 +1425,13 @@ _nm_connection_verify (NMConnection *connection, GError **error)
return NM_SETTING_VERIFY_ERROR;
}
/* Build up the list of settings */
g_hash_table_iter_init (&iter, priv->settings);
while (g_hash_table_iter_next (&iter, NULL, &value)) {
/* Order NMSettingConnection so that it will be verified first.
* The reason is, that errors in this setting might be more fundamental
* and should be checked and reported with higher priority.
*/
if (value == s_con)
all_settings = g_slist_append (all_settings, value);
else
all_settings = g_slist_prepend (all_settings, value);
}
all_settings = g_slist_reverse (all_settings);
/* Now, run the verify function of each setting */
for (setting_i = all_settings; setting_i; setting_i = setting_i->next) {
for (i = 0; settings[i]; i++) {
GError *verify_error = NULL;
NMSettingVerifyResult verify_result;
nm_assert (NM_IS_SETTING (settings[i]));
nm_assert (NM_IS_SETTING_CONNECTION (settings[i]) == (i == 0));
/* verify all settings. We stop if we find the first non-normalizable
* @NM_SETTING_VERIFY_ERROR. If we find normalizable errors we continue
* but remember the error to return it to the user.
@@ -1456,7 +1439,7 @@ _nm_connection_verify (NMConnection *connection, GError **error)
* @NM_SETTING_VERIFY_NORMALIZABLE, so, if we encounter such an error type,
* we remember it instead (to return it as output).
**/
verify_result = _nm_setting_verify (NM_SETTING (setting_i->data), connection, &verify_error);
verify_result = _nm_setting_verify (settings[i], connection, &verify_error);
if (verify_result == NM_SETTING_VERIFY_NORMALIZABLE ||
verify_result == NM_SETTING_VERIFY_NORMALIZABLE_ERROR) {
if ( verify_result == NM_SETTING_VERIFY_NORMALIZABLE_ERROR
@@ -1471,13 +1454,11 @@ _nm_connection_verify (NMConnection *connection, GError **error)
}
} else if (verify_result != NM_SETTING_VERIFY_SUCCESS) {
g_propagate_error (error, verify_error);
g_slist_free (all_settings);
g_return_val_if_fail (verify_result == NM_SETTING_VERIFY_ERROR, NM_SETTING_VERIFY_ERROR);
return NM_SETTING_VERIFY_ERROR;
}
g_clear_error (&verify_error);
}
g_slist_free (all_settings);
s_ip4 = nm_connection_get_setting_ip4_config (connection);
s_ip6 = nm_connection_get_setting_ip6_config (connection);