]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
imap-hibernate: Fix potential crash after fd_send() failure
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Mon, 2 Feb 2026 22:39:31 +0000 (00:39 +0200)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Fri, 6 Feb 2026 19:44:42 +0000 (19:44 +0000)
connection_input_parse_lines() accessed the already freed conn struct
after input_line() destroyed the connection.

src/imap-hibernate/imap-client.c
src/imap-hibernate/imap-master-connection.c
src/imap-hibernate/imap-master-connection.h

index 99e06c7e9ceff806f03b57fede612dd124bd9439..4c2fb4bc0aa05ce48e09ba003897cf702f7beca0 100644 (file)
@@ -148,7 +148,7 @@ imap_client_parse_userdb_fields(struct imap_client *client,
        }
 }
 
-static void
+static int
 imap_client_move_back_send_callback(void *context, struct ostream *output)
 {
        struct imap_client *client = context;
@@ -239,7 +239,7 @@ imap_client_move_back_send_callback(void *context, struct ostream *output)
                const char *error = t_strdup_printf(
                        "fd_send(%s) failed: %m", o_stream_get_name(output));
                imap_client_unhibernate_failed(&client, error);
-               return;
+               return -1;
        }
        /* If unhibernation fails after this, shutdown() the fd to make sure
           the imap process won't later on finish unhibernation after all and
@@ -247,6 +247,7 @@ imap_client_move_back_send_callback(void *context, struct ostream *output)
        client->shutdown_fd_on_destroy = TRUE;
        i_assert(ret > 0);
        o_stream_nsend(output, str_data(str) + 1, str_len(str) - 1);
+       return 0;
 }
 
 static void
index 71fa4dd5cc86cf378d5f8477521be46a99984754..303dfd3eb96286215fb3842acacdb28c38cd3375 100644 (file)
@@ -104,8 +104,7 @@ imap_master_client_input_line(struct connection *_conn, const char *line)
                if (connection_input_line_default(_conn, line) < 0)
                        return -1;
 
-               conn->send_callback(conn->context, _conn->output);
-               return 1;
+               return conn->send_callback(conn->context, _conn->output) < 0 ? -1 : 1;
        } else {
                imap_master_read_callback(&conn, line);
                /* we're finished now with this connection - disconnect it */
index 0ff2f3c611a5a8ba6ff12cfbd8336f7de33d406a..a3553c07b9f3a0345098243c6e007ba08f624487 100644 (file)
@@ -3,7 +3,7 @@
 
 struct imap_master_connection;
 
-typedef void
+typedef int
 imap_master_connection_send_callback_t(void *context, struct ostream *output);
 typedef void
 imap_master_connection_read_callback_t(void *context, const char *reply);