]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
auth: Aborting pending async requests on deinit caused crashes.
authorTimo Sirainen <tss@iki.fi>
Tue, 1 Jun 2010 15:37:59 +0000 (16:37 +0100)
committerTimo Sirainen <tss@iki.fi>
Tue, 1 Jun 2010 15:37:59 +0000 (16:37 +0100)
--HG--
branch : HEAD

src/auth/auth-client-connection.c
src/auth/auth-request-handler.c
src/auth/auth-request-handler.h
src/auth/auth-request.c

index ee47eda19ec631f8d820bf9b1bf58edb1dd5805b..4c70aedafeed58f92d3bc8a7de6b2bf390a32d9f 100644 (file)
@@ -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);
index 99bb7e9a82b89038fbdf0876c30571b7875a1193..feb292f97090da55101dc8ab15268787c908d198 100644 (file)
@@ -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)
index 02f75e6425eafe1f643bfb82ae2dc5f4bb725980..2391282327fc5fe71c9c05608114909eea742f32 100644 (file)
@@ -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,
index 77b5f4ade63d46f11e147621aa591aaed77cc697..0ef4d839e71fe0c66fb139e802f764cf11a10b53 100644 (file)
@@ -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)