From fbee9bffb56d882b98146dd0de76a5bcccc2bdc3 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Tue, 1 Jun 2010 16:37:59 +0100 Subject: [PATCH] auth: Aborting pending async requests on deinit caused crashes. --HG-- branch : HEAD --- src/auth/auth-client-connection.c | 2 +- src/auth/auth-request-handler.c | 21 ++++++++++++++++++++- src/auth/auth-request-handler.h | 4 +++- src/auth/auth-request.c | 16 ++++++++++++++++ 4 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/auth/auth-client-connection.c b/src/auth/auth-client-connection.c index ee47eda19e..4c70aedafe 100644 --- a/src/auth/auth-client-connection.c +++ b/src/auth/auth-client-connection.c @@ -348,7 +348,7 @@ void auth_client_connection_destroy(struct auth_client_connection **_conn) conn->fd = -1; if (conn->request_handler != NULL) - auth_request_handler_unref(&conn->request_handler); + auth_request_handler_destroy(&conn->request_handler); master_service_client_connection_destroyed(master_service); auth_client_connection_unref(&conn); diff --git a/src/auth/auth-request-handler.c b/src/auth/auth-request-handler.c index 99bb7e9a82..feb292f970 100644 --- a/src/auth/auth-request-handler.c +++ b/src/auth/auth-request-handler.c @@ -29,6 +29,8 @@ struct auth_request_handler { void *context; auth_request_callback_t *master_callback; + + unsigned int destroyed:1; }; static ARRAY_DEFINE(auth_failures_arr, struct auth_request *); @@ -57,7 +59,7 @@ auth_request_handler_create(auth_request_callback_t *callback, void *context, return handler; } -void auth_request_handler_unref(struct auth_request_handler **_handler) +static void auth_request_handler_unref(struct auth_request_handler **_handler) { struct auth_request_handler *handler = *_handler; struct hash_iterate_context *iter; @@ -83,6 +85,23 @@ void auth_request_handler_unref(struct auth_request_handler **_handler) pool_unref(&handler->pool); } +void auth_request_handler_destroy(struct auth_request_handler **_handler) +{ + struct auth_request_handler *handler = *_handler; + + *_handler = NULL; + + i_assert(!handler->destroyed); + + handler->destroyed = TRUE; + auth_request_handler_unref(&handler); +} + +bool auth_request_handler_is_destroyed(struct auth_request_handler *handler) +{ + return handler->destroyed; +} + void auth_request_handler_set(struct auth_request_handler *handler, unsigned int connect_uid, unsigned int client_pid) diff --git a/src/auth/auth-request-handler.h b/src/auth/auth-request-handler.h index 02f75e6425..2391282327 100644 --- a/src/auth/auth-request-handler.h +++ b/src/auth/auth-request-handler.h @@ -23,7 +23,9 @@ auth_request_handler_create(auth_request_callback_t *callback, void *context, (auth_request_callback_t *)callback, context, \ master_callback) #endif -void auth_request_handler_unref(struct auth_request_handler **handler); +void auth_request_handler_destroy(struct auth_request_handler **handler); + +bool auth_request_handler_is_destroyed(struct auth_request_handler *handler); void auth_request_handler_set(struct auth_request_handler *handler, unsigned int connect_uid, diff --git a/src/auth/auth-request.c b/src/auth/auth-request.c index 77b5f4ade6..0ef4d839e7 100644 --- a/src/auth/auth-request.c +++ b/src/auth/auth-request.c @@ -13,6 +13,7 @@ #include "var-expand.h" #include "auth-cache.h" #include "auth-request.h" +#include "auth-request-handler.h" #include "auth-client-connection.h" #include "auth-master-connection.h" #include "passdb.h" @@ -389,6 +390,13 @@ auth_request_handle_passdb_callback(enum passdb_result *result, strlen(request->passdb_password)); } + if (auth_request_handler_is_destroyed(request->handler)) { + /* the passdb may have been freed already. this request won't + be sent anywhere anyway, so just fail it immediately. */ + *result = PASSDB_RESULT_INTERNAL_FAILURE; + return TRUE; + } + if (request->passdb->set->deny && *result != PASSDB_RESULT_USER_UNKNOWN) { /* deny passdb. we can get through this step only if the @@ -734,6 +742,14 @@ void auth_request_userdb_callback(enum userdb_result result, { struct userdb_module *userdb = request->userdb->userdb; + if (auth_request_handler_is_destroyed(request->handler)) { + /* the userdb may have been freed already. this request won't + be sent anywhere anyway, so just fail it immediately. */ + request->private_callback. + userdb(USERDB_RESULT_INTERNAL_FAILURE, request); + return; + } + if (result != USERDB_RESULT_OK && request->userdb->next != NULL) { /* try next userdb. */ if (result == USERDB_RESULT_INTERNAL_FAILURE) -- 2.47.3