summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2018-04-09 12:36:06 +0200
committerThomas Haller <thaller@redhat.com>2018-04-13 09:09:46 +0200
commit290d02536c237cd14f187611e72e5fc0b52c81a7 (patch)
treefe8555c8e4e2275686e25ff2df87babb5b8e5a9d
parent50b74731f668067d445a28d7e545a169bf9d25c8 (diff)
downloadNetworkManager-290d02536c237cd14f187611e72e5fc0b52c81a7.tar.gz
auth-chain: avoid another idle-call when auth-request completes
NMAuthChain schedules (possibly) multiple authentication requests. When they all complete, it will once invoke the result-callback. There is no need to schedule this result-callback on another idle-handler, because nm_auth_manager_polkit_authority_check_authorization() should guarantee to invoke the callback never-synchronously and on a clean call-stack (to avoid problems with re-entrancy). At that point, NMAuthChain does not need to delay this further.
-rw-r--r--src/nm-auth-manager.c3
-rw-r--r--src/nm-auth-utils.c27
2 files changed, 14 insertions, 16 deletions
diff --git a/src/nm-auth-manager.c b/src/nm-auth-manager.c
index 003d997505..d1b8d91e1d 100644
--- a/src/nm-auth-manager.c
+++ b/src/nm-auth-manager.c
@@ -240,6 +240,9 @@ _call_check_authorization (CheckAuthData *data)
data->dbus_parameters = NULL;
}
+/*
+ * @callback must never be invoked synchronously.
+ */
void
nm_auth_manager_polkit_authority_check_authorization (NMAuthManager *self,
NMAuthSubject *subject,
diff --git a/src/nm-auth-utils.c b/src/nm-auth-utils.c
index da5843b0bf..3c5440eb2b 100644
--- a/src/nm-auth-utils.c
+++ b/src/nm-auth-utils.c
@@ -44,8 +44,6 @@ struct NMAuthChain {
NMAuthChainResultFunc done_func;
gpointer user_data;
- guint idle_id;
-
guint32 refcount;
bool done:1;
@@ -209,16 +207,15 @@ nm_auth_chain_get_subject (NMAuthChain *self)
/*****************************************************************************/
static gboolean
-auth_chain_finish (gpointer user_data)
+auth_chain_finish (NMAuthChain *self)
{
- NMAuthChain *self = user_data;
-
- self->idle_id = 0;
self->done = TRUE;
/* Ensure we stay alive across the callback */
+ nm_assert (self->refcount == 1);
self->refcount++;
self->done_func (self, NULL, self->context, self->user_data);
+ nm_assert (NM_IN_SET (self->refcount, 1, 2));
nm_auth_chain_destroy (self);
return FALSE;
}
@@ -232,14 +229,14 @@ auth_call_complete (AuthCall *call)
self = call->chain;
- c_list_unlink (&call->auth_call_lst);
+ nm_assert (!self->done);
+
+ auth_call_free (call);
if (c_list_is_empty (&self->auth_call_lst_head)) {
- nm_assert (!self->idle_id && !self->done);
- self->idle_id = g_idle_add (auth_chain_finish, self);
+ /* we are on an idle-handler or a clean call-stack (non-reentrant). */
+ auth_chain_finish (self);
}
-
- auth_call_free (call);
}
static gboolean
@@ -307,10 +304,10 @@ nm_auth_chain_add_call (NMAuthChain *self,
NMAuthManager *auth_manager = nm_auth_manager_get ();
g_return_if_fail (self);
- g_return_if_fail (permission && *permission);
g_return_if_fail (self->subject);
+ g_return_if_fail (!self->done);
+ g_return_if_fail (permission && *permission);
g_return_if_fail (nm_auth_subject_is_unix_process (self->subject) || nm_auth_subject_is_internal (self->subject));
- g_return_if_fail (!self->idle_id && !self->done);
call = g_slice_new0 (AuthCall);
call->chain = self;
@@ -412,13 +409,11 @@ nm_auth_chain_destroy (NMAuthChain *self)
AuthCall *call;
g_return_if_fail (self);
- g_return_if_fail (self->refcount > 0);
+ g_return_if_fail (NM_IN_SET (self->refcount, 1, 2));
if (--self->refcount > 0)
return;
- nm_clear_g_source (&self->idle_id);
-
nm_clear_g_object (&self->subject);
nm_clear_g_object (&self->context);