]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
auth: Fix leaking memory if auth client disconnects with pending penalty delays
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Fri, 28 Aug 2020 13:57:57 +0000 (16:57 +0300)
committertimo.sirainen <timo.sirainen@open-xchange.com>
Fri, 28 Aug 2020 14:01:11 +0000 (14:01 +0000)
 * auth penalty lookup returns that auth_request needs a penalty delay
 * during the penalty timeout auth client disconnects
 * auth requests are freed, but auth_request_handler isn't unreferenced

This resulted in memory leak, and after recent changes also logging warnings
about event leaks.

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

index d9a084d9903c0dd8ab4173025a907d48d1611fe7..9bf692438174427dc78098f0f20546e1fe5ac636 100644 (file)
@@ -366,6 +366,8 @@ void auth_request_handler_reply(struct auth_request *request,
                                const void *auth_reply, size_t reply_size)
 {
        struct auth_request_handler *handler = request->handler;
+
+       request->handler_pending_reply = FALSE;
        handler->reply_callback(request, result, auth_reply, reply_size);
 }
 
@@ -439,6 +441,15 @@ auth_request_handler_default_reply_continue(struct auth_request *request,
                                   reply, reply_size);
 }
 
+void auth_request_handler_abort(struct auth_request *request)
+{
+       i_assert(request->handler_pending_reply);
+
+       /* request destroyed while waiting for auth_request_penalty_finish()
+          to be called. */
+       auth_request_handler_unref(&request->handler);
+}
+
 static void
 auth_request_handler_auth_fail_code(struct auth_request_handler *handler,
                                           struct auth_request *request,
@@ -665,6 +676,7 @@ bool auth_request_handler_auth_begin(struct auth_request_handler *handler,
        /* handler is referenced until auth_request_handler_reply()
           is called. */
        handler->refcount++;
+       request->handler_pending_reply = TRUE;
 
        /* before we start authenticating, see if we need to wait first */
        auth_penalty_lookup(auth_penalty, request, auth_penalty_callback);
index 6b601b3f30b1b1388b7b912492b03206060729ac..ceba9356c5829339646fd2cbf2b7644785307316 100644 (file)
@@ -50,6 +50,8 @@ void auth_request_handler_reply(struct auth_request *request,
                                const void *reply, size_t reply_size);
 void auth_request_handler_reply_continue(struct auth_request *request,
                                         const void *reply, size_t reply_size);
+void auth_request_handler_abort(struct auth_request *request);
+
 unsigned int
 auth_request_handler_get_request_count(struct auth_request_handler *handler);
 bool auth_request_handler_master_request(struct auth_request_handler *handler,
index f591027fbd70bbd048e2051189d883d8049e8491..dc45a4003ffa165b8fafa935fa742076ac72d943 100644 (file)
@@ -331,6 +331,9 @@ void auth_request_unref(struct auth_request **_request)
 
        i_assert(array_count(&request->authdb_event) == 0);
 
+       if (request->handler_pending_reply)
+               auth_request_handler_abort(request);
+
        event_unref(&request->mech_event);
        event_unref(&request->event);
        auth_request_stats_send(request);
index dbb7c6392d1003eab9e52f6ce7b6a7f978510f6c..7f24c7d5fbb822a5b0363bf57b5d107129af47a6 100644 (file)
@@ -176,6 +176,7 @@ struct auth_request {
        bool userdbs_seen_internal_failure:1;
 
        /* current state: */
+       bool handler_pending_reply:1;
        bool accept_cont_input:1;
        bool prefer_plain_credentials:1;
        bool in_delayed_failure_queue:1;