]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-ssl-iostream: Fix potential crash if istream is destroyed before ostream
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Mon, 12 Mar 2018 11:58:02 +0000 (13:58 +0200)
committerVille Savolainen <ville.savolainen@dovecot.fi>
Thu, 7 Jun 2018 07:07:38 +0000 (10:07 +0300)
This happened if o_stream_destroy() triggered flush, which attempted to read
from the ssl_io->ssl_input. If the istream-ssl was already destroyed, it was
NULL and that caused a crash.

src/lib-ssl-iostream/iostream-openssl.c
src/lib-ssl-iostream/ostream-openssl.c

index d1459d40692d602e9bec4bb5e29431375caaae99..2af3c001d26fdccf02c8b94294e27612e38a7a21 100644 (file)
@@ -303,6 +303,8 @@ openssl_iostream_create(struct ssl_iostream_context *ctx, const char *host,
        o_stream_uncork(ssl_io->plain_output);
 
        *input = openssl_i_stream_create_ssl(ssl_io);
+       ssl_io->ssl_input = *input;
+
        *output = openssl_o_stream_create_ssl(ssl_io);
        i_stream_set_name(*input, t_strconcat("SSL ",
                i_stream_get_name(ssl_io->plain_input), NULL));
@@ -312,7 +314,6 @@ openssl_iostream_create(struct ssl_iostream_context *ctx, const char *host,
        if (ssl_io->plain_output->real_stream->error_handling_disabled)
                o_stream_set_no_error_handling(*output, TRUE);
 
-       ssl_io->ssl_input = *input;
        ssl_io->ssl_output = *output;
        *iostream_r = ssl_io;
        return 0;
index 3a71758c89d90e9b8d8cb36883a57a5a133a542d..e6e8aa5686d5febc9c2c4ff665e935f759831c18 100644 (file)
@@ -2,6 +2,7 @@
 
 #include "lib.h"
 #include "buffer.h"
+#include "istream.h"
 #include "ostream-private.h"
 #include "iostream-openssl.h"
 
@@ -23,8 +24,10 @@ o_stream_ssl_close(struct iostream_private *stream, bool close_parent)
 static void o_stream_ssl_destroy(struct iostream_private *stream)
 {
        struct ssl_ostream *sstream = (struct ssl_ostream *)stream;
+       struct istream *ssl_input = sstream->ssl_io->ssl_input;
 
        sstream->ssl_io->ssl_output = NULL;
+       i_stream_unref(&ssl_input);
        ssl_iostream_unref(&sstream->ssl_io);
        buffer_free(&sstream->buffer);
 }
@@ -245,6 +248,13 @@ struct ostream *openssl_o_stream_create_ssl(struct ssl_iostream *ssl_io)
 
        ssl_io->refcount++;
 
+       /* When ostream is destroyed, it's flushed. With iostream-ssl the
+          flushing requires both istream and ostream to be available. The
+          istream is referenced here to make sure it's not destroyed before
+          the ostream. */
+       i_assert(ssl_io->ssl_input != NULL);
+       i_stream_ref(ssl_io->ssl_input);
+
        sstream = i_new(struct ssl_ostream, 1);
        sstream->ssl_io = ssl_io;
        sstream->ostream.max_buffer_size =