From: Timo Sirainen Date: Mon, 18 Jun 2018 10:15:55 +0000 (+0300) Subject: lib-imap-client: Fix crash when ostream output blocks before connection finishes X-Git-Tag: 2.3.9~1682 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=31234376c416885e30993baaf5d2306ee43600bc;p=thirdparty%2Fdovecot%2Fcore.git lib-imap-client: Fix crash when ostream output blocks before connection finishes It's possible that ostream tries to add IO_WRITE callback before imapc_connection_connected() callback is called. Fixes: Panic: io_add(0x2) called twice fd=15, callback=0x... -> 0x... --- diff --git a/src/lib-imap-client/imapc-connection.c b/src/lib-imap-client/imapc-connection.c index c9e2b97f86..5ac544f5c6 100644 --- a/src/lib-imap-client/imapc-connection.c +++ b/src/lib-imap-client/imapc-connection.c @@ -1695,13 +1695,14 @@ static int imapc_connection_ssl_init(struct imapc_connection *conn) return 0; } -static void imapc_connection_connected(struct imapc_connection *conn) +static int imapc_connection_connected(struct imapc_connection *conn) { const struct ip_addr *ip = &conn->ips[conn->prev_connect_idx]; struct ip_addr local_ip; in_port_t local_port; int err; - io_remove(&conn->io); + + i_assert(conn->io == NULL); err = net_geterror(conn->fd); if (err != 0) { @@ -1709,7 +1710,7 @@ static void imapc_connection_connected(struct imapc_connection *conn) "connect(%s, %u) failed: %s", net_ip2addr(ip), conn->client->set.port, strerror(err)), conn->client->set.connect_retry_interval_msecs, TRUE); - return; + return -1; } if (net_getsockname(conn->fd, &local_ip, &local_port) < 0) local_port = 0; @@ -1717,11 +1718,14 @@ static void imapc_connection_connected(struct imapc_connection *conn) net_ip2addr(ip), conn->client->set.port, net_ip2addr(&local_ip), local_port); conn->io = io_add(conn->fd, IO_READ, imapc_connection_input, conn); + o_stream_set_flush_callback(conn->output, imapc_connection_output, + conn); if (conn->client->set.ssl_mode == IMAPC_CLIENT_SSL_MODE_IMMEDIATE) { if (imapc_connection_ssl_init(conn) < 0) imapc_connection_disconnect(conn); } + return imapc_connection_output(conn); } static void imapc_connection_timeout(struct imapc_connection *conn) @@ -1818,9 +1822,9 @@ static void imapc_connection_connect_next_ip(struct imapc_connection *conn) &conn->input, &conn->output); } - o_stream_set_flush_callback(conn->output, imapc_connection_output, + o_stream_set_flush_pending(conn->output, TRUE); + o_stream_set_flush_callback(conn->output, imapc_connection_connected, conn); - conn->io = io_add(fd, IO_WRITE, imapc_connection_connected, conn); conn->parser = imap_parser_create(conn->input, NULL, conn->client->set.max_line_length); conn->to = timeout_add(conn->client->set.connect_timeout_msecs,