summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2014-06-11 13:40:19 -0500
committerDan Williams <dcbw@redhat.com>2014-06-12 15:52:54 -0500
commit015958da6617215b1d96521486128e7170a80b5a (patch)
treef58feecc5655281feaab934db8dae1bb485a0deb
parent120bd702436317a5f40cda296d628a30596ff4c7 (diff)
downloadNetworkManager-dcbw/settings-fixes.tar.gz
ifnet: fix use-after-free and refcounting of invalid changed connectionsdcbw/settings-fixes
If a valid connection was updated and still valid, and then was updated and become invalid, the connection would not be properly removed from the ifnet plugin's priv->connections hash, and thus would never be disposed. This was due to using the direct pointer to the connection's UUID as the key for the hash table. When a connection is updated and its settings are replaced, the old UUID is freed and replaced with a new pointer. But the ifnet plugin hash table still uses the old (now freed) UUID pointer as the key. Thus when the connection is updated and becomes invalid, looking up the UUID in the hash table fails to find the connection, and the connection is not removed from the hash. This bug could cause a crash in some cases, if two keys of the GHashTable hashed to the same value, in which case GLib would call g_str_equal() on the freed pointer. Since code other than in the ifnet plugin replaces settings, we cannot be guaranteed that the pointer won't change. Avoid all that and just strdup() the UUID when using it as a key.
-rw-r--r--src/settings/plugins/ifnet/plugin.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/src/settings/plugins/ifnet/plugin.c b/src/settings/plugins/ifnet/plugin.c
index bc7b35c22c..ab07b8d627 100644
--- a/src/settings/plugins/ifnet/plugin.c
+++ b/src/settings/plugins/ifnet/plugin.c
@@ -231,7 +231,7 @@ static void
track_new_connection (SCPluginIfnet *self, NMIfnetConnection *connection)
{
g_hash_table_insert (SC_PLUGIN_IFNET_GET_PRIVATE (self)->connections,
- (gpointer) nm_connection_get_uuid (NM_CONNECTION (connection)),
+ g_strdup (nm_connection_get_uuid (NM_CONNECTION (connection))),
g_object_ref (connection));
g_signal_connect (connection, NM_SETTINGS_CONNECTION_REMOVED,
G_CALLBACK (connection_removed_cb),
@@ -432,7 +432,7 @@ init (NMSystemConfigInterface *config)
nm_log_info (LOGD_SETTINGS, "Initializing!");
- priv->connections = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
+ priv->connections = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
priv->unmanaged_well_known = !is_managed_plugin ();
nm_log_info (LOGD_SETTINGS, "management mode: %s",
priv->unmanaged_well_known ? "unmanaged" : "managed");