From b8b3750a4a88efddabbddb9f6c55144c31cb37ae Mon Sep 17 00:00:00 2001 From: mturk Date: Fri, 10 Nov 2006 14:26:11 +0000 Subject: [PATCH] Backport from tomcat-connectors. Fix coredump when the client socket is inside read/write operation (not closed), and the Tomcat is shutdown. The pool was destroyed twice in that case. git-svn-id: https://svn.apache.org/repos/asf/tomcat/tc6.0.x/trunk@473349 13f79535-47bb-0310-9956-ffa450edef68 --- native/connector/include/tcn.h | 1 + native/connector/src/network.c | 73 ++++++++++++++++++++++++------------ native/connector/src/sslnetwork.c | 78 ++++++++++++++++++++++++++++++--------- 3 files changed, 110 insertions(+), 42 deletions(-) diff --git a/native/connector/include/tcn.h b/native/connector/include/tcn.h index 1b880d155..c09ae6ea8 100644 --- a/native/connector/include/tcn.h +++ b/native/connector/include/tcn.h @@ -145,6 +145,7 @@ typedef struct { typedef struct { apr_pool_t *pool; + apr_pool_t *child; apr_socket_t *sock; void *opaque; char *jsbbuff; diff --git a/native/connector/src/network.c b/native/connector/src/network.c index 7326cc4f1..ac853fef6 100644 --- a/native/connector/src/network.c +++ b/native/connector/src/network.c @@ -83,8 +83,9 @@ static apr_status_t sp_socket_cleanup(void *data) if (s->net && s->net->cleanup) (*s->net->cleanup)(s->opaque); if (s->sock) { - apr_socket_close(s->sock); + apr_socket_t *as = s->sock; s->sock = NULL; + apr_socket_close(as); } #ifdef TCN_DO_STATISTICS apr_atomic_inc32(&sp_cleared); @@ -181,6 +182,15 @@ TCN_IMPLEMENT_CALL(jlong, Socket, create)(TCN_STDARGS, jint family, GET_S_FAMILY(f, family); GET_S_TYPE(t, type); + a = (tcn_socket_t *)apr_pcalloc(p, sizeof(tcn_socket_t)); + TCN_CHECK_ALLOCATED(a); + a->pool = p; + if (family >= 0) + a->net = &apr_socket_layer; + apr_pool_cleanup_register(p, (const void *)a, + sp_socket_cleanup, + apr_pool_cleanup_null); + if (family >= 0) { TCN_THROW_IF_ERR(apr_socket_create(&s, f, t, protocol, p), a); @@ -188,19 +198,15 @@ TCN_IMPLEMENT_CALL(jlong, Socket, create)(TCN_STDARGS, jint family, #ifdef TCN_DO_STATISTICS sp_created++; #endif - a = (tcn_socket_t *)apr_pcalloc(p, sizeof(tcn_socket_t)); - TCN_CHECK_ALLOCATED(a); a->sock = s; - a->pool = p; if (family >= 0) a->net = &apr_socket_layer; a->opaque = s; - apr_pool_cleanup_register(p, (const void *)a, - sp_socket_cleanup, - apr_pool_cleanup_null); + apr_pool_create(&a->child, a->pool); -cleanup: return P2J(a); +cleanup: + return 0; } @@ -209,6 +215,18 @@ TCN_IMPLEMENT_CALL(void, Socket, destroy)(TCN_STDARGS, jlong sock) tcn_socket_t *s = J2P(sock, tcn_socket_t *); UNREFERENCED_STDARGS; TCN_ASSERT(sock != 0); + + apr_pool_cleanup_kill(s->pool, s, sp_socket_cleanup); + if (s->net && s->net->cleanup) { + (*s->net->cleanup)(s->opaque); + s->net = NULL; + } + if (s->sock) { + apr_socket_t *as = s->sock; + s->sock = NULL; + apr_socket_close(as); + } + apr_pool_destroy(s->pool); } @@ -264,6 +282,10 @@ TCN_IMPLEMENT_CALL(jint, Socket, close)(TCN_STDARGS, jlong sock) UNREFERENCED_STDARGS; TCN_ASSERT(sock != 0); + apr_pool_cleanup_kill(s->pool, s, sp_socket_cleanup); + if (s->child) { + apr_pool_clear(s->child); + } #ifdef TCN_DO_STATISTICS apr_atomic_inc32(&sp_closed); #endif @@ -272,8 +294,9 @@ TCN_IMPLEMENT_CALL(jint, Socket, close)(TCN_STDARGS, jlong sock) s->net = NULL; } if (s->sock) { - rv = (jint)apr_socket_close(s->sock); + apr_socket_t *as = s->sock; s->sock = NULL; + rv = (jint)apr_socket_close(as); } return rv; } @@ -316,6 +339,13 @@ TCN_IMPLEMENT_CALL(jlong, Socket, acceptx)(TCN_STDARGS, jlong sock, if (s->net->type == TCN_SOCKET_APR) { TCN_ASSERT(s->sock != NULL); + a = (tcn_socket_t *)apr_pcalloc(p, sizeof(tcn_socket_t)); + TCN_CHECK_ALLOCATED(a); + a->pool = p; + apr_pool_cleanup_register(p, (const void *)a, + sp_socket_cleanup, + apr_pool_cleanup_null); + TCN_THROW_IF_ERR(apr_socket_accept(&n, s->sock, p), n); } else { @@ -326,15 +356,9 @@ TCN_IMPLEMENT_CALL(jlong, Socket, acceptx)(TCN_STDARGS, jlong sock, #ifdef TCN_DO_STATISTICS apr_atomic_inc32(&sp_accepted); #endif - a = (tcn_socket_t *)apr_pcalloc(p, sizeof(tcn_socket_t)); - TCN_CHECK_ALLOCATED(a); - a->sock = n; - a->pool = p; a->net = &apr_socket_layer; + a->sock = n; a->opaque = n; - apr_pool_cleanup_register(p, (const void *)a, - sp_socket_cleanup, - apr_pool_cleanup_null); } cleanup: @@ -354,6 +378,13 @@ TCN_IMPLEMENT_CALL(jlong, Socket, accept)(TCN_STDARGS, jlong sock) TCN_THROW_IF_ERR(apr_pool_create(&p, s->pool), p); if (s->net->type == TCN_SOCKET_APR) { TCN_ASSERT(s->sock != NULL); + a = (tcn_socket_t *)apr_pcalloc(p, sizeof(tcn_socket_t)); + TCN_CHECK_ALLOCATED(a); + a->pool = p; + apr_pool_cleanup_register(s->child, (const void *)a, + sp_socket_cleanup, + apr_pool_cleanup_null); + TCN_THROW_IF_ERR(apr_socket_accept(&n, s->sock, p), n); } else { @@ -364,15 +395,9 @@ TCN_IMPLEMENT_CALL(jlong, Socket, accept)(TCN_STDARGS, jlong sock) #ifdef TCN_DO_STATISTICS apr_atomic_inc32(&sp_accepted); #endif - a = (tcn_socket_t *)apr_pcalloc(p, sizeof(tcn_socket_t)); - TCN_CHECK_ALLOCATED(a); - a->sock = n; - a->pool = p; a->net = &apr_socket_layer; + a->sock = n; a->opaque = n; - apr_pool_cleanup_register(p, (const void *)a, - sp_socket_cleanup, - apr_pool_cleanup_null); } return P2J(a); cleanup: @@ -1202,7 +1227,7 @@ TCN_IMPLEMENT_CALL(jobject, Socket, dataGet)(TCN_STDARGS, jlong socket, void *rv = NULL; UNREFERENCED(o); - TCN_ASSERT(sock != 0); + TCN_ASSERT(socket != 0); if (apr_socket_data_get(&rv, J2S(key), s->sock) != APR_SUCCESS) { rv = NULL; diff --git a/native/connector/src/sslnetwork.c b/native/connector/src/sslnetwork.c index 7775d3b93..13f603d67 100644 --- a/native/connector/src/sslnetwork.c +++ b/native/connector/src/sslnetwork.c @@ -97,10 +97,15 @@ static apr_status_t ssl_cleanup(void *data) tcn_ssl_conn_t *con = (tcn_ssl_conn_t *)data; if (con) { + /* Pollset was already destroyed by + * the pool cleanup/destroy. + */ + con->pollset = NULL; if (con->ssl) { - ssl_smart_shutdown(con->ssl, con->shutdown_type); - SSL_free(con->ssl); - con->ssl = NULL; + SSL *ssl = con->ssl; + con->ssl = NULL; + ssl_smart_shutdown(ssl, con->shutdown_type); + SSL_free(ssl); } if (con->peer) { X509_free(con->peer); @@ -157,6 +162,12 @@ static tcn_ssl_conn_t *ssl_create(JNIEnv *env, tcn_ssl_ctxt_t *ctx, apr_pool_t * return con; } +#ifdef WIN32 +#define APR_INVALID_SOCKET INVALID_SOCKET +#else +#define APR_INVALID_SOCKET -1 +#endif + static apr_status_t wait_for_io_or_timeout(tcn_ssl_conn_t *con, int for_what) { @@ -164,6 +175,18 @@ static apr_status_t wait_for_io_or_timeout(tcn_ssl_conn_t *con, apr_pollfd_t pfd; int type; apr_status_t status; + apr_os_sock_t sock; + + if (!con->pollset) + return APR_ENOPOLL; + if (!con->sock) + return APR_ENOTSOCK; + + /* Check if the socket was already closed + */ + apr_os_sock_get(&sock, con->sock); + if (sock == APR_INVALID_SOCKET) + return APR_ENOTSOCK; /* Figure out the the poll direction */ switch (for_what) { @@ -241,12 +264,13 @@ ssl_socket_shutdown(apr_socket_t *sock, apr_shutdown_how_e how) tcn_ssl_conn_t *con = (tcn_ssl_conn_t *)sock; if (con->ssl) { + SSL *ssl = con->ssl; + con->ssl = NULL; if (how < 1) how = con->shutdown_type; - rv = ssl_smart_shutdown(con->ssl, how); + rv = ssl_smart_shutdown(ssl, how); /* TODO: Translate OpenSSL Error codes */ - SSL_free(con->ssl); - con->ssl = NULL; + SSL_free(ssl); } return rv; } @@ -261,9 +285,10 @@ ssl_socket_close(apr_socket_t *sock) apr_atomic_inc32(&ssl_closed); #endif if (con->ssl) { - rv = ssl_smart_shutdown(con->ssl, con->shutdown_type); - SSL_free(con->ssl); + SSL *ssl = con->ssl; con->ssl = NULL; + rv = ssl_smart_shutdown(ssl, con->shutdown_type); + SSL_free(ssl); } if (con->peer) { X509_free(con->peer); @@ -276,7 +301,7 @@ TCN_IMPLEMENT_CALL(jint, SSLSocket, handshake)(TCN_STDARGS, jlong sock) { tcn_socket_t *ss = J2P(sock, tcn_socket_t *); tcn_ssl_conn_t *con; - int s; + int s, i; apr_status_t rv; X509 *peer; @@ -287,7 +312,10 @@ TCN_IMPLEMENT_CALL(jint, SSLSocket, handshake)(TCN_STDARGS, jlong sock) con = (tcn_ssl_conn_t *)ss->opaque; while (!SSL_is_init_finished(con->ssl)) { if ((s = SSL_do_handshake(con->ssl)) <= 0) { - int i = SSL_get_error(con->ssl, s); + apr_status_t os = apr_get_netos_error(); + if (!con->ssl) + return os == APR_SUCCESS ? APR_ENOTSOCK : os; + i = SSL_get_error(con->ssl, s); switch (i) { case SSL_ERROR_NONE: con->shutdown_type = SSL_SHUTDOWN_TYPE_STANDARD; @@ -302,11 +330,10 @@ TCN_IMPLEMENT_CALL(jint, SSLSocket, handshake)(TCN_STDARGS, jlong sock) break; case SSL_ERROR_SYSCALL: case SSL_ERROR_SSL: - s = apr_get_netos_error(); - if (!APR_STATUS_IS_EAGAIN(s) && - !APR_STATUS_IS_EINTR(s)) { + if (!APR_STATUS_IS_EAGAIN(os) && + !APR_STATUS_IS_EINTR(os)) { con->shutdown_type = SSL_SHUTDOWN_TYPE_UNCLEAN; - return s; + return os; } break; default: @@ -318,6 +345,9 @@ TCN_IMPLEMENT_CALL(jint, SSLSocket, handshake)(TCN_STDARGS, jlong sock) break; } } + if (!con->ssl) + return APR_ENOTSOCK; + /* * Check for failed client authentication */ @@ -344,13 +374,16 @@ static apr_status_t APR_THREAD_FUNC ssl_socket_recv(apr_socket_t *sock, char *buf, apr_size_t *len) { tcn_ssl_conn_t *con = (tcn_ssl_conn_t *)sock; - int s, wr = (int)(*len); + int s, i, wr = (int)(*len); apr_status_t rv = APR_SUCCESS; for (;;) { if ((s = SSL_read(con->ssl, buf, wr)) <= 0) { apr_status_t os = apr_get_netos_error(); - int i = SSL_get_error(con->ssl, s); + if (!con->ssl) + return os == APR_SUCCESS ? APR_ENOTSOCK : os; + + i = SSL_get_error(con->ssl, s); /* Special case if the "close notify" alert send by peer */ if (s == 0 && (con->ssl->shutdown & SSL_RECEIVED_SHUTDOWN)) { *len = 0; @@ -397,13 +430,16 @@ ssl_socket_send(apr_socket_t *sock, const char *buf, apr_size_t *len) { tcn_ssl_conn_t *con = (tcn_ssl_conn_t *)sock; - int s, wr = (int)(*len); + int s, i, wr = (int)(*len); apr_status_t rv = APR_SUCCESS; for (;;) { if ((s = SSL_write(con->ssl, buf, wr)) <= 0) { apr_status_t os = apr_get_netos_error(); - int i = SSL_get_error(con->ssl, s); + if (!con->ssl) + return os == APR_SUCCESS ? APR_ENOTSOCK : os; + + i = SSL_get_error(con->ssl, s); switch (i) { case SSL_ERROR_ZERO_RETURN: *len = 0; @@ -490,8 +526,14 @@ TCN_IMPLEMENT_CALL(jint, SSLSocket, attach)(TCN_STDARGS, jlong ctx, TCN_ASSERT(ctx != 0); TCN_ASSERT(sock != 0); + if (!s->sock) + return APR_ENOTSOCK; + if ((rv = apr_os_sock_get(&oss, s->sock)) != APR_SUCCESS) return rv; + if (oss == APR_INVALID_SOCKET) + return APR_ENOTSOCK; + if ((con = ssl_create(e, c, s->pool)) == NULL) return APR_EGENERAL; con->sock = s->sock; -- 2.11.0