summaryrefslogtreecommitdiff
path: root/src/lib/tls/tortls_nss.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2018-09-12 11:02:59 -0400
committerNick Mathewson <nickm@torproject.org>2018-09-12 11:12:05 -0400
commitae5692994fc31cc5fa25fb5681e59e326e6c5dbe (patch)
treee83edf9652c3aea60ef2f7541eebb4c6cb7534ba /src/lib/tls/tortls_nss.c
parentbfc847255afb093b89dd82687d796e3e3c7fcb89 (diff)
downloadtor-ae5692994fc31cc5fa25fb5681e59e326e6c5dbe.tar.gz
tor-ae5692994fc31cc5fa25fb5681e59e326e6c5dbe.zip
Add a tor_tls_release_socket() function.
This function tells the underlying TLS object that it shouldn't close the fd on exit. Mostly, we hope not to have to use it, since the NSS implementation is kludgey, but it should allow us to fix
Diffstat (limited to 'src/lib/tls/tortls_nss.c')
-rw-r--r--src/lib/tls/tortls_nss.c37
1 files changed, 37 insertions, 0 deletions
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)
{