From da72f276cd067c76c38b6cf3d706e20b7da366f5 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 17 Jul 2019 11:01:07 +0200 Subject: [PATCH] settings: write tombstones when deleting connection with duplicate files on disk Create such duplicate files: UUID=0df1bac3-1131-42d4-8893-4492d5424d11 rm -f /etc/NetworkManager/system-connections/x[12] rm -f /{etc,run}/NetworkManager/system-connections/"$UUID".nmmeta printf -v C "[connection]\nuuid=$UUID\ntype=ethernet\nautoconnect=false" echo "$C" > /etc/NetworkManager/system-connections/x1 echo "$C" > /etc/NetworkManager/system-connections/x2 chmod 600 /etc/NetworkManager/system-connections/x[12] touch /etc/NetworkManager/system-connections/x2 ls -l --full-time /etc/NetworkManager/system-connections/x[12] /{etc,run}/NetworkManager/system-connections/"$UUID".nmmeta 2>/dev/null nmcli connection reload nmcli -f all connection show | grep $UUID Now, we have x2 file loaded, and x1 is shadowed. When we delete x2, we probably don't want to delete the hidden x1 file. What previously happend was that when calling nmcli connection delete $UUID the command would hang because the profile wasn't really deleted: [1563355597.3671] keyfile: commit: deleted "/etc/NetworkManager/system-connections/x2", profile 0df1bac3-1131-42d4-8893-4492d5424d11 (deleted from disk) [1563355597.3672] settings: storage[0df1bac3-1131-42d4-8893-4492d5424d11,91e13003dd84928f/keyfile]: change event for dropping profile (file "/etc/NetworkManager/system-connections/x2") [1563355597.3672] settings: update[0df1bac3-1131-42d4-8893-4492d5424d11]: updating connection "x1" (2b798d30d43b0daf/keyfile) [1563355597.3674] ++ connection 'update connection' (0x55a167693ee0/NMSimpleConnection/"802-3-ethernet" < 0x55a16762e580/NMSimpleConnection/"802-3-ethernet") [/org/freedesktop/NetworkManager/Settings/41]: [1563355597.3675] ++ connection [ 0x55a16782a400 < 0x55a16762c350 ] [1563355597.3675] ++ connection.id = 'x1' < 'x2' [1563355597.3680] audit: op="connection-delete" uuid="0df1bac3-1131-42d4-8893-4492d5424d11" name="x1" pid=32077 uid=0 result="success" instead, we need to write a tombstone: [1563359300.2910] keyfile: commit: deleted "/etc/NetworkManager/system-connections/x2", profile 0df1bac3-1131-42d4-8893-4492d5424d11 (deleted from disk) [1563359300.2911] settings: storage[0df1bac3-1131-42d4-8893-4492d5424d11,0c12620295ac7f83/keyfile]: change event for dropping profile (file "/etc/NetworkManager/system-connections/> [1563359300.2912] keyfile: commit: writing nmmeta symlink "/etc/NetworkManager/system-connections/0df1bac3-1131-42d4-8893-4492d5424d11.nmmeta" (pointing to "/dev/null") succeeded [1563359300.2912] settings: storage[0df1bac3-1131-42d4-8893-4492d5424d11,02a430e6ee52358d/keyfile]: change event for hiding profile (file "/etc/NetworkManager/system-connections/0d> [1563359300.2912] settings: update[0df1bac3-1131-42d4-8893-4492d5424d11]: delete connection "x2" (02a430e6ee52358d/keyfile) [1563359300.2914] Deleting secrets for connection /org/freedesktop/NetworkManager/Settings (x2) [1563359300.2915] dbus-object[13d79ec95177f9eb]: unexport: "/org/freedesktop/NetworkManager/Settings/54" [1563359300.2916] settings-connection[13d79ec95177f9eb,0df1bac3-1131-42d4-8893-4492d5424d11]: update settings-connection flags to none (was visible) [1563359300.2917] audit: op="connection-delete" uuid="0df1bac3-1131-42d4-8893-4492d5424d11" name="x2" pid=22572 uid=0 result="success" [1563359300.2918] settings-connection[13d79ec95177f9eb,0df1bac3-1131-42d4-8893-4492d5424d11]: disposing and of course after a `nmcli connection reload` the profile stays hidden: [1563359412.0355] settings: storage[0df1bac3-1131-42d4-8893-4492d5424d11,e45535721abb092a/keyfile]: change event with connection "x1" (file "/etc/NetworkManager/system-connections/x1") [1563359412.0355] settings: storage[0df1bac3-1131-42d4-8893-4492d5424d11,02a430e6ee52358d/keyfile]: change event for hiding profile (file "/etc/NetworkManager/system-connections/0df1bac3-1131-42d4-8893-4492d5424d11.nmmeta") --- src/settings/nm-settings.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c index ef242e564..acfede712 100644 --- a/src/settings/nm-settings.c +++ b/src/settings/nm-settings.c @@ -729,6 +729,7 @@ _sett_conn_entry_sds_update_cmp (const CList *ls_a, const CList *ls_b, gconstpointer user_data) { + const GSList *plugins = user_data; StorageData *sd_a = c_list_entry (ls_a, StorageData, sd_lst); StorageData *sd_b = c_list_entry (ls_b, StorageData, sd_lst); @@ -740,7 +741,7 @@ _sett_conn_entry_sds_update_cmp (const CList *ls_a, * would expect). * * We want to sort the list in reverse though, with highest priority first. */ - return nm_settings_storage_cmp (sd_b->storage, sd_a->storage, user_data); + return nm_settings_storage_cmp (sd_b->storage, sd_a->storage, plugins); } static void @@ -1798,7 +1799,7 @@ nm_settings_delete_connection (NMSettings *self, NMSettingsPrivate *priv; NMSettingsStorage *cur_storage; gs_free_error GError *local = NULL; - SettConnEntry *sett_conn_entry = NULL; + SettConnEntry *sett_conn_entry; const char *uuid; gboolean delete; gboolean tombstone_in_memory = FALSE; @@ -1823,7 +1824,7 @@ nm_settings_delete_connection (NMSettings *self, g_return_if_fail (sett_conn_entry); nm_assert (sett_conn_entry->sett_conn == sett_conn); - nm_assert (sett_conn_entry->storage == cur_storage); + g_return_if_fail (sett_conn_entry->storage == cur_storage); if (NMS_IS_KEYFILE_STORAGE (cur_storage)) { NMSKeyfileStorage *s = NMS_KEYFILE_STORAGE (cur_storage); @@ -1839,6 +1840,8 @@ nm_settings_delete_connection (NMSettings *self, delete = TRUE; if (delete) { + StorageData *sd; + if (!nm_settings_plugin_delete_connection (nm_settings_storage_get_plugin (cur_storage), cur_storage, &local)) { @@ -1850,7 +1853,24 @@ nm_settings_delete_connection (NMSettings *self, * cannot do better than warn. Proceed... */ tombstone_in_memory = TRUE; } - _connection_changed_track (self, cur_storage, NULL, FALSE); + + sett_conn_entry = _connection_changed_track (self, cur_storage, NULL, FALSE); + + c_list_for_each_entry (sd, &sett_conn_entry->sd_lst_head, sd_lst) { + if (sd->storage == cur_storage) + continue; + if (nm_settings_storage_is_keyfile_tombstone (sd->storage)) + continue; + if (!_storage_data_is_alive (sd)) + continue; + + /* we have still conflicting storages. We need to hide them with tombstones. */ + if (nm_settings_storage_is_keyfile_run (sd->storage)) { + tombstone_in_memory = TRUE; + continue; + } + tombstone_on_disk = TRUE; + } } if (tombstone_on_disk) {