CVE-2021-4213 (Java, published 2022-08-24T16:15Z)
Description: value: A flaw was found in JSS, where it did not properly free up all memory. Over time, the wasted memory builds up in the server memory, saturating the server’s RAM. This flaw allows an attacker to force the invocation of an out-of-memory process, causing a denial of service.
Severity: nan (CVSS v3 base score: 7.5)
Weakness: CWE-401 \u2014 Missing Release of Memory after Effective Lifetime
The product does not sufficiently track and release allocated memory after it has been used, which slowly consumes remaining memory.
Repository: https://github.com/dogtagpki/jss
Files changed:
src/main/java/org/mozilla/jss/nss/SSLFDProxy.java
src/main/java/org/mozilla/jss/ssl/javax/JSSEngineReferenceImpl.java
src/main/java/org/mozilla/jss/util/GlobalRefProxy.java
Commit message: Fix memory leak on each TLS connection

Each TLS connection is leaking a bunch of data that isn't in the heap
and so after 25k requests Tomcat uses about 2.5GB resident memory.

There are large number of relationships that point at each other and we
need to break the cycle so JSSEngineReferenceImpl's finalizer can run
and clear all the native resources these point at.

The lowest impact place to break the cycle was at SSLAlertEvent.engine.
This relationship doesn't seem to be used anywhere.  Once the cycle is
broken, JSSEngineReferenceImpl can be garbage collected and the
finalizer can run.

Signed-off-by: Chris Kelley <ckelley@redhat.com>

Vulnerable code:
import java.lang.IllegalArgumentException;
        synchronized (globalRef) {
            if (globalRef != null) {
                try {
                    globalRef.close();
                } finally {
                    globalRef = null;
                }
import java.nio.channels.WritableByteChannel;
import java.nio.ByteBuffer;

import javax.net.ssl.*;
import org.mozilla.jss.nss.*;
import org.mozilla.jss.pkcs11.*;
import org.mozilla.jss.provider.javax.crypto.*;
import org.mozilla.jss.ssl.*;
                PR.Close(ssl_fd);
                debug("Got exception trying to cleanup SSLFD: " + e.getMessage());
    protected synchronized void releaseNativeResources() {
        clear();
    }

Fixed code:

        super.releaseNativeResources();

        if (globalRef != null) {
            try {
                globalRef.close();
            } finally {
                globalRef = null;
import java.nio.ByteBuffer;
import java.nio.channels.WritableByteChannel;
import javax.net.ssl.SSLEngineResult;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.X509ExtendedTrustManager;
import javax.net.ssl.X509TrustManager;

import org.mozilla.jss.nss.BadCertHandler;
import org.mozilla.jss.nss.Buffer;
import org.mozilla.jss.nss.BufferProxy;
import org.mozilla.jss.nss.Cert;
import org.mozilla.jss.nss.CertAuthHandler;
import org.mozilla.jss.nss.PR;
import org.mozilla.jss.nss.PRErrors;
import org.mozilla.jss.nss.PRFDProxy;
import org.mozilla.jss.nss.SSL;
import org.mozilla.jss.nss.SSLErrors;
import org.mozilla.jss.nss.SSLFDProxy;
import org.mozilla.jss.nss.SSLPreliminaryChannelInfo;
import org.mozilla.jss.nss.SecurityStatusResult;
import org.mozilla.jss.pkcs11.PK11Cert;
import org.mozilla.jss.provider.javax.crypto.JSSNativeTrustManager;
import org.mozilla.jss.ssl.SSLAlertDescription;
import org.mozilla.jss.ssl.SSLAlertEvent;
import org.mozilla.jss.ssl.SSLAlertLevel;
import org.mozilla.jss.ssl.SSLCipher;
import org.mozilla.jss.ssl.SSLHandshakeCompletedEvent;
import org.mozilla.jss.ssl.SSLVersion;
import org.mozilla.jss.ssl.SSLVersionRange;
                ssl_fd = null;
                logger.error("Got exception trying to cleanup SSLFD", e);
    // During testing with Tomcat 8.5, most instances did not call
    // cleanup, so all the JNI resources end up getting leaked: ssl_fd
    // (and its global ref), read_buf, and write_buf.
    @Override
    protected void finalize() {
        cleanup();
    }


    protected native void releaseNativeResources();