dovecot-2.0: auth: Aborting pending async requests on deinit cau...

dovecot at dovecot.org dovecot at dovecot.org
Tue Jun 1 18:38:03 EEST 2010


details:   http://hg.dovecot.org/dovecot-2.0/rev/3ef582c3fb72
changeset: 11441:3ef582c3fb72
user:      Timo Sirainen <tss at iki.fi>
date:      Tue Jun 01 16:37:59 2010 +0100
description:
auth: Aborting pending async requests on deinit caused crashes.

diffstat:

 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(-)

diffs (111 lines):

diff -r 941608f8b3fb -r 3ef582c3fb72 src/auth/auth-client-connection.c
--- a/src/auth/auth-client-connection.c	Tue Jun 01 16:01:21 2010 +0100
+++ b/src/auth/auth-client-connection.c	Tue Jun 01 16:37:59 2010 +0100
@@ -348,7 +348,7 @@
 	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 -r 941608f8b3fb -r 3ef582c3fb72 src/auth/auth-request-handler.c
--- a/src/auth/auth-request-handler.c	Tue Jun 01 16:01:21 2010 +0100
+++ b/src/auth/auth-request-handler.c	Tue Jun 01 16:37:59 2010 +0100
@@ -29,6 +29,8 @@
 	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 @@
 	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 @@
 	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 -r 941608f8b3fb -r 3ef582c3fb72 src/auth/auth-request-handler.h
--- a/src/auth/auth-request-handler.h	Tue Jun 01 16:01:21 2010 +0100
+++ b/src/auth/auth-request-handler.h	Tue Jun 01 16:37:59 2010 +0100
@@ -23,7 +23,9 @@
 		(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 -r 941608f8b3fb -r 3ef582c3fb72 src/auth/auth-request.c
--- a/src/auth/auth-request.c	Tue Jun 01 16:01:21 2010 +0100
+++ b/src/auth/auth-request.c	Tue Jun 01 16:37:59 2010 +0100
@@ -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 @@
 			    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 @@
 {
 	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)


More information about the dovecot-cvs mailing list