You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by re...@apache.org on 2021/11/12 19:48:53 UTC

[tomcat] branch main updated: Use an implicit scope

This is an automated email from the ASF dual-hosted git repository.

remm pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/main by this push:
     new eb680be  Use an implicit scope
eb680be is described below

commit eb680be080ecafbb094602e49c4e23af9b8df1cc
Author: remm <re...@apache.org>
AuthorDate: Fri Nov 12 20:48:28 2021 +0100

    Use an implicit scope
    
    This ties the native memory to the Java GC in a very clean way. However,
    I have to give up on bound method handles (this created a GC root) and
    replace it with a static state map.
    Also the MemorySegment that I was supposed to use creates another (very
    weird, this one) GC root to the scope, so revert to MemoryAddress for
    now.
---
 .../util/net/openssl/panama/OpenSSLEngine.java     | 138 +++++++++++----------
 .../net/openssl/panama/LocalStrings.properties     |   1 +
 webapps/docs/changelog.xml                         |   8 ++
 3 files changed, 83 insertions(+), 64 deletions(-)

diff --git a/modules/openssl-java17/src/main/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLEngine.java b/modules/openssl-java17/src/main/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLEngine.java
index e5f4424..62ff9f2 100644
--- a/modules/openssl-java17/src/main/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLEngine.java
+++ b/modules/openssl-java17/src/main/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLEngine.java
@@ -22,7 +22,6 @@ import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
 import java.lang.ref.Cleaner;
-import java.lang.ref.Cleaner.Cleanable;
 import java.net.HttpURLConnection;
 import java.net.MalformedURLException;
 import java.net.URL;
@@ -39,6 +38,7 @@ import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
 
 import javax.net.ssl.SSLEngine;
 import javax.net.ssl.SSLEngineResult;
