提交 fb96db84 编写于 作者: M mchung

7193339: Prepare system classes be defined by a non-null module loader

Reviewed-by: alanb, dholmes, dsamersoff, sspitsyn, psandoz
上级 b1da5910
...@@ -169,7 +169,7 @@ public abstract class MXBeanMapping { ...@@ -169,7 +169,7 @@ public abstract class MXBeanMapping {
return (Class<?>) javaType; return (Class<?>) javaType;
try { try {
String className = openType.getClassName(); String className = openType.getClassName();
return Class.forName(className, false, null); return Class.forName(className, false, MXBeanMapping.class.getClassLoader());
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
throw new RuntimeException(e); // should not happen throw new RuntimeException(e); // should not happen
} }
......
...@@ -52,7 +52,8 @@ public final class IIOPHelper { ...@@ -52,7 +52,8 @@ public final class IIOPHelper {
AccessController.doPrivileged(new PrivilegedAction<IIOPProxy>() { AccessController.doPrivileged(new PrivilegedAction<IIOPProxy>() {
public IIOPProxy run() { public IIOPProxy run() {
try { try {
Class<?> c = Class.forName(IMPL_CLASS, true, null); Class<?> c = Class.forName(IMPL_CLASS, true,
IIOPHelper.class.getClassLoader());
return (IIOPProxy)c.newInstance(); return (IIOPProxy)c.newInstance();
} catch (ClassNotFoundException cnf) { } catch (ClassNotFoundException cnf) {
return null; return null;
......
...@@ -228,7 +228,8 @@ public final ...@@ -228,7 +228,8 @@ public final
* ensure it's ok to access the bootstrap class loader. * ensure it's ok to access the bootstrap class loader.
* *
* @param name fully qualified name of the desired class * @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 * @param loader class loader from which the class must be loaded
* @return class object representing the desired class * @return class object representing the desired class
* *
...@@ -605,7 +606,7 @@ public final ...@@ -605,7 +606,7 @@ public final
SecurityManager sm = System.getSecurityManager(); SecurityManager sm = System.getSecurityManager();
if (sm != null) { if (sm != null) {
ClassLoader ccl = ClassLoader.getCallerClassLoader(); ClassLoader ccl = ClassLoader.getCallerClassLoader();
if (ccl != null && ccl != cl && !cl.isAncestor(ccl)) { if (ClassLoader.needsClassLoaderPermissionCheck(ccl, cl)) {
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
} }
} }
...@@ -2170,8 +2171,7 @@ public final ...@@ -2170,8 +2171,7 @@ public final
if (s != null) { if (s != null) {
s.checkMemberAccess(this, which); s.checkMemberAccess(this, which);
ClassLoader cl = getClassLoader0(); ClassLoader cl = getClassLoader0();
if ((ccl != null) && (ccl != cl) && if (sun.reflect.misc.ReflectUtil.needsPackageAccessCheck(ccl, cl)) {
((cl == null) || !cl.isAncestor(ccl))) {
String name = this.getName(); String name = this.getName();
int i = name.lastIndexOf('.'); int i = name.lastIndexOf('.');
if (i != -1) { if (i != -1) {
......
...@@ -1403,7 +1403,7 @@ public abstract class ClassLoader { ...@@ -1403,7 +1403,7 @@ public abstract class ClassLoader {
SecurityManager sm = System.getSecurityManager(); SecurityManager sm = System.getSecurityManager();
if (sm != null) { if (sm != null) {
ClassLoader ccl = getCallerClassLoader(); ClassLoader ccl = getCallerClassLoader();
if (ccl != null && !isAncestor(ccl)) { if (needsClassLoaderPermissionCheck(ccl, this)) {
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
} }
} }
...@@ -1473,7 +1473,7 @@ public abstract class ClassLoader { ...@@ -1473,7 +1473,7 @@ public abstract class ClassLoader {
SecurityManager sm = System.getSecurityManager(); SecurityManager sm = System.getSecurityManager();
if (sm != null) { if (sm != null) {
ClassLoader ccl = getCallerClassLoader(); ClassLoader ccl = getCallerClassLoader();
if (ccl != null && ccl != scl && !scl.isAncestor(ccl)) { if (needsClassLoaderPermissionCheck(ccl, scl)) {
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
} }
} }
...@@ -1523,6 +1523,23 @@ public abstract class ClassLoader { ...@@ -1523,6 +1523,23 @@ public abstract class ClassLoader {
return false; 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. // Returns the invoker's class loader, or null if none.
// NOTE: This must always be invoked when there is exactly one intervening // NOTE: This must always be invoked when there is exactly one intervening
// frame from the core libraries on the stack between this method's // frame from the core libraries on the stack between this method's
......
...@@ -1449,8 +1449,7 @@ class Thread implements Runnable { ...@@ -1449,8 +1449,7 @@ class Thread implements Runnable {
SecurityManager sm = System.getSecurityManager(); SecurityManager sm = System.getSecurityManager();
if (sm != null) { if (sm != null) {
ClassLoader ccl = ClassLoader.getCallerClassLoader(); ClassLoader ccl = ClassLoader.getCallerClassLoader();
if (ccl != null && ccl != contextClassLoader && if (ClassLoader.needsClassLoaderPermissionCheck(ccl, contextClassLoader)) {
!contextClassLoader.isAncestor(ccl)) {
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
} }
} }
......
...@@ -576,16 +576,16 @@ public class ManagementFactory { ...@@ -576,16 +576,16 @@ public class ManagementFactory {
Class<T> mxbeanInterface) Class<T> mxbeanInterface)
throws java.io.IOException { throws java.io.IOException {
final Class<?> interfaceClass = mxbeanInterface;
// Only allow MXBean interfaces from rt.jar loaded by the // Only allow MXBean interfaces from rt.jar loaded by the
// bootstrap class loader // bootstrap class loader
final ClassLoader loader = final Class<?> cls = mxbeanInterface;
ClassLoader loader =
AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() { AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
public ClassLoader run() { public ClassLoader run() {
return interfaceClass.getClassLoader(); return cls.getClassLoader();
} }
}); });
if (loader != null) { if (!sun.misc.VM.isSystemDomainLoader(loader)) {
throw new IllegalArgumentException(mxbeanName + throw new IllegalArgumentException(mxbeanName +
" is not a platform MXBean"); " is not a platform MXBean");
} }
...@@ -593,10 +593,10 @@ public class ManagementFactory { ...@@ -593,10 +593,10 @@ public class ManagementFactory {
try { try {
final ObjectName objName = new ObjectName(mxbeanName); final ObjectName objName = new ObjectName(mxbeanName);
// skip the isInstanceOf check for LoggingMXBean // skip the isInstanceOf check for LoggingMXBean
String intfName = interfaceClass.getName(); String intfName = mxbeanInterface.getName();
if (!connection.isInstanceOf(objName, intfName)) { if (!connection.isInstanceOf(objName, intfName)) {
throw new IllegalArgumentException(mxbeanName + throw new IllegalArgumentException(mxbeanName +
" is not an instance of " + interfaceClass); " is not an instance of " + mxbeanInterface);
} }
final Class[] interfaces; final Class[] interfaces;
......
...@@ -363,7 +363,8 @@ enum PlatformComponent { ...@@ -363,7 +363,8 @@ enum PlatformComponent {
try { try {
// Lazy loading the MXBean interface only when it is needed // Lazy loading the MXBean interface only when it is needed
return (Class<? extends PlatformManagedObject>) return (Class<? extends PlatformManagedObject>)
Class.forName(mxbeanInterfaceName, false, null); Class.forName(mxbeanInterfaceName, false,
PlatformManagedObject.class.getClassLoader());
} catch (ClassNotFoundException x) { } catch (ClassNotFoundException x) {
throw new AssertionError(x); throw new AssertionError(x);
} }
......
...@@ -300,7 +300,8 @@ public abstract class Preferences { ...@@ -300,7 +300,8 @@ public abstract class Preferences {
} }
try { try {
return (PreferencesFactory) return (PreferencesFactory)
Class.forName(platformFactory, false, null).newInstance(); Class.forName(platformFactory, false,
Preferences.class.getClassLoader()).newInstance();
} catch (Exception e) { } catch (Exception e) {
throw new InternalError( throw new InternalError(
"Can't instantiate platform default Preferences factory " "Can't instantiate platform default Preferences factory "
......
...@@ -423,7 +423,7 @@ public class ScriptEngineManager { ...@@ -423,7 +423,7 @@ public class ScriptEngineManager {
SecurityManager sm = System.getSecurityManager(); SecurityManager sm = System.getSecurityManager();
if (sm != null) { if (sm != null) {
ClassLoader callerLoader = getCallerClassLoader(); ClassLoader callerLoader = getCallerClassLoader();
if (callerLoader != null) { if (!sun.misc.VM.isSystemDomainLoader(callerLoader)) {
if (loader != callerLoader || !isAncestor(loader, callerLoader)) { if (loader != callerLoader || !isAncestor(loader, callerLoader)) {
try { try {
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
......
...@@ -803,7 +803,7 @@ public abstract class MappedMXBeanType { ...@@ -803,7 +803,7 @@ public abstract class MappedMXBeanType {
Class<?> c; Class<?> c;
try { try {
c = Class.forName(t.getClassName(), false, c = Class.forName(t.getClassName(), false,
String.class.getClassLoader()); MappedMXBeanType.class.getClassLoader());
MappedMXBeanType.newBasicType(c, t); MappedMXBeanType.newBasicType(c, t);
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
// the classes that these predefined types declare // the classes that these predefined types declare
......
...@@ -82,7 +82,7 @@ public final class Unsafe { ...@@ -82,7 +82,7 @@ public final class Unsafe {
*/ */
public static Unsafe getUnsafe() { public static Unsafe getUnsafe() {
Class<?> cc = sun.reflect.Reflection.getCallerClass(2); Class<?> cc = sun.reflect.Reflection.getCallerClass(2);
if (cc.getClassLoader() != null) if (!VM.isSystemDomainLoader(cc.getClassLoader()))
throw new SecurityException("Unsafe"); throw new SecurityException("Unsafe");
return theUnsafe; return theUnsafe;
} }
......
...@@ -217,6 +217,14 @@ public class VM { ...@@ -217,6 +217,14 @@ public class VM {
return allowArraySyntax; 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 * Returns the system property of the specified key saved at
* system initialization time. This method should only be used * system initialization time. This method should only be used
......
...@@ -144,4 +144,38 @@ public final class ReflectUtil { ...@@ -144,4 +144,38 @@ public final class ReflectUtil {
} }
return true; 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);
}
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册