mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 07:14:30 +02:00
8234466: Class loading deadlock involving X509Factory#commitEvent()
Reviewed-by: alanb, chegar, dfuchs
This commit is contained in:
parent
ab90653aa9
commit
2c5167803a
8 changed files with 405 additions and 18 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -157,8 +157,10 @@ public class JarFile extends ZipFile {
|
|||
private boolean jvInitialized;
|
||||
private boolean verify;
|
||||
private final Runtime.Version version; // current version
|
||||
private final int versionFeature; // version.feature()
|
||||
private final int versionFeature; // version.feature()
|
||||
private boolean isMultiRelease; // is jar multi-release?
|
||||
static final ThreadLocal<Boolean> isInitializing =
|
||||
ThreadLocal.withInitial(() -> Boolean.FALSE);
|
||||
|
||||
// indicates if Class-Path attribute present
|
||||
private boolean hasClassPathAttribute;
|
||||
|
@ -1031,8 +1033,13 @@ public class JarFile extends ZipFile {
|
|||
throw new RuntimeException(e);
|
||||
}
|
||||
if (jv != null && !jvInitialized) {
|
||||
initializeVerifier();
|
||||
jvInitialized = true;
|
||||
isInitializing.set(Boolean.TRUE);
|
||||
try {
|
||||
initializeVerifier();
|
||||
jvInitialized = true;
|
||||
} finally {
|
||||
isInitializing.set(Boolean.FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -68,4 +68,8 @@ class JavaUtilJarAccessImpl implements JavaUtilJarAccess {
|
|||
public void ensureInitialization(JarFile jar) {
|
||||
jar.ensureInitialization();
|
||||
}
|
||||
|
||||
public Boolean isInitializing() {
|
||||
return JarFile.isInitializing.get();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -45,4 +45,5 @@ public interface JavaUtilJarAccess {
|
|||
public List<Object> getManifestDigests(JarFile jar);
|
||||
public Attributes getTrustedAttributes(Manifest man, String name);
|
||||
public void ensureInitialization(JarFile jar);
|
||||
public Boolean isInitializing();
|
||||
}
|
||||
|
|
|
@ -25,6 +25,11 @@
|
|||
|
||||
package jdk.internal.event;
|
||||
|
||||
import jdk.internal.access.JavaUtilJarAccess;
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Date;
|
||||
|
@ -37,14 +42,24 @@ import java.util.stream.IntStream;
|
|||
|
||||
public final class EventHelper {
|
||||
|
||||
private static final JavaUtilJarAccess JUJA = SharedSecrets.javaUtilJarAccess();
|
||||
private static volatile boolean loggingSecurity;
|
||||
private static volatile System.Logger securityLogger;
|
||||
private static final VarHandle LOGGER_HANDLE;
|
||||
static {
|
||||
try {
|
||||
LOGGER_HANDLE =
|
||||
MethodHandles.lookup().findStaticVarHandle(
|
||||
EventHelper.class, "securityLogger", System.Logger.class);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
private static final System.Logger.Level LOG_LEVEL = System.Logger.Level.DEBUG;
|
||||
|
||||
// helper class used for logging security related events for now
|
||||
private static final String SECURITY_LOGGER_NAME = "jdk.event.security";
|
||||
private static final System.Logger SECURITY_LOGGER =
|
||||
System.getLogger(SECURITY_LOGGER_NAME);
|
||||
private static final boolean LOGGING_SECURITY =
|
||||
SECURITY_LOGGER.isLoggable(LOG_LEVEL);
|
||||
|
||||
|
||||
public static void logTLSHandshakeEvent(Instant start,
|
||||
String peerHost,
|
||||
|
@ -52,8 +67,9 @@ public final class EventHelper {
|
|||
String cipherSuite,
|
||||
String protocolVersion,
|
||||
long peerCertId) {
|
||||
assert securityLogger != null;
|
||||
String prepend = getDurationString(start);
|
||||
SECURITY_LOGGER.log(LOG_LEVEL, prepend +
|
||||
securityLogger.log(LOG_LEVEL, prepend +
|
||||
" TLSHandshake: {0}:{1,number,#}, {2}, {3}, {4,number,#}",
|
||||
peerHost, peerPort, protocolVersion, cipherSuite, peerCertId);
|
||||
}
|
||||
|
@ -61,18 +77,18 @@ public final class EventHelper {
|
|||
public static void logSecurityPropertyEvent(String key,
|
||||
String value) {
|
||||
|
||||
if (isLoggingSecurity()) {
|
||||
SECURITY_LOGGER.log(LOG_LEVEL,
|
||||
"SecurityPropertyModification: key:{0}, value:{1}", key, value);
|
||||
}
|
||||
assert securityLogger != null;
|
||||
securityLogger.log(LOG_LEVEL,
|
||||
"SecurityPropertyModification: key:{0}, value:{1}", key, value);
|
||||
}
|
||||
|
||||
public static void logX509ValidationEvent(int anchorCertId,
|
||||
int[] certIds) {
|
||||
assert securityLogger != null;
|
||||
String codes = IntStream.of(certIds)
|
||||
.mapToObj(Integer::toString)
|
||||
.collect(Collectors.joining(", "));
|
||||
SECURITY_LOGGER.log(LOG_LEVEL,
|
||||
securityLogger.log(LOG_LEVEL,
|
||||
"ValidationChain: {0,number,#}, {1}", anchorCertId, codes);
|
||||
}
|
||||
|
||||
|
@ -85,7 +101,8 @@ public final class EventHelper {
|
|||
long certId,
|
||||
long beginDate,
|
||||
long endDate) {
|
||||
SECURITY_LOGGER.log(LOG_LEVEL, "X509Certificate: Alg:{0}, Serial:{1}" +
|
||||
assert securityLogger != null;
|
||||
securityLogger.log(LOG_LEVEL, "X509Certificate: Alg:{0}, Serial:{1}" +
|
||||
", Subject:{2}, Issuer:{3}, Key type:{4}, Length:{5,number,#}" +
|
||||
", Cert Id:{6,number,#}, Valid from:{7}, Valid until:{8}",
|
||||
algId, serialNum, subject, issuer, keyType, length,
|
||||
|
@ -124,6 +141,14 @@ public final class EventHelper {
|
|||
* @return boolean indicating whether an event should be logged
|
||||
*/
|
||||
public static boolean isLoggingSecurity() {
|
||||
return LOGGING_SECURITY;
|
||||
// Avoid a bootstrap issue where the commitEvent attempts to
|
||||
// trigger early loading of System Logger but where
|
||||
// the verification process still has JarFiles locked
|
||||
if (securityLogger == null && !JUJA.isInitializing()) {
|
||||
LOGGER_HANDLE.compareAndSet( null, System.getLogger(SECURITY_LOGGER_NAME));
|
||||
loggingSecurity = securityLogger.isLoggable(LOG_LEVEL);
|
||||
}
|
||||
return loggingSecurity;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue