diff options
author | Nick Mathewson <nickm@torproject.org> | 2018-09-14 10:22:38 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2018-09-14 10:22:38 -0400 |
commit | e43ae24e7d8cc96eaed41b8e135232248ac39721 (patch) | |
tree | 779b708fc7ab44fbe116b2822af54c46258586fb /src/lib | |
parent | dbb0abc9f1a174efdb65d581f5dbe46dbad2ebb5 (diff) | |
parent | 9f5f67bda26979bb75e10a0ce0080997b1b72603 (diff) | |
download | tor-e43ae24e7d8cc96eaed41b8e135232248ac39721.tar.gz tor-e43ae24e7d8cc96eaed41b8e135232248ac39721.zip |
Merge branch 'nss_27451'
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/tls/tortls.h | 1 | ||||
-rw-r--r-- | src/lib/tls/tortls_nss.c | 37 | ||||
-rw-r--r-- | src/lib/tls/tortls_openssl.c | 24 |
3 files changed, 61 insertions, 1 deletions
diff --git a/src/lib/tls/tortls.h b/src/lib/tls/tortls.h index 4591927081..3f1098bbac 100644 --- a/src/lib/tls/tortls.h +++ b/src/lib/tls/tortls.h @@ -94,6 +94,7 @@ void tor_tls_set_renegotiate_callback(tor_tls_t *tls, void (*cb)(tor_tls_t *, void *arg), void *arg); int tor_tls_is_server(tor_tls_t *tls); +void tor_tls_release_socket(tor_tls_t *tls); void tor_tls_free_(tor_tls_t *tls); #define tor_tls_free(tls) FREE_AND_NULL(tor_tls_t, tor_tls_free_, (tls)) int tor_tls_peer_has_cert(tor_tls_t *tls); diff --git a/src/lib/tls/tortls_nss.c b/src/lib/tls/tortls_nss.c index 53adfedf32..1b2032764d 100644 --- a/src/lib/tls/tortls_nss.c +++ b/src/lib/tls/tortls_nss.c @@ -414,6 +414,43 @@ tor_tls_set_renegotiate_callback(tor_tls_t *tls, /* We don't support renegotiation-based TLS with NSS. */ } +/** + * Tell the TLS library that the underlying socket for <b>tls</b> has been + * closed, and the library should not attempt to free that socket itself. + */ +void +tor_tls_release_socket(tor_tls_t *tls) +{ + if (! tls) + return; + + /* NSS doesn't have the equivalent of BIO_NO_CLOSE. If you replace the + * fd with something that's invalid, it causes a memory leak in PR_Close. + * + * If there were a way to put the PRFileDesc into the CLOSED state, that + * would prevent it from closing its fd -- but there doesn't seem to be a + * supported way to do that either. + * + * So instead: we make a new sacrificial socket, and replace the original + * socket with that one. This seems to be the best we can do, until we + * redesign the mainloop code enough to make this function unnecessary. + */ + tor_socket_t sock = + tor_open_socket_nonblocking(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (!sock) { + log_warn(LD_NET, "Out of sockets when trying to shut down an NSS " + "connection"); + return; + } + + PRFileDesc *tcp = PR_GetIdentitiesLayer(tls->ssl, PR_NSPR_IO_LAYER); + if (BUG(! tcp)) { + return; + } + + PR_ChangeFileDescNativeHandle(tcp, sock); +} + void tor_tls_impl_free_(tor_tls_impl_t *tls) { diff --git a/src/lib/tls/tortls_openssl.c b/src/lib/tls/tortls_openssl.c index dc6c0bee9c..534a90de5d 100644 --- a/src/lib/tls/tortls_openssl.c +++ b/src/lib/tls/tortls_openssl.c @@ -1048,7 +1048,7 @@ tor_tls_new(tor_socket_t sock, int isServer) goto err; } result->socket = sock; - bio = BIO_new_socket(sock, BIO_NOCLOSE); + bio = BIO_new_socket(sock, BIO_CLOSE); if (! bio) { tls_log_errors(NULL, LOG_WARN, LD_NET, "opening BIO"); #ifdef SSL_set_tlsext_host_name @@ -1154,6 +1154,28 @@ tor_tls_assert_renegotiation_unblocked(tor_tls_t *tls) #endif /* defined(SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION) && ... */ } +/** + * Tell the TLS library that the underlying socket for <b>tls</b> has been + * closed, and the library should not attempt to free that socket itself. + */ +void +tor_tls_release_socket(tor_tls_t *tls) +{ + if (! tls) + return; + + BIO *rbio, *wbio; + rbio = SSL_get_rbio(tls->ssl); + wbio = SSL_get_wbio(tls->ssl); + + if (rbio) { + BIO_set_close(rbio, BIO_NOCLOSE); + } + if (wbio && wbio != rbio) { + BIO_set_close(wbio, BIO_NOCLOSE); + } +} + void tor_tls_impl_free_(tor_tls_impl_t *ssl) { |