diff --git a/jdk/src/share/classes/java/lang/Class.java b/jdk/src/share/classes/java/lang/Class.java index 614ecdf3d46..365c8aadb72 100644 --- a/jdk/src/share/classes/java/lang/Class.java +++ b/jdk/src/share/classes/java/lang/Class.java @@ -2338,7 +2338,7 @@ public final class Class implements java.io.Serializable, if (i != -1) { // skip the package access check on a proxy class in default proxy package String pkg = name.substring(0, i); - if (!Proxy.isProxyClass(this) || !pkg.equals(ReflectUtil.PROXY_PACKAGE)) { + if (!Proxy.isProxyClass(this) || ReflectUtil.isNonPublicProxyClass(this)) { s.checkPackageAccess(pkg); } } diff --git a/jdk/src/share/classes/java/lang/reflect/Proxy.java b/jdk/src/share/classes/java/lang/reflect/Proxy.java index e6de8b77956..96e81964752 100644 --- a/jdk/src/share/classes/java/lang/reflect/Proxy.java +++ b/jdk/src/share/classes/java/lang/reflect/Proxy.java @@ -734,25 +734,21 @@ public class Proxy implements java.io.Serializable { private static void checkNewProxyPermission(Class caller, Class proxyClass) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { - String pcn = proxyClass.getName(); - if (pcn.startsWith(ReflectUtil.PROXY_PACKAGE + ".")) { - // all proxy interfaces are public - return; - } + if (ReflectUtil.isNonPublicProxyClass(proxyClass)) { + ClassLoader ccl = caller.getClassLoader(); + ClassLoader pcl = proxyClass.getClassLoader(); - ClassLoader ccl = caller.getClassLoader(); - ClassLoader pcl = proxyClass.getClassLoader(); + // do permission check if the caller is in a different runtime package + // of the proxy class + int n = proxyClass.getName().lastIndexOf('.'); + String pkg = (n == -1) ? "" : proxyClass.getName().substring(0, n); - // do permission check if the caller is in a different runtime package - // of the proxy class - int n = pcn.lastIndexOf('.'); - String pkg = (n == -1) ? "" : pcn.substring(0, n); + n = caller.getName().lastIndexOf('.'); + String callerPkg = (n == -1) ? "" : caller.getName().substring(0, n); - n = caller.getName().lastIndexOf('.'); - String callerPkg = (n == -1) ? "" : caller.getName().substring(0, n); - - if (pcl != ccl || !pkg.equals(callerPkg)) { - sm.checkPermission(new ReflectPermission("newProxyInPackage." + pkg)); + if (pcl != ccl || !pkg.equals(callerPkg)) { + sm.checkPermission(new ReflectPermission("newProxyInPackage." + pkg)); + } } } } diff --git a/jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java b/jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java index 0640d92e5d0..efd85fca9cb 100644 --- a/jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java +++ b/jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java @@ -27,6 +27,7 @@ package sun.reflect.misc; import java.lang.reflect.Modifier; +import java.lang.reflect.Proxy; import sun.reflect.Reflection; public final class ReflectUtil { @@ -114,11 +115,26 @@ public final class ReflectUtil { return false; } - + /** + * Checks package access on the given class. + * + * If it is a {@link Proxy#isProxyClass(java.lang.Class)} that implements + * a non-public interface (i.e. may be in a non-restricted package), + * also check the package access on the proxy interfaces. + */ public static void checkPackageAccess(Class clazz) { checkPackageAccess(clazz.getName()); + if (isNonPublicProxyClass(clazz)) { + checkProxyPackageAccess(clazz); + } } + /** + * Checks package access on the given classname. + * This method is typically called when the Class instance is not + * available and the caller attempts to load a class on behalf + * the true caller (application). + */ public static void checkPackageAccess(String name) { SecurityManager s = System.getSecurityManager(); if (s != null) { @@ -179,14 +195,31 @@ public final class ReflectUtil { return !isAncestor(from, to); } + /** + * Check package access on the proxy interfaces that the given proxy class + * implements. + * + * @param clazz Proxy class object + */ + public static void checkProxyPackageAccess(Class clazz) { + SecurityManager s = System.getSecurityManager(); + if (s != null) { + // check proxy interfaces if the given class is a proxy class + if (Proxy.isProxyClass(clazz)) { + for (Class intf : clazz.getInterfaces()) { + checkPackageAccess(intf); + } + } + } + } + /** * Access check on the interfaces that a proxy class implements and throw - * {@code SecurityException} if it accesses a restricted package. + * {@code SecurityException} if it accesses a restricted package from + * the caller's class loader. * * @param ccl the caller's class loader * @param interfaces the list of interfaces that a proxy class implements - * - * @see Proxy#checkProxyAccess */ public static void checkProxyPackageAccess(ClassLoader ccl, Class... interfaces) @@ -205,4 +238,16 @@ public final class ReflectUtil { // Note that bytecode instrumentation tools may exclude 'sun.*' // classes but not generated proxy classes and so keep it in com.sun.* public static final String PROXY_PACKAGE = "com.sun.proxy"; + + /** + * Test if the given class is a proxy class that implements + * non-public interface. Such proxy class may be in a non-restricted + * package that bypasses checkPackageAccess. + */ + public static boolean isNonPublicProxyClass(Class cls) { + String name = cls.getName(); + int i = name.lastIndexOf('.'); + String pkg = (i != -1) ? name.substring(0, i) : ""; + return Proxy.isProxyClass(cls) && !pkg.equals(PROXY_PACKAGE); + } }