You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2021/09/28 07:28:05 UTC
[tomcat] branch 8.5.x updated: Fix BZ 65553 - add workaround for
JRE triggered memory leak
This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch 8.5.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/8.5.x by this push:
new 72cbdb9 Fix BZ 65553 - add workaround for JRE triggered memory leak
72cbdb9 is described below
commit 72cbdb92cad4d8ffbcac8945ca02036c9c2382f2
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Tue Sep 28 08:19:14 2021 +0100
Fix BZ 65553 - add workaround for JRE triggered memory leak
https://bz.apache.org/bugzilla/show_bug.cgi?id=65553
https://bugs.openjdk.java.net/browse/JDK-8273874
---
java/org/apache/catalina/realm/JNDIRealm.java | 242 +++++++++++++++++++++-----
webapps/docs/changelog.xml | 9 +
2 files changed, 208 insertions(+), 43 deletions(-)
diff --git a/java/org/apache/catalina/realm/JNDIRealm.java b/java/org/apache/catalina/realm/JNDIRealm.java
index b0e75a5..c16a444 100644
--- a/java/org/apache/catalina/realm/JNDIRealm.java
+++ b/java/org/apache/catalina/realm/JNDIRealm.java
@@ -22,6 +22,7 @@ import java.net.URISyntaxException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.Principal;
+import java.security.cert.X509Certificate;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
@@ -64,6 +65,7 @@ import javax.net.ssl.SSLSocketFactory;
import org.apache.catalina.LifecycleException;
import org.apache.tomcat.util.collections.SynchronizedStack;
+import org.ietf.jgss.GSSContext;
import org.ietf.jgss.GSSCredential;
import org.ietf.jgss.GSSName;
@@ -1223,10 +1225,19 @@ public class JNDIRealm extends RealmBase {
@Override
public Principal authenticate(String username, String credentials) {
+ ClassLoader ocl = null;
JNDIConnection connection = null;
Principal principal = null;
try {
+ // https://bz.apache.org/bugzilla/show_bug.cgi?id=65553
+ // This can move back to open() once it is known that Tomcat must be
+ // running on a JVM that includes a fix for
+ // https://bugs.openjdk.java.net/browse/JDK-8273874
+ if (!isUseContextClassLoader()) {
+ ocl = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
+ }
// Ensure that we have a directory context available
connection = get();
@@ -1290,6 +1301,10 @@ public class JNDIRealm extends RealmBase {
containerLog.debug("Returning null principal.");
}
return null;
+ } finally {
+ if (!isUseContextClassLoader()) {
+ Thread.currentThread().setContextClassLoader(ocl);
+ }
}
}
@@ -1316,52 +1331,189 @@ public class JNDIRealm extends RealmBase {
return null;
}
- if (userPatternArray != null) {
- for (int curUserPattern = 0; curUserPattern < userPatternArray.length; curUserPattern++) {
- // Retrieve user information
- User user = getUser(connection, username, credentials, curUserPattern);
- if (user != null) {
- try {
- // Check the user's credentials
- if (checkCredentials(connection.context, user, credentials)) {
- // Search for additional roles
- List<String> roles = getRoles(connection, user);
- if (containerLog.isDebugEnabled()) {
- containerLog.debug("Found roles: " + roles.toString());
+ ClassLoader ocl = null;
+ try {
+ // https://bz.apache.org/bugzilla/show_bug.cgi?id=65553
+ // This can move back to open() once it is known that Tomcat must be
+ // running on a JVM that includes a fix for
+ // https://bugs.openjdk.java.net/browse/JDK-8273874
+ if (!isUseContextClassLoader()) {
+ ocl = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
+ }
+
+ if (userPatternArray != null) {
+ for (int curUserPattern = 0; curUserPattern < userPatternArray.length; curUserPattern++) {
+ // Retrieve user information
+ User user = getUser(connection, username, credentials, curUserPattern);
+ if (user != null) {
+ try {
+ // Check the user's credentials
+ if (checkCredentials(connection.context, user, credentials)) {
+ // Search for additional roles
+ List<String> roles = getRoles(connection, user);
+ if (containerLog.isDebugEnabled()) {
+ containerLog.debug("Found roles: " + roles.toString());
+ }
+ return new GenericPrincipal(username, credentials, roles);
}
- return new GenericPrincipal(username, credentials, roles);
+ } catch (InvalidNameException ine) {
+ // Log the problem for posterity
+ containerLog.warn(sm.getString("jndiRealm.exception"), ine);
+ // ignore; this is probably due to a name not fitting
+ // the search path format exactly, as in a fully-
+ // qualified name being munged into a search path
+ // that already contains cn= or vice-versa
}
- } catch (InvalidNameException ine) {
- // Log the problem for posterity
- containerLog.warn(sm.getString("jndiRealm.exception"), ine);
- // ignore; this is probably due to a name not fitting
- // the search path format exactly, as in a fully-
- // qualified name being munged into a search path
- // that already contains cn= or vice-versa
}
}
- }
- return null;
- } else {
- // Retrieve user information
- User user = getUser(connection, username, credentials);
- if (user == null) {
return null;
+ } else {
+ // Retrieve user information
+ User user = getUser(connection, username, credentials);
+ if (user == null) {
+ return null;
+ }
+
+ // Check the user's credentials
+ if (!checkCredentials(connection.context, user, credentials)) {
+ return null;
+ }
+
+ // Search for additional roles
+ List<String> roles = getRoles(connection, user);
+ if (containerLog.isDebugEnabled()) {
+ containerLog.debug("Found roles: " + roles.toString());
+ }
+
+ // Create and return a suitable Principal for this user
+ return new GenericPrincipal(username, credentials, roles);
}
+ } finally {
+ if (!isUseContextClassLoader()) {
+ Thread.currentThread().setContextClassLoader(ocl);
+ }
+ }
+ }
- // Check the user's credentials
- if (!checkCredentials(connection.context, user, credentials)) {
- return null;
+
+ /*
+ * https://bz.apache.org/bugzilla/show_bug.cgi?id=65553
+ * This method can be removed and the class loader switch moved back to
+ * open() once it is known that Tomcat must be running on a JVM that
+ * includes a fix for
+ * https://bugs.openjdk.java.net/browse/JDK-8273874
+ */
+ @Override
+ public Principal authenticate(String username) {
+ ClassLoader ocl = null;
+ try {
+ if (!isUseContextClassLoader()) {
+ ocl = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
+ }
+ return super.authenticate(username);
+ } finally {
+ if (!isUseContextClassLoader()) {
+ Thread.currentThread().setContextClassLoader(ocl);
}
+ }
+ }
- // Search for additional roles
- List<String> roles = getRoles(connection, user);
- if (containerLog.isDebugEnabled()) {
- containerLog.debug("Found roles: " + roles.toString());
+
+ /*
+ * https://bz.apache.org/bugzilla/show_bug.cgi?id=65553
+ * This method can be removed and the class loader switch moved back to
+ * open() once it is known that Tomcat must be running on a JVM that
+ * includes a fix for
+ * https://bugs.openjdk.java.net/browse/JDK-8273874
+ */
+ @Override
+ public Principal authenticate(String username, String clientDigest, String nonce, String nc,
+ String cnonce, String qop, String realm, String md5a2) {
+ ClassLoader ocl = null;
+ try {
+ if (!isUseContextClassLoader()) {
+ ocl = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
+ }
+ return super.authenticate(username, clientDigest, nonce, nc, cnonce, qop, realm, md5a2);
+ } finally {
+ if (!isUseContextClassLoader()) {
+ Thread.currentThread().setContextClassLoader(ocl);
}
+ }
+ }
+
- // Create and return a suitable Principal for this user
- return new GenericPrincipal(username, credentials, roles);
+ /*
+ * https://bz.apache.org/bugzilla/show_bug.cgi?id=65553
+ * This method can be removed and the class loader switch moved back to
+ * open() once it is known that Tomcat must be running on a JVM that
+ * includes a fix for
+ * https://bugs.openjdk.java.net/browse/JDK-8273874
+ */
+ @Override
+ public Principal authenticate(X509Certificate[] certs) {
+ ClassLoader ocl = null;
+ try {
+ if (!isUseContextClassLoader()) {
+ ocl = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
+ }
+ return super.authenticate(certs);
+ } finally {
+ if (!isUseContextClassLoader()) {
+ Thread.currentThread().setContextClassLoader(ocl);
+ }
+ }
+ }
+
+
+ /*
+ * https://bz.apache.org/bugzilla/show_bug.cgi?id=65553
+ * This method can be removed and the class loader switch moved back to
+ * open() once it is known that Tomcat must be running on a JVM that
+ * includes a fix for
+ * https://bugs.openjdk.java.net/browse/JDK-8273874
+ */
+ @Override
+ public Principal authenticate(GSSContext gssContext, boolean storeCred) {
+ ClassLoader ocl = null;
+ try {
+ if (!isUseContextClassLoader()) {
+ ocl = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
+ }
+ return super.authenticate(gssContext, storeCred);
+ } finally {
+ if (!isUseContextClassLoader()) {
+ Thread.currentThread().setContextClassLoader(ocl);
+ }
+ }
+ }
+
+
+ /*
+ * https://bz.apache.org/bugzilla/show_bug.cgi?id=65553
+ * This method can be removed and the class loader switch moved back to
+ * open() once it is known that Tomcat must be running on a JVM that
+ * includes a fix for
+ * https://bugs.openjdk.java.net/browse/JDK-8273874
+ */
+ @Override
+ public Principal authenticate(GSSName gssName, GSSCredential gssCredential) {
+ ClassLoader ocl = null;
+ try {
+ if (!isUseContextClassLoader()) {
+ ocl = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
+ }
+ return super.authenticate(gssName, gssCredential);
+ } finally {
+ if (!isUseContextClassLoader()) {
+ Thread.currentThread().setContextClassLoader(ocl);
+ }
}
}
@@ -2473,12 +2625,7 @@ public class JNDIRealm extends RealmBase {
* @throws NamingException if a directory server error occurs
*/
protected void open(JNDIConnection connection) throws NamingException {
- ClassLoader ocl = null;
try {
- if (!isUseContextClassLoader()) {
- ocl = Thread.currentThread().getContextClassLoader();
- Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
- }
// Ensure that we have a directory context available
connection.context = createDirContext(getDirectoryContextEnvironment());
} catch (Exception e) {
@@ -2495,9 +2642,6 @@ public class JNDIRealm extends RealmBase {
// reset it in case the connection times out.
// the primary may come back.
connectionAttempt = 0;
- if (!isUseContextClassLoader()) {
- Thread.currentThread().setContextClassLoader(ocl);
- }
}
}
@@ -2683,8 +2827,17 @@ public class JNDIRealm extends RealmBase {
}
// Check to see if the connection to the directory can be opened
+ ClassLoader ocl = null;
JNDIConnection connection = null;
try {
+ // https://bz.apache.org/bugzilla/show_bug.cgi?id=65553
+ // This can move back to open() once it is known that Tomcat must be
+ // running on a JVM that includes a fix for
+ // https://bugs.openjdk.java.net/browse/JDK-8273874
+ if (!isUseContextClassLoader()) {
+ ocl = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
+ }
connection = get();
} catch (NamingException e) {
// A failure here is not fatal as the directory may be unavailable
@@ -2694,6 +2847,9 @@ public class JNDIRealm extends RealmBase {
containerLog.error(sm.getString("jndiRealm.open"), e);
} finally {
release(connection);
+ if (!isUseContextClassLoader()) {
+ Thread.currentThread().setContextClassLoader(ocl);
+ }
}
super.startInternal();
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 2c9deb3..85471c5 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -105,6 +105,15 @@
issues do not "pop up" wrt. others).
-->
<section name="Tomcat 8.5.72 (schultz)" rtext="in development">
+ <subsection name="Catalina">
+ <changelog>
+ <fix>
+ <bug>65553</bug>: Implement a work-around for a
+ <a href="https://bugs.openjdk.java.net/browse/JDK-8273874">JRE bug</a>
+ that can trigger a memory leak when using the JNDI realm. (markt)
+ </fix>
+ </changelog>
+ </subsection>
<subsection name="Coyote">
<changelog>
<fix>
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org