7193339: Prepare system classes be defined by a non-null module loader
Reviewed-by: alanb, dholmes, dsamersoff, sspitsyn, psandoz
This commit is contained in:
parent
54f3f7f7ed
commit
9108824515
@ -169,7 +169,7 @@ public abstract class MXBeanMapping {
|
||||
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
|
||||
}
|
||||
|
@ -52,7 +52,8 @@ public final class IIOPHelper {
|
||||
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;
|
||||
|
@ -228,7 +228,8 @@ public final
|
||||
* 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 @@ public final
|
||||
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 @@ public final
|
||||
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) {
|
||||
|
@ -1403,7 +1403,7 @@ public abstract class ClassLoader {
|
||||
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 @@ public abstract class ClassLoader {
|
||||
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 @@ public abstract class ClassLoader {
|
||||
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
|
||||
|
@ -1449,8 +1449,7 @@ class Thread implements Runnable {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -576,16 +576,16 @@ public class ManagementFactory {
|
||||
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 @@ public class ManagementFactory {
|
||||
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;
|
||||
|
@ -363,7 +363,8 @@ enum PlatformComponent {
|
||||
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);
|
||||
}
|
||||
|
@ -300,7 +300,8 @@ public abstract class Preferences {
|
||||
}
|
||||
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 "
|
||||
|
@ -423,7 +423,7 @@ public class ScriptEngineManager {
|
||||
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);
|
||||
|
@ -803,7 +803,7 @@ public abstract class MappedMXBeanType {
|
||||
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
|
||||
|
@ -82,7 +82,7 @@ public final class Unsafe {
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
@ -217,6 +217,14 @@ public class VM {
|
||||
return allowArraySyntax;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
@ -144,4 +144,38 @@ public final class ReflectUtil {
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user