7193339: Prepare system classes be defined by a non-null module loader
Reviewed-by: alanb, dholmes, dsamersoff, sspitsyn, psandoz
--- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/MXBeanMapping.java Fri Aug 24 11:48:51 2012 -0700
+++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/MXBeanMapping.java Fri Aug 24 22:55:49 2012 -0700
@@ -169,7 +169,7 @@
return (Class<?>) javaType;
try {
String className = openType.getClassName();
- return Class.forName(className, false, null);
+ return Class.forName(className, false, MXBeanMapping.class.getClassLoader());
} catch (ClassNotFoundException e) {
throw new RuntimeException(e); // should not happen
}
--- a/jdk/src/share/classes/com/sun/jmx/remote/internal/IIOPHelper.java Fri Aug 24 11:48:51 2012 -0700
+++ b/jdk/src/share/classes/com/sun/jmx/remote/internal/IIOPHelper.java Fri Aug 24 22:55:49 2012 -0700
@@ -52,7 +52,8 @@
AccessController.doPrivileged(new PrivilegedAction<IIOPProxy>() {
public IIOPProxy run() {
try {
- Class<?> c = Class.forName(IMPL_CLASS, true, null);
+ Class<?> c = Class.forName(IMPL_CLASS, true,
+ IIOPHelper.class.getClassLoader());
return (IIOPProxy)c.newInstance();
} catch (ClassNotFoundException cnf) {
return null;
--- a/jdk/src/share/classes/java/lang/Class.java Fri Aug 24 11:48:51 2012 -0700
+++ b/jdk/src/share/classes/java/lang/Class.java Fri Aug 24 22:55:49 2012 -0700
@@ -228,7 +228,8 @@
* ensure it's ok to access the bootstrap class loader.
*
* @param name fully qualified name of the desired class
- * @param initialize whether the class must be initialized
+ * @param initialize if {@code true} the class will be initialized.
+ * See Section 12.4 of <em>The Java Language Specification</em>.
* @param loader class loader from which the class must be loaded
* @return class object representing the desired class
*
@@ -605,7 +606,7 @@
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
ClassLoader ccl = ClassLoader.getCallerClassLoader();
- if (ccl != null && ccl != cl && !cl.isAncestor(ccl)) {
+ if (ClassLoader.needsClassLoaderPermissionCheck(ccl, cl)) {
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
}
}
@@ -2170,8 +2171,7 @@
if (s != null) {
s.checkMemberAccess(this, which);
ClassLoader cl = getClassLoader0();
- if ((ccl != null) && (ccl != cl) &&
- ((cl == null) || !cl.isAncestor(ccl))) {
+ if (sun.reflect.misc.ReflectUtil.needsPackageAccessCheck(ccl, cl)) {
String name = this.getName();
int i = name.lastIndexOf('.');
if (i != -1) {
--- a/jdk/src/share/classes/java/lang/ClassLoader.java Fri Aug 24 11:48:51 2012 -0700
+++ b/jdk/src/share/classes/java/lang/ClassLoader.java Fri Aug 24 22:55:49 2012 -0700
@@ -1403,7 +1403,7 @@
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
ClassLoader ccl = getCallerClassLoader();
- if (ccl != null && !isAncestor(ccl)) {
+ if (needsClassLoaderPermissionCheck(ccl, this)) {
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
}
}
@@ -1473,7 +1473,7 @@
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
ClassLoader ccl = getCallerClassLoader();
- if (ccl != null && ccl != scl && !scl.isAncestor(ccl)) {
+ if (needsClassLoaderPermissionCheck(ccl, scl)) {
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
}
}
@@ -1523,6 +1523,23 @@
return false;
}
+ // Tests if class loader access requires "getClassLoader" permission
+ // check. A class loader 'from' can access class loader 'to' if
+ // class loader 'from' is same as class loader 'to' or an ancestor
+ // of 'to'. The class loader in a system domain can access
+ // any class loader.
+ static boolean needsClassLoaderPermissionCheck(ClassLoader from,
+ ClassLoader to)
+ {
+ if (from == to)
+ return false;
+
+ if (from == null)
+ return false;
+
+ return !to.isAncestor(from);
+ }
+
// Returns the invoker's class loader, or null if none.
// NOTE: This must always be invoked when there is exactly one intervening
// frame from the core libraries on the stack between this method's
--- a/jdk/src/share/classes/java/lang/Thread.java Fri Aug 24 11:48:51 2012 -0700
+++ b/jdk/src/share/classes/java/lang/Thread.java Fri Aug 24 22:55:49 2012 -0700
@@ -1449,8 +1449,7 @@
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
ClassLoader ccl = ClassLoader.getCallerClassLoader();
- if (ccl != null && ccl != contextClassLoader &&
- !contextClassLoader.isAncestor(ccl)) {
+ if (ClassLoader.needsClassLoaderPermissionCheck(ccl, contextClassLoader)) {
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
}
}
--- a/jdk/src/share/classes/java/lang/management/ManagementFactory.java Fri Aug 24 11:48:51 2012 -0700
+++ b/jdk/src/share/classes/java/lang/management/ManagementFactory.java Fri Aug 24 22:55:49 2012 -0700
@@ -576,16 +576,16 @@
Class<T> mxbeanInterface)
throws java.io.IOException {
- final Class<?> interfaceClass = mxbeanInterface;
// Only allow MXBean interfaces from rt.jar loaded by the
// bootstrap class loader
- final ClassLoader loader =
+ final Class<?> cls = mxbeanInterface;
+ ClassLoader loader =
AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
public ClassLoader run() {
- return interfaceClass.getClassLoader();
+ return cls.getClassLoader();
}
});
- if (loader != null) {
+ if (!sun.misc.VM.isSystemDomainLoader(loader)) {
throw new IllegalArgumentException(mxbeanName +
" is not a platform MXBean");
}
@@ -593,10 +593,10 @@
try {
final ObjectName objName = new ObjectName(mxbeanName);
// skip the isInstanceOf check for LoggingMXBean
- String intfName = interfaceClass.getName();
+ String intfName = mxbeanInterface.getName();
if (!connection.isInstanceOf(objName, intfName)) {
throw new IllegalArgumentException(mxbeanName +
- " is not an instance of " + interfaceClass);
+ " is not an instance of " + mxbeanInterface);
}
final Class[] interfaces;
--- a/jdk/src/share/classes/java/lang/management/PlatformComponent.java Fri Aug 24 11:48:51 2012 -0700
+++ b/jdk/src/share/classes/java/lang/management/PlatformComponent.java Fri Aug 24 22:55:49 2012 -0700
@@ -363,7 +363,8 @@
try {
// Lazy loading the MXBean interface only when it is needed
return (Class<? extends PlatformManagedObject>)
- Class.forName(mxbeanInterfaceName, false, null);
+ Class.forName(mxbeanInterfaceName, false,
+ PlatformManagedObject.class.getClassLoader());
} catch (ClassNotFoundException x) {
throw new AssertionError(x);
}
--- a/jdk/src/share/classes/java/util/prefs/Preferences.java Fri Aug 24 11:48:51 2012 -0700
+++ b/jdk/src/share/classes/java/util/prefs/Preferences.java Fri Aug 24 22:55:49 2012 -0700
@@ -300,7 +300,8 @@
}
try {
return (PreferencesFactory)
- Class.forName(platformFactory, false, null).newInstance();
+ Class.forName(platformFactory, false,
+ Preferences.class.getClassLoader()).newInstance();
} catch (Exception e) {
throw new InternalError(
"Can't instantiate platform default Preferences factory "
--- a/jdk/src/share/classes/javax/script/ScriptEngineManager.java Fri Aug 24 11:48:51 2012 -0700
+++ b/jdk/src/share/classes/javax/script/ScriptEngineManager.java Fri Aug 24 22:55:49 2012 -0700
@@ -423,7 +423,7 @@
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
ClassLoader callerLoader = getCallerClassLoader();
- if (callerLoader != null) {
+ if (!sun.misc.VM.isSystemDomainLoader(callerLoader)) {
if (loader != callerLoader || !isAncestor(loader, callerLoader)) {
try {
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
--- a/jdk/src/share/classes/sun/management/MappedMXBeanType.java Fri Aug 24 11:48:51 2012 -0700
+++ b/jdk/src/share/classes/sun/management/MappedMXBeanType.java Fri Aug 24 22:55:49 2012 -0700
@@ -803,7 +803,7 @@
Class<?> c;
try {
c = Class.forName(t.getClassName(), false,
- String.class.getClassLoader());
+ MappedMXBeanType.class.getClassLoader());
MappedMXBeanType.newBasicType(c, t);
} catch (ClassNotFoundException e) {
// the classes that these predefined types declare
--- a/jdk/src/share/classes/sun/misc/Unsafe.java Fri Aug 24 11:48:51 2012 -0700
+++ b/jdk/src/share/classes/sun/misc/Unsafe.java Fri Aug 24 22:55:49 2012 -0700
@@ -82,7 +82,7 @@
*/
public static Unsafe getUnsafe() {
Class<?> cc = sun.reflect.Reflection.getCallerClass(2);
- if (cc.getClassLoader() != null)
+ if (!VM.isSystemDomainLoader(cc.getClassLoader()))
throw new SecurityException("Unsafe");
return theUnsafe;
}
--- a/jdk/src/share/classes/sun/misc/VM.java Fri Aug 24 11:48:51 2012 -0700
+++ b/jdk/src/share/classes/sun/misc/VM.java Fri Aug 24 22:55:49 2012 -0700
@@ -218,6 +218,14 @@
}
/**
+ * Returns true if the given class loader is in the system domain
+ * in which all permissions are granted.
+ */
+ public static boolean isSystemDomainLoader(ClassLoader loader) {
+ return loader == null;
+ }
+
+ /**
* Returns the system property of the specified key saved at
* system initialization time. This method should only be used
* for the system properties that are not changed during runtime.
--- a/jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java Fri Aug 24 11:48:51 2012 -0700
+++ b/jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java Fri Aug 24 22:55:49 2012 -0700
@@ -144,4 +144,38 @@
}
return true;
}
+
+ // Returns true if p is an ancestor of cl i.e. class loader 'p' can
+ // be found in the cl's delegation chain
+ private static boolean isAncestor(ClassLoader p, ClassLoader cl) {
+ ClassLoader acl = cl;
+ do {
+ acl = acl.getParent();
+ if (p == acl) {
+ return true;
+ }
+ } while (acl != null);
+ return false;
+ }
+
+ /**
+ * Returns true if package access check is needed for reflective
+ * access from a class loader 'from' to classes or members in
+ * a class defined by class loader 'to'. This method returns true
+ * if 'from' is not the same as or an ancestor of 'to'. All code
+ * in a system domain are granted with all permission and so this
+ * method returns false if 'from' class loader is a class loader
+ * loading system classes. On the other hand, if a class loader
+ * attempts to access system domain classes, it requires package
+ * access check and this method will return true.
+ */
+ public static boolean needsPackageAccessCheck(ClassLoader from, ClassLoader to) {
+ if (from == null || from == to)
+ return false;
+
+ if (to == null)
+ return true;
+
+ return !isAncestor(from, to);
+ }
}