@@ -94,9 +94,9 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn
     static {
         MethodHandles.Lookup lookup = MethodHandles.lookup();
         try {
-            openSSLCallbackInfoHandle = lookup.findVirtual(OpenSSLEngine.class, "openSSLCallbackInfo",
+            openSSLCallbackInfoHandle = lookup.findStatic(OpenSSLEngine.class, "openSSLCallbackInfo",
                     MethodType.methodType(void.class, MemoryAddress.class, int.class, int.class));
-            openSSLCallbackVerifyHandle = lookup.findVirtual(OpenSSLEngine.class, "openSSLCallbackVerify",
+            openSSLCallbackVerifyHandle = lookup.findStatic(OpenSSLEngine.class, "openSSLCallbackVerify",
                     MethodType.methodType(int.class, int.class, MemoryAddress.class));
         } catch (Exception e) {
             throw new IllegalStateException(e);
@@ -110,7 +110,7 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn
             try {
                 SSL_CTX_set_options(sslCtx, SSL_OP_ALL());
                 SSL_CTX_set_cipher_list(sslCtx, CLinker.toCString("ALL", scope));
-                var ssl = SSL_new(sslCtx).asSegment(CLinker.C_POINTER.byteSize(), scope);
+                var ssl = SSL_new(sslCtx);
                 SSL_set_accept_state(ssl);
                 try {
                     for (String c : getCiphers(ssl)) {
@@ -142,7 +142,7 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn
         IMPLEMENTED_PROTOCOLS_SET = Collections.unmodifiableSet(protocols);
     }
 
-    private static String[] getCiphers(MemorySegment ssl) {
+    private static String[] getCiphers(MemoryAddress ssl) {
         MemoryAddress sk = SSL_get_ciphers(ssl);
         int len = OPENSSL_sk_num(sk);
         if (len <= 0) {
@@ -177,16 +177,16 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn
 
     private static final String INVALID_CIPHER = "SSL_NULL_WITH_NULL_NULL";
 
+    private static final ConcurrentHashMap<Long, OpenSSLState> states = new ConcurrentHashMap<>();
+
     private final OpenSSLState state;
-    private final Cleanable cleanable;
+    private final ResourceScope scope;
 
     private enum Accepted { NOT, IMPLICIT, EXPLICIT }
     private Accepted accepted = Accepted.NOT;
     private enum PHAState { NONE, START, COMPLETE }
-    private PHAState phaState = PHAState.NONE;
     private boolean handshakeFinished;
     private int currentHandshake;
-    private int handshakeCount = 0;
     private boolean receivedShutdown;
     private volatile boolean destroyed;
 
@@ -208,15 +208,11 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn
     private boolean sendHandshakeError = false;
 
     private final boolean clientMode;
-    private final boolean noOcspCheck;
     private final String fallbackApplicationProtocol;
     private final OpenSSLSessionContext sessionContext;
     private final boolean alpn;
     private final boolean initialized;
     private final boolean certificateVerificationOptionalNoCA;
-    private final int certificateVerificationDepth;
-
-    private int certificateVerifyMode = 0;
 
     private String selectedProtocol = null;
 
@@ -248,13 +244,12 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn
         if (sslCtx == null) {
             throw new IllegalArgumentException(sm.getString("engine.noSSLContext"));
         }
-        ResourceScope scope = ResourceScope.newSharedScope();
+        scope = ResourceScope.newImplicitScope();
         var allocator = SegmentAllocator.ofScope(scope);
         session = new OpenSSLSession();
-        var ssl = SSL_new(sslCtx).asSegment(CLinker.C_POINTER.byteSize(), scope);
-        this.certificateVerificationDepth = certificateVerificationDepth;
+        var ssl = SSL_new(sslCtx);
         // Set ssl_info_callback
-        MemoryAddress openSSLCallbackInfo = CLinker.getInstance().upcallStub(openSSLCallbackInfoHandle.bindTo(this),
+        MemoryAddress openSSLCallbackInfo = CLinker.getInstance().upcallStub(openSSLCallbackInfoHandle,
                 openSSLCallbackInfoFunctionDescriptor, scope);
         SSL_set_info_callback(ssl, openSSLCallbackInfo);
         if (clientMode) {
@@ -267,17 +262,15 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn
         var networkBIOPointer = allocator.allocate(CLinker.C_POINTER);
         BIO_new_bio_pair(internalBIOPointer, 0, networkBIOPointer, 0);
         var internalBIO = MemoryAccess.getAddress(internalBIOPointer);
-        var networkBIO = MemoryAccess.getAddress(networkBIOPointer).asSegment(CLinker.C_POINTER.byteSize(), scope);
+        var networkBIO = MemoryAccess.getAddress(networkBIOPointer);
         SSL_set_bio(ssl, internalBIO, internalBIO);
-        state = new OpenSSLState(scope, ssl, networkBIO);
-        cleanable = cleaner.register(this, state);
+        state = new OpenSSLState(scope, ssl, networkBIO, certificateVerificationDepth, noOcspCheck);
         this.fallbackApplicationProtocol = fallbackApplicationProtocol;
         this.clientMode = clientMode;
         this.sessionContext = sessionContext;
         this.alpn = alpn;
         this.initialized = initialized;
         this.certificateVerificationOptionalNoCA = certificateVerificationOptionalNoCA;
-        this.noOcspCheck = noOcspCheck;
     }
 
     @Override
@@ -291,7 +284,7 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn
     public synchronized void shutdown() {
         if (!destroyed) {
             destroyed = true;
-            cleanable.clean();
+            states.remove(Long.valueOf(state.ssl.address().toRawLongValue()));
             // internal errors can cause shutdown without marking the engine closed
             isInboundDone = isOutboundDone = engineClosed = true;
         }
@@ -303,7 +296,7 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn
      * Calling this function with src.remaining == 0 is undefined.
      * @throws SSLException if the OpenSSL error check fails
      */
-    private int writePlaintextData(final MemorySegment ssl, final ByteBuffer src) throws SSLException {
+    private int writePlaintextData(final MemoryAddress ssl, final ByteBuffer src) throws SSLException {
         clearLastError();
         final int pos = src.position();
         final int limit = src.limit();
@@ -341,7 +334,7 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn
      * Write encrypted data to the OpenSSL network BIO.
      * @throws SSLException if the OpenSSL error check fails
      */
-    private int writeEncryptedData(final MemorySegment networkBIO, final ByteBuffer src) throws SSLException {
+    private int writeEncryptedData(final MemoryAddress networkBIO, final ByteBuffer src) throws SSLException {
         clearLastError();
         final int pos = src.position();
         final int len = src.remaining();
@@ -380,7 +373,7 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn
      * Read plain text data from the OpenSSL internal BIO
      * @throws SSLException if the OpenSSL error check fails
      */
-    private int readPlaintextData(final MemorySegment ssl, final ByteBuffer dst) throws SSLException {
+    private int readPlaintextData(final MemoryAddress ssl, final ByteBuffer dst) throws SSLException {
         clearLastError();
         final int pos = dst.position();
 
@@ -417,7 +410,7 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn
      * Read encrypted data from the OpenSSL network BIO
      * @throws SSLException if the OpenSSL error check fails
      */
-    private int readEncryptedData(final MemorySegment networkBIO, final ByteBuffer dst, final int pending) throws SSLException {
+    private int readEncryptedData(final MemoryAddress networkBIO, final ByteBuffer dst, final int pending) throws SSLException {
         clearLastError();
         final int pos = dst.position();
         if (dst.isDirect()) {
@@ -835,7 +828,7 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn
 
         final String cipherSuiteSpec = buf.toString();
         try {
-            SSL_set_cipher_list(state.ssl, CLinker.toCString(cipherSuiteSpec, state.scope));
+            SSL_set_cipher_list(state.ssl, CLinker.toCString(cipherSuiteSpec, scope));
         } catch (Exception e) {
             throw new IllegalStateException(sm.getString("engine.failedCipherSuite", cipherSuiteSpec), e);
         }
@@ -971,7 +964,7 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn
     }
 
     private byte[] getPeerCertificate() {
-        var allocator = SegmentAllocator.ofScope(state.scope);
+        var allocator = SegmentAllocator.ofScope(scope);
         MemoryAddress/*(X509*)*/ x509 = SSL_get_peer_certificate(state.ssl);
         MemorySegment bufPointer = allocator.allocate(CLinker.C_POINTER, MemoryAddress.NULL);
         int length = i2d_X509(x509, bufPointer);
@@ -979,7 +972,7 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn
             return null;
         }
         MemoryAddress buf = MemoryAccess.getAddress(bufPointer);
-        byte[] certificate = buf.asSegment(length, state.scope).toByteArray();
+        byte[] certificate = buf.asSegment(length, scope).toByteArray();
         X509_free(x509);
         CRYPTO_free(buf, OPENSSL_FILE(), OPENSSL_LINE()); // OPENSSL_free macro
         return certificate;
@@ -992,7 +985,7 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn
             return null;
         }
         byte[][] certificateChain = new byte[len][];
-        var allocator = SegmentAllocator.ofScope(state.scope);
+        var allocator = SegmentAllocator.ofScope(scope);
         for (int i = 0; i < len; i++) {
             MemoryAddress/*(X509*)*/ x509 = OPENSSL_sk_value(sk, i);
             MemorySegment bufPointer = allocator.allocate(CLinker.C_POINTER, MemoryAddress.NULL);
@@ -1002,7 +995,7 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn
                 continue;
             }
             MemoryAddress buf = MemoryAccess.getAddress(bufPointer);
-            byte[] certificate = buf.asSegment(length, state.scope).toByteArray();
+            byte[] certificate = buf.asSegment(length, scope).toByteArray();
             certificateChain[i] = certificate;
             CRYPTO_free(buf, OPENSSL_FILE(), OPENSSL_LINE()); // OPENSSL_free macro
         }
@@ -1010,7 +1003,7 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn
     }
 
     private String getProtocolNegotiated() {
-        var allocator = SegmentAllocator.ofScope(state.scope);
+        var allocator = SegmentAllocator.ofScope(scope);
         MemorySegment lenAddress = allocator.allocate(CLinker.C_INT, 0);
         MemorySegment protocolPointer = allocator.allocate(CLinker.C_POINTER, MemoryAddress.NULL);
         SSL_get0_alpn_selected(state.ssl, protocolPointer, lenAddress);
@@ -1025,7 +1018,7 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn
             return null;
         }
         MemoryAddress protocolAddress = MemoryAccess.getAddress(protocolPointer);
-        byte[] name = protocolAddress.asSegment(length, state.scope).toByteArray();
+        byte[] name = protocolAddress.asSegment(length, scope).toByteArray();
         if (logger.isDebugEnabled()) {
             logger.debug("Protocol negotiated [" + new String(name) + "]");
         }
@@ -1038,7 +1031,7 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn
     }
 
     private void handshake() throws SSLException {
-        currentHandshake = handshakeCount;
+        currentHandshake = state.handshakeCount;
         clearLastError();
         int code = SSL_do_handshake(state.ssl);
         if (code <= 0) {
@@ -1061,7 +1054,7 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn
         clearLastError();
         int code;
         if (CLinker.toJavaString(SSL_get_version(state.ssl)).equals(Constants.SSL_PROTO_TLSv1_3)) {
-            phaState = PHAState.START;
+            state.phaState = PHAState.START;
             code = SSL_verify_client_post_handshake(state.ssl);
         } else {
             code = SSL_renegotiate(state.ssl);
@@ -1072,7 +1065,7 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn
         handshakeFinished = false;
         peerCerts = null;
         x509PeerCerts = null;
-        currentHandshake = handshakeCount;
+        currentHandshake = state.handshakeCount;
         int code2 = SSL_do_handshake(state.ssl);
         if (code2 <= 0) {
             checkLastError();
@@ -1112,7 +1105,7 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn
         String sslError = null;
         long error = ERR_get_error();
         if (error != SSL_ERROR_NONE()) {
-            var allocator = SegmentAllocator.ofScope(state.scope);
+            var allocator = SegmentAllocator.ofScope(scope);
             do {
                 // Loop until getLastErrorNumber() returns SSL_ERROR_NONE
                 var buf = allocator.allocateArray(CLinker.C_CHAR, new byte[128]);
@@ -1185,8 +1178,8 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn
 
             // No pending data to be sent to the peer
             // Check to see if we have finished handshaking
-            if (handshakeCount != currentHandshake && SSL_renegotiate_pending(state.ssl) == 0 &&
-                    (phaState != PHAState.START)) {
+            if (state.handshakeCount != currentHandshake && SSL_renegotiate_pending(state.ssl) == 0 &&
+                    (state.phaState != PHAState.START)) {
                 if (alpn) {
                     selectedProtocol = getProtocolNegotiated();
                 }
@@ -1258,7 +1251,7 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn
             if (clientAuth == mode) {
                 return;
             }
-            certificateVerifyMode = switch (mode) {
+            state.certificateVerifyMode = switch (mode) {
                 case NONE -> SSL_VERIFY_NONE();
                 case REQUIRE -> SSL_VERIFY_FAIL_IF_NO_PEER_CERT();
                 case OPTIONAL -> certificateVerificationOptionalNoCA ? OPTIONAL_NO_CA : SSL_VERIFY_PEER();
@@ -1266,8 +1259,8 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn
             // SSL.setVerify(state.ssl, value, certificateVerificationDepth);
             // Set int verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx) callback
             MemoryAddress openSSLCallbackVerify =
-                    CLinker.getInstance().upcallStub(openSSLCallbackVerifyHandle.bindTo(this),
-                    openSSLCallbackVerifyFunctionDescriptor, state.scope);
+                    CLinker.getInstance().upcallStub(openSSLCallbackVerifyHandle,
+                    openSSLCallbackVerifyFunctionDescriptor, scope);
             int value = switch (mode) {
                 case NONE -> SSL_VERIFY_NONE();
                 case REQUIRE -> SSL_VERIFY_PEER() | SSL_VERIFY_FAIL_IF_NO_PEER_CERT();
@@ -1278,21 +1271,32 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn
         }
     }
 
-    public synchronized void openSSLCallbackInfo(MemoryAddress ssl, int where, int ret) {
+    public static void openSSLCallbackInfo(MemoryAddress ssl, int where, int ret) {
+        OpenSSLState state = states.get(Long.valueOf(ssl.toRawLongValue()));
+        if (state == null) {
+            logger.warn(sm.getString("engine.noSSL", Long.valueOf(ssl.toRawLongValue())));
+            return;
+        }
         if (0 != (where & SSL_CB_HANDSHAKE_DONE())) {
-            handshakeCount++;
+            state.handshakeCount++;
         }
     }
 
-    public synchronized int openSSLCallbackVerify(int preverify_ok, MemoryAddress /*X509_STORE_CTX*/ x509ctx) {
+    public static int openSSLCallbackVerify(int preverify_ok, MemoryAddress /*X509_STORE_CTX*/ x509ctx) {
+        MemoryAddress ssl = X509_STORE_CTX_get_ex_data(x509ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
+        OpenSSLState state = states.get(Long.valueOf(ssl.toRawLongValue()));
+        if (state == null) {
+            logger.warn(sm.getString("engine.noSSL", Long.valueOf(ssl.toRawLongValue())));
+            return 0;
+        }
         if (logger.isDebugEnabled()) {
-            logger.debug("Verification in engine with mode [" + certificateVerifyMode + "] for " + state.ssl);
+            logger.debug("Verification in engine with mode [" + state.certificateVerifyMode + "] for " + state.ssl);
         }
         int ok = preverify_ok;
         int errnum = X509_STORE_CTX_get_error(x509ctx);
         int errdepth = X509_STORE_CTX_get_error_depth(x509ctx);
-        phaState = PHAState.COMPLETE;
-        if (certificateVerifyMode == -1 /*SSL_CVERIFY_UNSET*/ || certificateVerifyMode == SSL_VERIFY_NONE()) {
+        state.phaState = PHAState.COMPLETE;
+        if (state.certificateVerifyMode == -1 /*SSL_CVERIFY_UNSET*/ || state.certificateVerifyMode == SSL_VERIFY_NONE()) {
             return 1;
         }
         /*SSL_VERIFY_ERROR_IS_OPTIONAL(errnum) -> ((errnum == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT)
@@ -1305,7 +1309,7 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn
                 || (errnum == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY())
                 || (errnum == X509_V_ERR_CERT_UNTRUSTED())
                 || (errnum == X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE());
-        if (verifyErrorIsOptional && (certificateVerifyMode == OPTIONAL_NO_CA)) {
+        if (verifyErrorIsOptional && (state.certificateVerifyMode == OPTIONAL_NO_CA)) {
             ok = 1;
             SSL_set_verify_result(state.ssl, X509_V_OK());
         }
@@ -1326,13 +1330,13 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn
         }
 
         // OCSP
-        if (!noOcspCheck && (ok > 0)) {
+        if (!state.noOcspCheck && (ok > 0)) {
             /* If there was an optional verification error, it's not
              * possible to perform OCSP validation since the issuer may be
              * missing/untrusted.  Fail in that case.
              */
             if (verifyErrorIsOptional) {
-                if (certificateVerifyMode != OPTIONAL_NO_CA) {
+                if (state.certificateVerifyMode != OPTIONAL_NO_CA) {
                     X509_STORE_CTX_set_error(x509ctx, X509_V_ERR_APPLICATION_VERIFICATION());
                     errnum = X509_V_ERR_APPLICATION_VERIFICATION();
                     ok = 0;
@@ -1351,7 +1355,7 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn
             }
         }
 
-        if (errdepth > certificateVerificationDepth) {
+        if (errdepth > state.certificateVerificationDepth) {
             // Certificate Verification: Certificate Chain too long
             ok = 0;
         }
@@ -1560,12 +1564,12 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn
             byte[] id = null;
             synchronized (OpenSSLEngine.this) {
                 if (!destroyed) {
-                    var allocator = SegmentAllocator.ofScope(state.scope);
+                    var allocator = SegmentAllocator.ofScope(scope);
                     MemorySegment lenPointer = allocator.allocate(CLinker.C_POINTER);
                     var session = SSL_get_session(state.ssl);
                     MemoryAddress sessionId = SSL_SESSION_get_id(session, lenPointer);
                     int length = MemoryAccess.getInt(lenPointer);
-                    id = (length == 0) ? new byte[0] : sessionId.asSegment(length, state.scope).toByteArray();
+                    id = (length == 0) ? new byte[0] : sessionId.asSegment(length, scope).toByteArray();
                 }
             }
 
@@ -1851,24 +1855,30 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn
 
     private static class OpenSSLState implements Runnable {
 
-        private final ResourceScope scope;
-        private final MemorySegment ssl;
-        private final MemorySegment networkBIO;
+        // FIXME: MemorySegment is supposed to be used but creates GC roots to the implicit scope
+        private final MemoryAddress ssl;
+        private final MemoryAddress networkBIO;
+        private final int certificateVerificationDepth;
+        private final boolean noOcspCheck;
+
+        private PHAState phaState = PHAState.NONE;
+        private int certificateVerifyMode = 0;
+        private int handshakeCount = 0;
 
-        private OpenSSLState(ResourceScope scope, MemorySegment ssl, MemorySegment networkBIO) {
-            this.scope = scope;
+        private OpenSSLState(ResourceScope scope, MemoryAddress ssl, MemoryAddress networkBIO,
+                int certificateVerificationDepth, boolean noOcspCheck) {
+            states.put(Long.valueOf(ssl.address().toRawLongValue()), this);
+            scope.addCloseAction(this);
             this.ssl = ssl;
             this.networkBIO = networkBIO;
+            this.certificateVerificationDepth = certificateVerificationDepth;
+            this.noOcspCheck = noOcspCheck;
         }
 
         @Override
         public void run() {
-            try {
-                BIO_free(networkBIO);
-                SSL_free(ssl);
-            } finally {
-                scope.close();
-            }
+            BIO_free(networkBIO);
+            SSL_free(ssl);
         }
     }
 }
diff --git a/modules/openssl-java17/src/main/resources/org/apache/tomcat/util/net/openssl/panama/LocalStrings.properties b/modules/openssl-java17/src/main/resources/org/apache/tomcat/util/net/openssl/panama/LocalStrings.properties
index 336418f..d236292 100644
--- a/modules/openssl-java17/src/main/resources/org/apache/tomcat/util/net/openssl/panama/LocalStrings.properties
+++ b/modules/openssl-java17/src/main/resources/org/apache/tomcat/util/net/openssl/panama/LocalStrings.properties
@@ -24,6 +24,7 @@ engine.invalidBufferArray=offset: [{0}], length: [{1}] (expected: offset <= offs
 engine.invalidDestinationBuffersState=The state of the destination buffers changed concurrently while unwrapping bytes
 engine.invalidOCSPURL=The OCSP URL is invalid: [{0}]
 engine.noRestrictSessionCreation=OpenSslEngine does not permit restricting the engine to only resuming existing sessions
+engine.noSSL=No SSL sound for address [{0}]
 engine.noSSLContext=No SSL context
 engine.noSession=SSL session ID not available
 engine.nullBuffer=Null buffer
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index fa65b2a..15e8083 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -113,6 +113,14 @@
       </update>
     </changelog>
   </subsection>
+  <subsection name="Coyote">
+    <changelog>
+      <add>
+        Use an implicit scope to tie the cleanup of OpenSSL memory to the Java
+        GC. (remm)
+      </add>
+    </changelog>
+  </subsection>
 </section>
 <section name="Tomcat 10.1.0-M7 (markt)" rtext="release in progress">
   <subsection name="Catalina">

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org