]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Maintain a per-thread TLS ctx reference in TLS stream code
authorArtem Boldariev <artem@boldariev.com>
Tue, 29 Mar 2022 17:42:16 +0000 (20:42 +0300)
committerArtem Boldariev <artem@boldariev.com>
Wed, 6 Apr 2022 15:45:57 +0000 (18:45 +0300)
This commit changes the generic TLS stream code to maintain a
per-worker thread TLS context reference.

lib/isc/netmgr/netmgr-int.h
lib/isc/netmgr/tlsstream.c

index 1ce685cc0f821993ee7e99870237906d6fcce321..a8a7e93ad4a2080bfce4c0af3c08f4adb42de56a 100644 (file)
@@ -928,6 +928,8 @@ struct isc_nmsocket {
                BIO *bio_out;
                isc_tls_t *tls;
                isc_tlsctx_t *ctx;
+               isc_tlsctx_t **listener_tls_ctx; /*%< A context reference per
+                                                   worker */
                isc_nmsocket_t *tlslistener;
                atomic_bool result_updated;
                enum {
index dfff57f0dd7a1863c58b35d390fd8da432f9f488..0a46214a0380bb8cb61f9ebdd6be717d3b2de830 100644 (file)
@@ -77,6 +77,15 @@ tls_close_direct(isc_nmsocket_t *sock);
 static void
 async_tls_do_bio(isc_nmsocket_t *sock);
 
+static void
+tls_init_listener_tlsctx(isc_nmsocket_t *listener, isc_tlsctx_t *ctx);
+
+static void
+tls_cleanup_listener_tlsctx(isc_nmsocket_t *listener);
+
+static isc_tlsctx_t *
+tls_get_listener_tlsctx(isc_nmsocket_t *listener, const int tid);
+
 /*
  * The socket is closing, outerhandle has been detached, listener is
  * inactive, or the netmgr is closing: any operation on it should abort
@@ -585,6 +594,8 @@ static isc_result_t
 tlslisten_acceptcb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
        isc_nmsocket_t *tlslistensock = (isc_nmsocket_t *)cbarg;
        isc_nmsocket_t *tlssock = NULL;
+       isc_tlsctx_t *tlsctx = NULL;
+       int tid;
 
        /* If accept() was unsuccessful we can't do anything */
        if (result != ISC_R_SUCCESS) {
@@ -603,12 +614,15 @@ tlslisten_acceptcb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
        isc__nmsocket_init(tlssock, handle->sock->mgr, isc_nm_tlssocket,
                           &handle->sock->iface);
 
+       tid = isc_nm_tid();
        /* We need to initialize SSL now to reference SSL_CTX properly */
-       isc_tlsctx_attach(tlslistensock->tlsstream.ctx,
-                         &tlssock->tlsstream.ctx);
+       tlsctx = tls_get_listener_tlsctx(tlslistensock, tid);
+       RUNTIME_CHECK(tlsctx != NULL);
+       isc_tlsctx_attach(tlsctx, &tlssock->tlsstream.ctx);
        tlssock->tlsstream.tls = isc_tls_create(tlssock->tlsstream.ctx);
        if (tlssock->tlsstream.tls == NULL) {
                atomic_store(&tlssock->closed, true);
+               isc_tlsctx_free(&tlssock->tlsstream.ctx);
                isc__nmsocket_detach(&tlssock);
                return (ISC_R_TLSERROR);
        }
@@ -617,7 +631,7 @@ tlslisten_acceptcb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
        isc_nmhandle_attach(handle, &tlssock->outerhandle);
        tlssock->peer = handle->sock->peer;
        tlssock->read_timeout = atomic_load(&handle->sock->mgr->init);
-       tlssock->tid = isc_nm_tid();
+       tlssock->tid = tid;
 
        result = initialize_tls(tlssock, true);
        RUNTIME_CHECK(result == ISC_R_SUCCESS);
@@ -643,7 +657,7 @@ isc_nm_listentls(isc_nm_t *mgr, isc_sockaddr_t *iface,
        tlssock->result = ISC_R_UNSET;
        tlssock->accept_cb = accept_cb;
        tlssock->accept_cbarg = accept_cbarg;
-       isc_tlsctx_attach(sslctx, &tlssock->tlsstream.ctx);
+       tls_init_listener_tlsctx(tlssock, sslctx);
        tlssock->tlsstream.tls = NULL;
 
        /*
@@ -865,10 +879,9 @@ isc__nm_tls_stoplistening(isc_nmsocket_t *sock) {
        atomic_store(&sock->closed, true);
        sock->recv_cb = NULL;
        sock->recv_cbarg = NULL;
-       if (sock->tlsstream.tls != NULL) {
-               isc_tls_free(&sock->tlsstream.tls);
-               isc_tlsctx_free(&sock->tlsstream.ctx);
-       }
+
+       INSIST(sock->tlsstream.tls == NULL);
+       INSIST(sock->tlsstream.ctx == NULL);
 
        if (sock->outer != NULL) {
                isc_nm_stoplistening(sock->outer);
@@ -1020,9 +1033,7 @@ isc__nm_tls_cleanup_data(isc_nmsocket_t *sock) {
                        sock->tlsstream.bio_in = NULL;
                }
        } else if (sock->type == isc_nm_tlslistener) {
-               if (sock->tlsstream.ctx != NULL) {
-                       isc_tlsctx_free(&sock->tlsstream.ctx);
-               }
+               tls_cleanup_listener_tlsctx(sock);
        }
 }
 
@@ -1087,3 +1098,55 @@ isc__nm_tls_verify_tls_peer_result_string(const isc_nmhandle_t *handle) {
 
        return (isc_tls_verify_peer_result_string(sock->tlsstream.tls));
 }
+
+static void
+tls_init_listener_tlsctx(isc_nmsocket_t *listener, isc_tlsctx_t *ctx) {
+       uint32_t nworkers;
+
+       REQUIRE(VALID_NM(listener->mgr));
+
+       nworkers = isc_nm_getnworkers(listener->mgr);
+
+       REQUIRE(nworkers > 0);
+       REQUIRE(ctx != NULL);
+
+       listener->tlsstream.listener_tls_ctx = isc_mem_get(
+               listener->mgr->mctx, sizeof(isc_tlsctx_t *) * nworkers);
+       for (size_t i = 0; i < nworkers; i++) {
+               listener->tlsstream.listener_tls_ctx[i] = NULL;
+               isc_tlsctx_attach(ctx,
+                                 &listener->tlsstream.listener_tls_ctx[i]);
+       }
+}
+
+static void
+tls_cleanup_listener_tlsctx(isc_nmsocket_t *listener) {
+       uint32_t nworkers;
+
+       REQUIRE(VALID_NM(listener->mgr));
+
+       nworkers = isc_nm_getnworkers(listener->mgr);
+
+       REQUIRE(nworkers > 0);
+       if (listener->tlsstream.listener_tls_ctx == NULL) {
+               return;
+       }
+
+       for (size_t i = 0; i < nworkers; i++) {
+               isc_tlsctx_free(&listener->tlsstream.listener_tls_ctx[i]);
+       }
+       isc_mem_put(listener->mgr->mctx, listener->tlsstream.listener_tls_ctx,
+                   sizeof(isc_tlsctx_t *) * nworkers);
+}
+
+static isc_tlsctx_t *
+tls_get_listener_tlsctx(isc_nmsocket_t *listener, const int tid) {
+       REQUIRE(VALID_NM(listener->mgr));
+       REQUIRE(tid >= 0);
+
+       if (listener->tlsstream.listener_tls_ctx == NULL) {
+               return (NULL);
+       }
+
+       return (listener->tlsstream.listener_tls_ctx[tid]);
+}