Blob Blame History Raw
From 222d392527d3c74d31d08166eb1580b9c4f5204f Mon Sep 17 00:00:00 2001
From: Thomas Haller <thaller@redhat.com>
Date: Wed, 11 Jun 2014 16:47:07 +0200
Subject: [PATCH 1/1] core: fix deactivation of assumed connections on device
 removal (bgo #729833)

The following procedure leaves an NMActiveConnection around for a deactivated
device, which causes errors in libnm-glib clients when they cannot create the
GObject for the non-existent device of the AC.

1) allow a device which can assume connections to be activated
2) stop NM, which should leave the device's IP configuration up
3) start NM and allow it to assume the device's existing connection
4) remove the device, either by unplugging it or 'rmmod'

The device is removed by nm-manager.c::remove_device(), but the device object
is not moved to UNMANAGED state, leaving the NMActiveConnection completely
unaware the device has gone away.

The nm-manager.c::remove_device() code did not correctly handle moving a
forcibly removed (eg, by unplugging or 'ip link del' or 'rmmod') device to
the UNMANAGED state when the device was active with an assumed connection.
To fix this, make the conditions when the device should be deactivated
on removal much more explicit.

A device should be deactivated on removal if:

1) it is forcibly removed, eg by the kernel network interface being
removed due to 'ip link del' or hotplugging, or internally by NM due
to a parent WWAN interface taking priority over a WWAN ethernet interface

2) if the device cannot assume connections, in which case NetworkManager
must have activated the device and since we cannot assume the connection
on restart, we should deactivate it

3) if the device is not activated, to ensure that its IPv6 parameters
and other things get reset to the pre-NetworkManager values

https://bugzilla.gnome.org/show_bug.cgi?id=729833
https://bugzilla.gnome.org/show_bug.cgi?id=731277
https://bugzilla.redhat.com/show_bug.cgi?id=1108167
Related: https://bugzilla.gnome.org/show_bug.cgi?id=729832

(cherry picked from commit 4b6f0d50a456a29e17785fb8b13c11ce018b31db)

Signed-off-by: Thomas Haller <thaller@redhat.com>
---
 src/nm-manager.c | 29 ++++++++++++++++-------------
 1 file changed, 16 insertions(+), 13 deletions(-)

diff --git a/src/nm-manager.c b/src/nm-manager.c
index b7e89d7..d45226b 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -746,20 +746,23 @@ remove_device (NMManager *manager, NMDevice *device, gboolean quitting)
 	NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
 
 	if (nm_device_get_managed (device)) {
-		/* Leave configured interfaces up when quitting so they can be
-		 * taken over again if NM starts up, and to ensure connectivity while
-		 * NM is gone.  Assumed connections don't get taken down even if they
-		 * haven't been fully activated.
-		 */
-
-		if (   !nm_device_can_assume_connections (device)
-		    || (nm_device_get_state (device) != NM_DEVICE_STATE_ACTIVATED)
-		    || !quitting) {
-				NMActRequest *req = nm_device_get_act_request (device);
+		NMActRequest *req = nm_device_get_act_request (device);
+		gboolean unmanage = FALSE;
 
-				if (!req || !nm_active_connection_get_assumed (NM_ACTIVE_CONNECTION (req)))
-					nm_device_set_manager_managed (device, FALSE, NM_DEVICE_STATE_REASON_REMOVED);
-			}
+		/* Leave activated interfaces up when quitting so their configuration
+		 * can be taken over when NM restarts.  This ensures connectivity while
+		 * NM is stopped. Devices which do not support connection assumption
+		 * cannot be left up.
+		 */
+		if (!quitting)  /* Forced removal; device already gone */
+			unmanage = TRUE;
+		else if (!nm_device_can_assume_connections (device))
+			unmanage = TRUE;
+		else if (!req)
+			unmanage = TRUE;
+
+		if (unmanage)
+			nm_device_set_manager_managed (device, FALSE, NM_DEVICE_STATE_REASON_REMOVED);
 	}
 
 	g_signal_handlers_disconnect_matched (device, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, manager);
-- 
1.8.3.1