# HG changeset patch # User mchung # Date 1366236299 25200 # Node ID a1031f4526b2f698dc97cd23228efc914d7f2bff # Parent 176cb77883eb0563fda216b0d7e718e84d32db5f 8011557: Improve reflection utility classes Reviewed-by: ahgross, alanb diff -r 176cb77883eb -r a1031f4526b2 jdk/src/share/classes/java/lang/Class.java --- a/jdk/src/share/classes/java/lang/Class.java Mon Apr 22 11:29:43 2013 +0100 +++ b/jdk/src/share/classes/java/lang/Class.java Wed Apr 17 15:04:59 2013 -0700 @@ -2338,7 +2338,7 @@ 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 -r 176cb77883eb -r a1031f4526b2 jdk/src/share/classes/java/lang/reflect/Proxy.java --- a/jdk/src/share/classes/java/lang/reflect/Proxy.java Mon Apr 22 11:29:43 2013 +0100 +++ b/jdk/src/share/classes/java/lang/reflect/Proxy.java Wed Apr 17 15:04:59 2013 -0700 @@ -734,25 +734,21 @@ 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; - } - - ClassLoader ccl = caller.getClassLoader(); - ClassLoader pcl = proxyClass.getClassLoader(); + if (ReflectUtil.isNonPublicProxyClass(proxyClass)) { + 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 = pcn.lastIndexOf('.'); - String pkg = (n == -1) ? "" : pcn.substring(0, n); + // 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); - 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 -r 176cb77883eb -r a1031f4526b2 jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java --- a/jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java Mon Apr 22 11:29:43 2013 +0100 +++ b/jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java Wed Apr 17 15:04:59 2013 -0700 @@ -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 @@ 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) { @@ -180,13 +196,30 @@ } /** + * 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 @@ // 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); + } }