]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MAJOR: ssl: fix segfault on connection close using async engines.
authorEmeric Brun <ebrun@haproxy.com>
Wed, 31 May 2017 10:02:53 +0000 (10:02 +0000)
committerWilly Tarreau <w@1wt.eu>
Thu, 8 Jun 2017 04:47:34 +0000 (06:47 +0200)
This patch ensure that the ASYNC fd handlers won't be wake up
too early, disabling the event cache for this fd on connection close
and when a WANT_ASYNC is rised by Openssl.

The calls to SSL_read/SSL_write/SSL_do_handshake before rising a real read
event from the ASYNC fd, generated an EAGAIN followed by a context switch
for some engines, or a blocked read for the others.

On connection close it resulted in a too early call to SSL_free followed
by a segmentation fault.

src/ssl_sock.c

index 885aff973417a702f06a1e21b3da471248d6ac79..c8e6b57b699673c10f63c835b3cfbfe5c3c5f6f7 100644 (file)
@@ -454,8 +454,16 @@ static void inline ssl_async_process_fds(struct connection *conn, SSL *ssl)
 
        /* We activate the polling for all known async fds */
        SSL_get_all_async_fds(ssl, add_fd, &num_add_fds);
-       for (i=0 ; i < num_add_fds ; i++)
+       for (i=0 ; i < num_add_fds ; i++) {
                fd_want_recv(add_fd[i]);
+               /* To ensure that the fd cache won't be used
+                * We'll prefer to catch a real RD event
+                * because handling an EAGAIN on this fd will
+                * result in a context switch and also
+                * some engines uses a fd in blocking mode.
+                */
+               fd_cant_recv(add_fd[i]);
+       }
 
        /* We must also prevent the conn_handler
         * to be called until a read event was
@@ -5037,6 +5045,10 @@ static void ssl_sock_close(struct connection *conn) {
                                        fdtab[afd].iocb = ssl_async_fd_free;
                                        fdtab[afd].owner = conn->xprt_ctx;
                                        fd_want_recv(afd);
+                                       /* To ensure that the fd cache won't be used
+                                        * and we'll catch a real RD event.
+                                        */
+                                       fd_cant_recv(afd);
                                }
                                conn->xprt_ctx = NULL;
                                jobs++;