manager: avoid that auto-activations preempt user activations

In _internal_activate_device(), we try to find an existing master AC
for the slave AC, and we create a new one in case of failure. The
master AC may already exist, but it may not be detected by
find_master() because it is undergoing authorization.

The result is that we auto-activate the master when there is already a
user activation in place, and the auto-activation will cancel the user
one. This is bad, as user-activation should always have precedence.

To fix this, introduce a last-minute check before activating internal
connections.

https://bugzilla.redhat.com/show_bug.cgi?id=1450219
This commit is contained in:
Beniamino Galvani
2017-06-16 10:59:35 +02:00
parent 02d56ec87c
commit 0922a17738

View File

@@ -3580,10 +3580,36 @@ _internal_activation_auth_done (NMActiveConnection *active,
{
NMManager *self = user_data1;
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
NMActiveConnection *candidate;
GError *error = NULL;
GSList *iter;
priv->authorizing_connections = g_slist_remove (priv->authorizing_connections, active);
/* Don't continue with the activation if an equivalent active connection
* already exists. We also check this earlier, but there we may fail to
* detect a duplicate if the existing active connection is undergoing
* authorization in impl_manager_activate_connection().
*/
if (success && nm_auth_subject_is_internal (nm_active_connection_get_subject (active))) {
for (iter = priv->active_connections; iter; iter = iter->next) {
candidate = iter->data;
if ( nm_active_connection_get_device (candidate) == nm_active_connection_get_device (active)
&& nm_active_connection_get_settings_connection (candidate) == nm_active_connection_get_settings_connection (active)
&& NM_IN_SET (nm_active_connection_get_state (candidate),
NM_ACTIVE_CONNECTION_STATE_ACTIVATING,
NM_ACTIVE_CONNECTION_STATE_ACTIVATED)) {
g_set_error (&error,
NM_MANAGER_ERROR,
NM_MANAGER_ERROR_CONNECTION_ALREADY_ACTIVE,
"Connection '%s' is already active",
nm_active_connection_get_settings_connection_id (active));
success = FALSE;
break;
}
}
}
if (success) {
if (_internal_activate_generic (self, active, &error)) {
g_object_unref (active);