8139884: Use privileged blocks when working with class loaders
Reviewed-by: hannesw, mhaupt, sundar
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/ClassMap.java Mon Oct 19 18:24:47 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/ClassMap.java Mon Oct 19 22:36:03 2015 +0200
@@ -150,15 +150,15 @@
final T newV = computeValue(clazz);
assert newV != null;
- final ClassLoader clazzLoader = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
+ final Boolean canReferenceDirectly = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
@Override
- public ClassLoader run() {
- return clazz.getClassLoader();
+ public Boolean run() {
+ return Guards.canReferenceDirectly(classLoader, clazz.getClassLoader());
}
}, ClassLoaderGetterContextProvider.GET_CLASS_LOADER_CONTEXT);
// If allowed to strongly reference, put it in the fast map
- if(Guards.canReferenceDirectly(classLoader, clazzLoader)) {
+ if(canReferenceDirectly) {
final T oldV = map.putIfAbsent(clazz, newV);
return oldV != null ? oldV : newV;
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/ClassString.java Mon Oct 19 18:24:47 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/ClassString.java Mon Oct 19 22:36:03 2015 +0200
@@ -85,6 +85,9 @@
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodType;
+import java.security.AccessController;
+import java.security.Permission;
+import java.security.PrivilegedAction;
import java.util.LinkedList;
import java.util.List;
import jdk.internal.dynalink.linker.LinkerServices;
@@ -97,6 +100,8 @@
* JLS.
*/
final class ClassString {
+ private static final Permission GET_CLASS_LOADER_PERMISSION = new RuntimePermission("getClassLoader");
+
/**
* An anonymous inner class used solely to represent the "type" of null values for method applicability checking.
*/
@@ -143,12 +148,17 @@
}
boolean isVisibleFrom(final ClassLoader classLoader) {
- for(int i = 0; i < classes.length; ++i) {
- if(!Guards.canReferenceDirectly(classLoader, classes[i].getClassLoader())) {
- return false;
+ return AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
+ @Override
+ public Boolean run() {
+ for(final Class<?> clazz: classes) {
+ if(!Guards.canReferenceDirectly(classLoader, clazz.getClassLoader())) {
+ return false;
+ }
+ }
+ return true;
}
- }
- return true;
+ }, null, GET_CLASS_LOADER_PERMISSION);
}
List<MethodHandle> getMaximallySpecifics(final List<MethodHandle> methods, final LinkerServices linkerServices, final boolean varArg) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java Mon Oct 19 18:24:47 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java Mon Oct 19 22:36:03 2015 +0200
@@ -85,6 +85,11 @@
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodType;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.Permissions;
+import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Collections;
@@ -218,10 +223,27 @@
for(final SingleDynamicMethod method: invokables) {
methodHandles.add(method.getTarget(callSiteDescriptor));
}
- return new OverloadedMethod(methodHandles, this, callSiteType, linkerServices).getInvoker();
+ return new OverloadedMethod(methodHandles, this, getCallSiteClassLoader(callSiteDescriptor), callSiteType, linkerServices).getInvoker();
}
}
+ }
+ private static final AccessControlContext GET_CALL_SITE_CLASS_LOADER_CONTEXT;
+ static {
+ final Permissions perms = new Permissions();
+ perms.add(new RuntimePermission("getClassLoader"));
+ perms.add(CallSiteDescriptor.GET_LOOKUP_PERMISSION);
+ GET_CALL_SITE_CLASS_LOADER_CONTEXT = new AccessControlContext(
+ new ProtectionDomain[] { new ProtectionDomain(null, perms) });
+ }
+
+ private static ClassLoader getCallSiteClassLoader(final CallSiteDescriptor callSiteDescriptor) {
+ return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
+ @Override
+ public ClassLoader run() {
+ return callSiteDescriptor.getLookup().lookupClass().getClassLoader();
+ }
+ }, GET_CALL_SITE_CLASS_LOADER_CONTEXT);
}
@Override
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/OverloadedMethod.java Mon Oct 19 18:24:47 2015 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/OverloadedMethod.java Mon Oct 19 22:36:03 2015 +0200
@@ -104,15 +104,20 @@
class OverloadedMethod {
private final Map<ClassString, MethodHandle> argTypesToMethods = new ConcurrentHashMap<>();
private final OverloadedDynamicMethod parent;
+ private final ClassLoader callSiteClassLoader;
private final MethodType callSiteType;
private final MethodHandle invoker;
private final LinkerServices linkerServices;
private final ArrayList<MethodHandle> fixArgMethods;
private final ArrayList<MethodHandle> varArgMethods;
- OverloadedMethod(final List<MethodHandle> methodHandles, final OverloadedDynamicMethod parent, final MethodType callSiteType,
+ OverloadedMethod(final List<MethodHandle> methodHandles,
+ final OverloadedDynamicMethod parent,
+ final ClassLoader callSiteClassLoader,
+ final MethodType callSiteType,
final LinkerServices linkerServices) {
this.parent = parent;
+ this.callSiteClassLoader = callSiteClassLoader;
final Class<?> commonRetType = getCommonReturnType(methodHandles);
this.callSiteType = callSiteType.changeReturnType(commonRetType);
this.linkerServices = linkerServices;
@@ -179,7 +184,7 @@
}
// Avoid keeping references to unrelated classes; this ruins the performance a bit, but avoids class loader
// memory leaks.
- if(classString.isVisibleFrom(parent.getClassLoader())) {
+ if(classString.isVisibleFrom(callSiteClassLoader)) {
argTypesToMethods.put(classString, method);
}
}