From b585278b3212ec5d13f5e1cf15feb25b043f3753 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sat, 30 Apr 2016 19:26:02 -0500 Subject: [PATCH] authd: provider: make refcounting system less fragile --- authd/provider.c | 14 ++++++++------ authd/provider.h | 18 ++++++++++++++++-- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/authd/provider.c b/authd/provider.c index 8fca1a08..9bafbc15 100644 --- a/authd/provider.c +++ b/authd/provider.c @@ -167,9 +167,15 @@ unload_provider(struct auth_provider *provider) rb_dlinkAddAlloc(RB_UINT_TO_POINTER(provider->id), &free_pids); } +void +auth_client_free(struct auth_client *auth) +{ + rb_dictionary_delete(auth_clients, RB_UINT_TO_POINTER(auth->cid)); + rb_free(auth->data); + rb_free(auth); +} -/* Cancel outstanding providers for a client (if any) and free the auth instance - * WARNING: do not use auth instance after calling! */ +/* Cancel outstanding providers for a client (if any). */ void cancel_providers(struct auth_client *auth) { @@ -185,10 +191,6 @@ cancel_providers(struct auth_client *auth) provider->cancel(auth); } } - - rb_dictionary_delete(auth_clients, RB_UINT_TO_POINTER(auth->cid)); - rb_free(auth->data); - rb_free(auth); } /* Provider is done diff --git a/authd/provider.h b/authd/provider.h index a4f2ed8c..7145d07d 100644 --- a/authd/provider.h +++ b/authd/provider.h @@ -120,7 +120,21 @@ void reject_client(struct auth_client *auth, uint32_t id, const char *data, cons void handle_new_connection(int parc, char *parv[]); void handle_cancel_connection(int parc, char *parv[]); +void auth_client_free(struct auth_client *auth); +static inline void +auth_client_ref(struct auth_client *auth) +{ + auth->refcount++; +} + +static inline void +auth_client_unref(struct auth_client *auth) +{ + auth->refcount--; + if (auth->refcount == 0) + auth_client_free(auth); +} /* Get a provider by name */ static inline struct auth_provider * @@ -163,7 +177,7 @@ set_provider_status(struct auth_client *auth, uint32_t provider, provider_status static inline void set_provider_running(struct auth_client *auth, uint32_t provider) { - auth->refcount++; + auth_client_ref(auth); set_provider_status(auth, provider, PROVIDER_STATUS_RUNNING); } @@ -172,8 +186,8 @@ set_provider_running(struct auth_client *auth, uint32_t provider) static inline void set_provider_done(struct auth_client *auth, uint32_t provider) { - auth->refcount--; set_provider_status(auth, provider, PROVIDER_STATUS_DONE); + auth_client_unref(auth); } /* Check if provider is operating on this auth client */