From 43d65cae60552c4d4d1827eb5519e3ed02cef52e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Mon, 19 Dec 2022 06:51:27 +0000 Subject: [PATCH] SSL and fast_forward : handling of SSL_ERROR_SYSCALL --- lib/ClickHouse_Server.cpp | 2 + lib/MySQL_Thread.cpp | 2 +- lib/mysql_data_stream.cpp | 20 ++++++---- src/SQLite3_Server.cpp | 1 + test/tap/tests/test_ssl_fast_forward-t.cpp | 46 ++++++++++++++-------- 5 files changed, 47 insertions(+), 24 deletions(-) diff --git a/lib/ClickHouse_Server.cpp b/lib/ClickHouse_Server.cpp index 94cecdeb7..6d4f84ece 100644 --- a/lib/ClickHouse_Server.cpp +++ b/lib/ClickHouse_Server.cpp @@ -567,6 +567,8 @@ void ClickHouse_Server_session_handler(MySQL_Session *sess, void *_pa, PtrSize_t query_no_space[query_no_space_length]=0; } + proxy_debug(PROXY_DEBUG_SQLITE, 4, "Received query on Session %p , thread_session_id %u : %s\n", sess, sess->thread_session_id, query_no_space); + if (sess->session_type == PROXYSQL_SESSION_CLICKHOUSE) { if (!strncasecmp("SET ", query_no_space, 4)) { diff --git a/lib/MySQL_Thread.cpp b/lib/MySQL_Thread.cpp index 1fe30ea2d..c81b54339 100644 --- a/lib/MySQL_Thread.cpp +++ b/lib/MySQL_Thread.cpp @@ -3588,7 +3588,7 @@ bool MySQL_Thread::process_data_on_data_stream(MySQL_Data_Stream *myds, unsigned int sslhp = SSL_has_pending(myds->ssl); proxy_debug(PROXY_DEBUG_NET, 5, "Session=%p: in fast_forward mode and SSL read %d bytes , SSL_pending: %d bytes , SSL_has_pending: %d\n", myds->sess, rb, sslp, sslhp); */ - proxy_debug(PROXY_DEBUG_NET, 5, "Session=%p, DataStream=%p -- in fast_forward mode and SSL read %d bytes\n", myds->sess, myds, rb); + proxy_debug(PROXY_DEBUG_NET, 5, "Session=%p, DataStream=%p , thread_session_id=%u -- in fast_forward mode and SSL read %d bytes\n", myds->sess, myds, myds->sess->thread_session_id, rb); while (rb == 16384) { rb = myds->read_from_net(); proxy_debug(PROXY_DEBUG_NET, 5, "Session=%p, DataStream=%p -- in fast_forward mode and SSL read %d bytes\n", myds->sess, myds, rb); diff --git a/lib/mysql_data_stream.cpp b/lib/mysql_data_stream.cpp index d2c4dd94c..28d21c216 100644 --- a/lib/mysql_data_stream.cpp +++ b/lib/mysql_data_stream.cpp @@ -629,13 +629,12 @@ int MySQL_Data_Stream::read_from_net() { } } else { int ssl_ret=SSL_get_error(ssl, r); - proxy_debug(PROXY_DEBUG_NET, 5, "Session=%p, Datastream=%p -- SSL_get_error(): %d , errno: %d\n", sess, this, ssl_ret, errno); - if (ssl_ret!=SSL_ERROR_WANT_READ && ssl_ret!=SSL_ERROR_WANT_WRITE) shut_soft(); - if (r==0) { // we couldn't read any data - if (ssl_ret == SSL_ERROR_SYSCALL && (errno == EINTR || errno == EAGAIN)) { - proxy_debug(PROXY_DEBUG_NET, 5, "Session=%p, Datastream=%p -- SSL_get_error() is SSL_ERROR_SYSCALL, errno: %d\n", sess, this, errno); - // the read was interrupted, do nothing - } else { + proxy_debug(PROXY_DEBUG_NET, 5, "Session=%p, Datastream=%p -- session_id: %u , SSL_get_error(): %d , errno: %d\n", sess, this, sess->thread_session_id, ssl_ret, errno); + if (ssl_ret == SSL_ERROR_SYSCALL && (errno == EINTR || errno == EAGAIN)) { + // the read was interrupted, do nothing + proxy_debug(PROXY_DEBUG_NET, 5, "Session=%p, Datastream=%p -- SSL_get_error() is SSL_ERROR_SYSCALL, errno: %d\n", sess, this, errno); + } else { + if (r==0) { // we couldn't read any data if (revents==1) { // revents returns 1 , but recv() returns 0 , so there is no data. // Therefore the socket is already closed @@ -643,6 +642,8 @@ int MySQL_Data_Stream::read_from_net() { shut_soft(); } } + if (ssl_ret!=SSL_ERROR_WANT_READ && ssl_ret!=SSL_ERROR_WANT_WRITE) shut_soft(); + // it seems we end in shut_soft() anyway } } } else { @@ -673,11 +674,13 @@ int MySQL_Data_Stream::write_to_net() { if (encrypted) { bytes_io = SSL_write (ssl, queue_r_ptr(queueOUT), s); //proxy_info("Used SSL_write to write %d bytes\n", bytes_io); + proxy_debug(PROXY_DEBUG_NET, 7, "Session=%p, Datastream=%p: SSL_write() wrote %d bytes . queueOUT before: %u\n", sess, this, bytes_io, queue_data(queueOUT)); if (ssl_write_len || wbio_ssl->num_write > wbio_ssl->num_read) { //proxy_info("ssl_write_len = %d , num_write = %d , num_read = %d\n", ssl_write_len , wbio_ssl->num_write , wbio_ssl->num_read); char buf[MY_SSL_BUFFER]; do { n = BIO_read(wbio_ssl, buf, sizeof(buf)); + proxy_debug(PROXY_DEBUG_NET, 7, "Session=%p, Datastream=%p: BIO_read() read %d bytes\n", sess, this, n); //proxy_info("BIO read = %d\n", n); if (n > 0) { //proxy_info("Setting %d byte in queue encrypted\n", n); @@ -690,8 +693,10 @@ int MySQL_Data_Stream::write_to_net() { } } while (n>0); } + proxy_debug(PROXY_DEBUG_NET, 7, "Session=%p, Datastream=%p: current ssl_write_len is %lu bytes\n", sess, this, ssl_write_len); if (ssl_write_len) { n = write(fd, ssl_write_buf, ssl_write_len); + proxy_debug(PROXY_DEBUG_NET, 7, "Session=%p, Datastream=%p: write() wrote %d bytes in FD %d\n", sess, this, n, fd); //proxy_info("Calling write() on SSL: %d\n", n); if (n>0) { if ((size_t)n < ssl_write_len) { @@ -722,6 +727,7 @@ int MySQL_Data_Stream::write_to_net() { #else bytes_io = send(fd, queue_r_ptr(queueOUT), s, MSG_NOSIGNAL); #endif + proxy_debug(PROXY_DEBUG_NET, 7, "Session=%p, Datastream=%p: send() wrote %d bytes in FD %d\n", sess, this, bytes_io, fd); } if (encrypted) { //proxy_info("bytes_io: %d\n", bytes_io); diff --git a/src/SQLite3_Server.cpp b/src/SQLite3_Server.cpp index 8f92fc02e..142dce4d7 100644 --- a/src/SQLite3_Server.cpp +++ b/src/SQLite3_Server.cpp @@ -372,6 +372,7 @@ void SQLite3_Server_session_handler(MySQL_Session *sess, void *_pa, PtrSize_t *p query_no_space[query_no_space_length]=0; } + proxy_debug(PROXY_DEBUG_SQLITE, 4, "Received query on Session %p , thread_session_id %u : %s\n", sess, sess->thread_session_id, query_no_space); { SQLite3_Session *sqlite_sess = (SQLite3_Session *)sess->thread->gen_args; diff --git a/test/tap/tests/test_ssl_fast_forward-t.cpp b/test/tap/tests/test_ssl_fast_forward-t.cpp index 7d75ddf0c..9cdb7dfa8 100644 --- a/test/tap/tests/test_ssl_fast_forward-t.cpp +++ b/test/tap/tests/test_ssl_fast_forward-t.cpp @@ -18,6 +18,8 @@ Several bugs were identified and fixed while developing this test: - several memory corruption in SSL and fast_forward - SQLite3 Server stops working if the user is a fast_forward user - potential stalls with large resultset +- connections being closed because of interrupted syscall in SSL (SSL_ERROR_SYSCALL) + */ @@ -64,10 +66,11 @@ std::vector queries_SQL2 = { "INSERT INTO tbl1459 SELECT NULL , i1 + id, i2 + id FROM tbl1459", }; - std::vector queries_limits = { 1, 10, 20, 27, 103, 169, 320, 450, 512, 619, 915, 1022, - 1033, 1145, 1516, 1920, 2034, 5014, 9932, 10111 + 1033, 1145, 1516, 1920, 2034, 5014, 9932, 10111, + 11033, 11145, 12516, 11920, 12034, 15014, 19932, + 21033, 21145, 22516, 21920, 22034, 25014, 29932 }; @@ -80,8 +83,9 @@ int run_queries_sets(std::vector& queries, MYSQL *my, const std::st return 0; } - -#define ITER 4 +#define ITER1 10 +// ITER2 is big because we iterate many times in case SSL_ERROR_SYSCALL (interrupted syscall, that is normally a rare event) is triggered +#define ITER2 20 int main(int argc, char** argv) { CommandLine cl; @@ -89,7 +93,10 @@ int main(int argc, char** argv) { if(cl.getEnv()) return exit_status(); - plan(5*ITER+5*ITER*queries_limits.size()); + unsigned int p = 0; + p += 5*ITER1; + p += (5-3)*ITER2*queries_limits.size(); // only on encrypted backend connections + plan(p); diag("Testing SSL and fast_forward"); MYSQL* mysqladmin = mysql_init(NULL); @@ -106,10 +113,10 @@ int main(int argc, char** argv) { for (int i = 0 ; i<5 ; i++) { mysqls[i] = NULL; } - // We will loop ITER times. + // We will loop ITER1 times. // On each iteration we create 5 connections with different configuration and run a simple SELECT 1 - for (int it = 0 ; itthread_id, l, rr); mysql_free_result(result); } } } + + + + for (int i=0; i<5; i++) { + diag("Connection %d has thread_id: %lu", i, mysqls[i]->thread_id); + } + mysql_close(mysqladmin); return exit_status();