8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
authormchung
Wed, 17 Apr 2013 12:04:15 -0700
changeset 16923 50bfa0defec2
parent 16922 6c918c972850
child 16925 e42763b1ea55
child 16927 e72c5f9cc691
8004260: dynamic proxy class should have the same Java language access as the proxy interfaces Reviewed-by: alanb, jrose, jdn
jdk/src/share/classes/java/lang/reflect/Proxy.java
jdk/src/share/classes/java/lang/reflect/ReflectPermission.java
jdk/src/share/classes/sun/misc/ProxyGenerator.java
jdk/src/share/classes/sun/reflect/annotation/AnnotationParser.java
jdk/src/share/classes/sun/rmi/server/Util.java
jdk/src/share/classes/sun/tracing/ProviderSkeleton.java
jdk/test/java/lang/reflect/Proxy/nonPublicProxy/NonPublicProxyClass.java
jdk/test/java/lang/reflect/Proxy/nonPublicProxy/SimpleProxy.java
jdk/test/java/lang/reflect/Proxy/nonPublicProxy/p/Bar.java
jdk/test/java/lang/reflect/Proxy/nonPublicProxy/p/Foo.java
jdk/test/java/rmi/server/RMIClassLoader/loadProxyClasses/security.policy
--- a/jdk/src/share/classes/java/lang/reflect/Proxy.java	Wed Apr 17 11:39:52 2013 -0700
+++ b/jdk/src/share/classes/java/lang/reflect/Proxy.java	Wed Apr 17 12:04:15 2013 -0700
@@ -28,7 +28,6 @@
 import java.lang.ref.Reference;
 import java.lang.ref.WeakReference;
 import java.security.AccessController;
-import java.security.Permission;
 import java.security.PrivilegedAction;
 import java.util.Arrays;
 import java.util.Collections;
@@ -53,16 +52,14 @@
  * <p>To create a proxy for some interface {@code Foo}:
  * <pre>
  *     InvocationHandler handler = new MyInvocationHandler(...);
- *     Class proxyClass = Proxy.getProxyClass(
- *         Foo.class.getClassLoader(), new Class[] { Foo.class });
- *     Foo f = (Foo) proxyClass.
- *         getConstructor(new Class[] { InvocationHandler.class }).
- *         newInstance(new Object[] { handler });
+ *     Class&lt;?&gt; proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(), Foo.class);
+ *     Foo f = (Foo) proxyClass.getConstructor(InvocationHandler.class).
+ *                     newInstance(handler);
  * </pre>
  * or more simply:
  * <pre>
  *     Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
- *                                          new Class[] { Foo.class },
+ *                                          new Class&lt;?&gt;[] { Foo.class },
  *                                          handler);
  * </pre>
  *
@@ -91,7 +88,11 @@
  * <p>A proxy class has the following properties:
  *
  * <ul>
- * <li>Proxy classes are public, final, and not abstract.
+ * <li>Proxy classes are <em>public, final, and not abstract</em> if
+ * all proxy interfaces are public.</li>
+ *
+ * <li>Proxy classes are <em>non-public, final, and not abstract</em> if
+ * any of the proxy interfaces is non-public.</li>
  *
  * <li>The unqualified name of a proxy class is unspecified.  The space
  * of class names that begin with the string {@code "$Proxy"}
@@ -273,76 +274,17 @@
      * @param   h the invocation handler for this proxy instance
      */
     protected Proxy(InvocationHandler h) {
-        doNewInstanceCheck();
         this.h = h;
     }
 
-    private static class ProxyAccessHelper {
-        // The permission is implementation specific.
-        static final Permission PROXY_PERMISSION =
-            new ReflectPermission("proxyConstructorNewInstance");
-        // These system properties are defined to provide a short-term
-        // workaround if customers need to disable the new security checks.
-        static final boolean allowNewInstance;
-        static final boolean allowNullLoader;
-        static {
-            allowNewInstance = getBooleanProperty("sun.reflect.proxy.allowsNewInstance");
-            allowNullLoader = getBooleanProperty("sun.reflect.proxy.allowsNullLoader");
-        }
-
-        private static boolean getBooleanProperty(final String key) {
-            String s = AccessController.doPrivileged(new PrivilegedAction<String>() {
-                public String run() {
-                    return System.getProperty(key);
-                }
-            });
-            return Boolean.valueOf(s);
-        }
-
-        static boolean needsNewInstanceCheck(Class<?> proxyClass) {
-            if (!Proxy.isProxyClass(proxyClass) || allowNewInstance) {
-                return false;
-            }
-
-            if (proxyClass.getName().startsWith(ReflectUtil.PROXY_PACKAGE + ".")) {
-                // all proxy interfaces are public
-                return false;
-            }
-            for (Class<?> intf : proxyClass.getInterfaces()) {
-                if (!Modifier.isPublic(intf.getModifiers())) {
-                    return true;
-                }
-            }
-            return false;
-        }
-    }
-
-    /*
-     * Access check on a proxy class that implements any non-public interface.
-     *
-     * @throws  SecurityException if a security manager exists, and
-     *          the caller does not have the permission.
-     */
-    private void doNewInstanceCheck() {
-        SecurityManager sm = System.getSecurityManager();
-        Class<?> proxyClass = this.getClass();
-        if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(proxyClass)) {
-            try {
-                sm.checkPermission(ProxyAccessHelper.PROXY_PERMISSION);
-            } catch (SecurityException e) {
-                throw new SecurityException("Not allowed to construct a Proxy "
-                        + "instance that implements a non-public interface", e);
-            }
-        }
-    }
-
     /**
      * Returns the {@code java.lang.Class} object for a proxy class
      * given a class loader and an array of interfaces.  The proxy class
      * will be defined by the specified class loader and will implement
-     * all of the supplied interfaces.  If a proxy class for the same
-     * permutation of interfaces has already been defined by the class
-     * loader, then the existing proxy class will be returned; otherwise,
+     * all of the supplied interfaces.  If any of the given interfaces
+     * is non-public, the proxy class will be non-public. If a proxy class
+     * for the same permutation of interfaces has already been defined by the
+     * class loader, then the existing proxy class will be returned; otherwise,
      * a proxy class for those interfaces will be generated dynamically
      * and defined by the class loader.
      *
@@ -407,6 +349,22 @@
      * @throws  IllegalArgumentException if any of the restrictions on the
      *          parameters that may be passed to {@code getProxyClass}
      *          are violated
+     * @throws  SecurityException if a security manager, <em>s</em>, is present
+     *          and any of the following conditions is met:
+     *          <ul>
+     *             <li> the given {@code loader} is {@code null} and
+     *             the caller's class loader is not {@code null} and the
+     *             invocation of {@link SecurityManager#checkPermission
+     *             s.checkPermission} with
+     *             {@code RuntimePermission("getClassLoader")} permission
+     *             denies access.</li>
+     *             <li> the caller's class loader is not the same as or an
+     *             ancestor of the class loader for the current class and
+     *             invocation of {@link SecurityManager#checkPackageAccess
+     *             s.checkPackageAccess()} denies access to any one of the
+     *             given proxy interfaces.</li>
+     *          </ul>
+
      * @throws  NullPointerException if the {@code interfaces} array
      *          argument or any of its elements are {@code null}
      */
@@ -449,9 +407,7 @@
         if (sm != null) {
             ClassLoader ccl = caller.getClassLoader();
             if (VM.isSystemDomainLoader(loader) && !VM.isSystemDomainLoader(ccl)) {
-                if (!ProxyAccessHelper.allowNullLoader) {
-                    sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
-                }
+                sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
             }
             ReflectUtil.checkProxyPackageAccess(ccl, interfaces);
         }
@@ -593,6 +549,7 @@
 
         try {
             String proxyPkg = null;     // package to define proxy class in
+            int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
 
             /*
              * Record the package of a non-public proxy interface so that the
@@ -602,6 +559,7 @@
             for (int i = 0; i < interfaces.length; i++) {
                 int flags = interfaces[i].getModifiers();
                 if (!Modifier.isPublic(flags)) {
+                    accessFlags = Modifier.FINAL;
                     String name = interfaces[i].getName();
                     int n = name.lastIndexOf('.');
                     String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
@@ -637,7 +595,7 @@
                  * Generate the specified proxy class.
                  */
                 byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
-                    proxyName, interfaces);
+                    proxyName, interfaces, accessFlags);
                 try {
                     proxyClass = defineClass0(loader, proxyName,
                         proxyClassFile, 0, proxyClassFile.length);
@@ -678,12 +636,7 @@
     /**
      * Returns an instance of a proxy class for the specified interfaces
      * that dispatches method invocations to the specified invocation
-     * handler.  This method is equivalent to:
-     * <pre>
-     *     Proxy.getProxyClass(loader, interfaces).
-     *         getConstructor(new Class[] { InvocationHandler.class }).
-     *         newInstance(new Object[] { handler });
-     * </pre>
+     * handler.
      *
      * <p>{@code Proxy.newProxyInstance} throws
      * {@code IllegalArgumentException} for the same reasons that
@@ -699,6 +652,27 @@
      * @throws  IllegalArgumentException if any of the restrictions on the
      *          parameters that may be passed to {@code getProxyClass}
      *          are violated
+     * @throws  SecurityException if a security manager, <em>s</em>, is present
+     *          and any of the following conditions is met:
+     *          <ul>
+     *          <li> the given {@code loader} is {@code null} and
+     *               the caller's class loader is not {@code null} and the
+     *               invocation of {@link SecurityManager#checkPermission
+     *               s.checkPermission} with
+     *               {@code RuntimePermission("getClassLoader")} permission
+     *               denies access;</li>
+     *          <li> the caller's class loader is not the same as or an
+     *               ancestor of the class loader for the current class and
+     *               invocation of {@link SecurityManager#checkPackageAccess
+     *               s.checkPackageAccess()} denies access to any one of the
+     *               given proxy interfaces.</li>
+     *          <li> any of the given proxy interfaces is non-public and the
+     *               caller class is not in the same {@linkplain Package runtime package}
+     *               as the non-public interface and the invocation of
+     *               {@link SecurityManager#checkPermission s.checkPermission} with
+     *               {@code ReflectPermission("newProxyInPackage.{package name}")}
+     *               permission denies access.</li>
+     *          </ul>
      * @throws  NullPointerException if the {@code interfaces} array
      *          argument or any of its elements are {@code null}, or
      *          if the invocation handler, {@code h}, is
@@ -728,24 +702,61 @@
          * Invoke its constructor with the designated invocation handler.
          */
         try {
+            if (sm != null) {
+                checkNewProxyPermission(Reflection.getCallerClass(), cl);
+            }
+
             final Constructor<?> cons = cl.getConstructor(constructorParams);
             final InvocationHandler ih = h;
-            if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) {
-                // create proxy instance with doPrivilege as the proxy class may
-                // implement non-public interfaces that requires a special permission
-                return AccessController.doPrivileged(new PrivilegedAction<Object>() {
-                    public Object run() {
-                        return newInstance(cons, ih);
+            if (!Modifier.isPublic(cl.getModifiers())) {
+                AccessController.doPrivileged(new PrivilegedAction<Void>() {
+                    public Void run() {
+                        cons.setAccessible(true);
+                        return null;
                     }
                 });
+            }
+            return cons.newInstance(new Object[]{h});
+        } catch (IllegalAccessException|InstantiationException e) {
+            throw new InternalError(e.toString(), e);
+        } catch (InvocationTargetException e) {
+            Throwable t = e.getCause();
+            if (t instanceof RuntimeException) {
+                throw (RuntimeException) t;
             } else {
-                return newInstance(cons, ih);
+                throw new InternalError(t.toString(), t);
             }
         } catch (NoSuchMethodException e) {
             throw new InternalError(e.toString(), e);
         }
     }
 
+    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();
+
+            // 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);
+
+            if (pcl != ccl || !pkg.equals(callerPkg)) {
+                sm.checkPermission(new ReflectPermission("newProxyInPackage." + pkg));
+            }
+        }
+    }
+
     private static Object newInstance(Constructor<?> cons, InvocationHandler h) {
         try {
             return cons.newInstance(new Object[] {h} );
--- a/jdk/src/share/classes/java/lang/reflect/ReflectPermission.java	Wed Apr 17 11:39:52 2013 -0700
+++ b/jdk/src/share/classes/java/lang/reflect/ReflectPermission.java	Wed Apr 17 12:04:15 2013 -0700
@@ -26,12 +26,7 @@
 package java.lang.reflect;
 
 /**
- * The Permission class for reflective operations.  A
- * ReflectPermission is a <em>named permission</em> and has no
- * actions.  The only name currently defined is {@code suppressAccessChecks},
- * which allows suppressing the standard Java language access checks
- * -- for public, default (package) access, protected, and private
- * members -- performed by reflected objects at their point of use.
+ * The Permission class for reflective operations.
  * <P>
  * The following table
  * provides a summary description of what the permission allows,
@@ -47,11 +42,21 @@
  *
  * <tr>
  *   <td>suppressAccessChecks</td>
- *   <td>ability to access
- * fields and invoke methods in a class. Note that this includes
- * not only public, but protected and private fields and methods as well.</td>
+ *   <td>ability to suppress the standard Java language access checks
+ *       on fields and methods in a class; allow access not only public members
+ *       but also allow access to default (package) access, protected,
+ *       and private members.</td>
  *   <td>This is dangerous in that information (possibly confidential) and
- * methods normally unavailable would be accessible to malicious code.</td>
+ *       methods normally unavailable would be accessible to malicious code.</td>
+ * </tr>
+ * <tr>
+ *   <td>newProxyInPackage.{package name}</td>
+ *   <td>ability to create a proxy instance in the specified package of which
+ *       the non-public interface that the proxy class implements.</td>
+ *   <td>This gives code access to classes in packages to which it normally
+ *       does not have access and the dynamic proxy class is in the system
+ *       protection domain. Malicious code may use these classes to
+ *       help in its attempt to compromise security in the system.</td>
  * </tr>
  *
  * </table>
@@ -63,6 +68,7 @@
  * @see Field#set
  * @see Method#invoke
  * @see Constructor#newInstance
+ * @see Proxy#newProxyInstance
  *
  * @since 1.2
  */
--- a/jdk/src/share/classes/sun/misc/ProxyGenerator.java	Wed Apr 17 11:39:52 2013 -0700
+++ b/jdk/src/share/classes/sun/misc/ProxyGenerator.java	Wed Apr 17 12:04:15 2013 -0700
@@ -27,11 +27,14 @@
 
 import java.io.ByteArrayOutputStream;
 import java.io.DataOutputStream;
-import java.io.FileOutputStream;
+import java.io.File;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.lang.reflect.Array;
 import java.lang.reflect.Method;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.LinkedList;
@@ -314,12 +317,25 @@
                 "sun.misc.ProxyGenerator.saveGeneratedFiles")).booleanValue();
 
     /**
-     * Generate a proxy class given a name and a list of proxy interfaces.
+     * Generate a public proxy class given a name and a list of proxy interfaces.
      */
     public static byte[] generateProxyClass(final String name,
-                                            Class[] interfaces)
+                                            Class<?>[] interfaces) {
+        return generateProxyClass(name, interfaces, (ACC_PUBLIC | ACC_FINAL | ACC_SUPER));
+    }
+
+    /**
+     * Generate a proxy class given a name and a list of proxy interfaces.
+     *
+     * @param name        the class name of the proxy class
+     * @param interfaces  proxy interfaces
+     * @param accessFlags access flags of the proxy class
+    */
+    public static byte[] generateProxyClass(final String name,
+                                            Class<?>[] interfaces,
+                                            int accessFlags)
     {
-        ProxyGenerator gen = new ProxyGenerator(name, interfaces);
+        ProxyGenerator gen = new ProxyGenerator(name, interfaces, accessFlags);
         final byte[] classFile = gen.generateClassFile();
 
         if (saveGeneratedFiles) {
@@ -327,10 +343,16 @@
             new java.security.PrivilegedAction<Void>() {
                 public Void run() {
                     try {
-                        FileOutputStream file =
-                            new FileOutputStream(dotToSlash(name) + ".class");
-                        file.write(classFile);
-                        file.close();
+                        int i = name.lastIndexOf('.');
+                        Path path;
+                        if (i > 0) {
+                            Path dir = Paths.get(name.substring(0, i).replace('.', File.separatorChar));
+                            Files.createDirectories(dir);
+                            path = dir.resolve(name.substring(i+1, name.length()) + ".class");
+                        } else {
+                            path = Paths.get(name + ".class");
+                        }
+                        Files.write(path, classFile);
                         return null;
                     } catch (IOException e) {
                         throw new InternalError(
@@ -364,21 +386,23 @@
     /** proxy interfaces */
     private Class[] interfaces;
 
+    /** proxy class access flags */
+    private int accessFlags;
+
     /** constant pool of class being generated */
     private ConstantPool cp = new ConstantPool();
 
     /** FieldInfo struct for each field of generated class */
-    private List<FieldInfo> fields = new ArrayList<FieldInfo>();
+    private List<FieldInfo> fields = new ArrayList<>();
 
     /** MethodInfo struct for each method of generated class */
-    private List<MethodInfo> methods = new ArrayList<MethodInfo>();
+    private List<MethodInfo> methods = new ArrayList<>();
 
     /**
      * maps method signature string to list of ProxyMethod objects for
      * proxy methods with that signature
      */
-    private Map<String, List<ProxyMethod>> proxyMethods =
-        new HashMap<String,List<ProxyMethod>>();
+    private Map<String, List<ProxyMethod>> proxyMethods = new HashMap<>();
 
     /** count of ProxyMethod objects added to proxyMethods */
     private int proxyMethodCount = 0;
@@ -390,9 +414,10 @@
      * A ProxyGenerator object contains the state for the ongoing
      * generation of a particular proxy class.
      */
-    private ProxyGenerator(String className, Class[] interfaces) {
+    private ProxyGenerator(String className, Class<?>[] interfaces, int accessFlags) {
         this.className = className;
         this.interfaces = interfaces;
+        this.accessFlags = accessFlags;
     }
 
     /**
@@ -422,10 +447,9 @@
          * earlier interfaces precedence over later ones with duplicate
          * methods.
          */
-        for (int i = 0; i < interfaces.length; i++) {
-            Method[] methods = interfaces[i].getMethods();
-            for (int j = 0; j < methods.length; j++) {
-                addProxyMethod(methods[j], interfaces[i]);
+        for (Class<?> intf : interfaces) {
+            for (Method m : intf.getMethods()) {
+                addProxyMethod(m, intf);
             }
         }
 
@@ -480,8 +504,8 @@
          */
         cp.getClass(dotToSlash(className));
         cp.getClass(superclassName);
-        for (int i = 0; i < interfaces.length; i++) {
-            cp.getClass(dotToSlash(interfaces[i].getName()));
+        for (Class<?> intf: interfaces) {
+            cp.getClass(dotToSlash(intf.getName()));
         }
 
         /*
@@ -508,7 +532,7 @@
             cp.write(dout);             // (write constant pool)
 
                                         // u2 access_flags;
-            dout.writeShort(ACC_PUBLIC | ACC_FINAL | ACC_SUPER);
+            dout.writeShort(accessFlags);
                                         // u2 this_class;
             dout.writeShort(cp.getClass(dotToSlash(className)));
                                         // u2 super_class;
@@ -517,9 +541,9 @@
                                         // u2 interfaces_count;
             dout.writeShort(interfaces.length);
                                         // u2 interfaces[interfaces_count];
-            for (int i = 0; i < interfaces.length; i++) {
+            for (Class<?> intf : interfaces) {
                 dout.writeShort(cp.getClass(
-                    dotToSlash(interfaces[i].getName())));
+                    dotToSlash(intf.getName())));
             }
 
                                         // u2 fields_count;
@@ -576,7 +600,7 @@
                      * compatibly with the throws clauses of both
                      * overridden methods.
                      */
-                    List<Class<?>> legalExceptions = new ArrayList<Class<?>>();
+                    List<Class<?>> legalExceptions = new ArrayList<>();
                     collectCompatibleTypes(
                         exceptionTypes, pm.exceptionTypes, legalExceptions);
                     collectCompatibleTypes(
@@ -588,7 +612,7 @@
                 }
             }
         } else {
-            sigmethods = new ArrayList<ProxyMethod>(3);
+            sigmethods = new ArrayList<>(3);
             proxyMethods.put(sig, sigmethods);
         }
         sigmethods.add(new ProxyMethod(name, parameterTypes, returnType,
@@ -618,7 +642,7 @@
          * List of return types that are not yet known to be
          * assignable from ("covered" by) any of the others.
          */
-        LinkedList<Class<?>> uncoveredReturnTypes = new LinkedList<Class<?>>();
+        LinkedList<Class<?>> uncoveredReturnTypes = new LinkedList<>();
 
     nextNewReturnType:
         for (ProxyMethod pm : methods) {
@@ -833,8 +857,8 @@
                                         // u2 number_of_exceptions;
             out.writeShort(declaredExceptions.length);
                         // u2 exception_index_table[number_of_exceptions];
-            for (int i = 0; i < declaredExceptions.length; i++) {
-                out.writeShort(declaredExceptions[i]);
+            for (short value : declaredExceptions) {
+                out.writeShort(value);
             }
         }
 
@@ -1525,11 +1549,11 @@
                                                Class<?>[] with,
                                                List<Class<?>> list)
     {
-        for (int i = 0; i < from.length; i++) {
-            if (!list.contains(from[i])) {
-                for (int j = 0; j < with.length; j++) {
-                    if (with[j].isAssignableFrom(from[i])) {
-                        list.add(from[i]);
+        for (Class<?> fc: from) {
+            if (!list.contains(fc)) {
+                for (Class<?> wc: with) {
+                    if (wc.isAssignableFrom(fc)) {
+                        list.add(fc);
                         break;
                     }
                 }
@@ -1559,15 +1583,14 @@
      * need to be caught.
      */
     private static List<Class<?>> computeUniqueCatchList(Class<?>[] exceptions) {
-        List<Class<?>> uniqueList = new ArrayList<Class<?>>();
+        List<Class<?>> uniqueList = new ArrayList<>();
                                                 // unique exceptions to catch
 
         uniqueList.add(Error.class);            // always catch/rethrow these
         uniqueList.add(RuntimeException.class);
 
     nextException:
-        for (int i = 0; i < exceptions.length; i++) {
-            Class<?> ex = exceptions[i];
+        for (Class<?> ex: exceptions) {
             if (ex.isAssignableFrom(Throwable.class)) {
                 /*
                  * If Throwable is declared to be thrown by the proxy method,
--- a/jdk/src/share/classes/sun/reflect/annotation/AnnotationParser.java	Wed Apr 17 11:39:52 2013 -0700
+++ b/jdk/src/share/classes/sun/reflect/annotation/AnnotationParser.java	Wed Apr 17 12:04:15 2013 -0700
@@ -30,6 +30,8 @@
 import java.nio.ByteBuffer;
 import java.nio.BufferUnderflowException;
 import java.lang.reflect.*;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import sun.reflect.ConstantPool;
 
 import sun.reflect.generics.parser.SignatureParser;
@@ -253,12 +255,15 @@
      * Returns an annotation of the given type backed by the given
      * member -> value map.
      */
-    public static Annotation annotationForMap(
-        Class<? extends Annotation> type, Map<String, Object> memberValues)
+    public static Annotation annotationForMap(final Class<? extends Annotation> type,
+                                              final Map<String, Object> memberValues)
     {
-        return (Annotation) Proxy.newProxyInstance(
-            type.getClassLoader(), new Class<?>[] { type },
-            new AnnotationInvocationHandler(type, memberValues));
+        return AccessController.doPrivileged(new PrivilegedAction<Annotation>() {
+            public Annotation run() {
+                return (Annotation) Proxy.newProxyInstance(
+                    type.getClassLoader(), new Class<?>[] { type },
+                    new AnnotationInvocationHandler(type, memberValues));
+            }});
     }
 
     /**
--- a/jdk/src/share/classes/sun/rmi/server/Util.java	Wed Apr 17 11:39:52 2013 -0700
+++ b/jdk/src/share/classes/sun/rmi/server/Util.java	Wed Apr 17 12:04:15 2013 -0700
@@ -48,6 +48,7 @@
 import java.security.MessageDigest;
 import java.security.DigestOutputStream;
 import java.security.NoSuchAlgorithmException;
+import java.security.PrivilegedAction;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Map;
@@ -140,17 +141,20 @@
             return createStub(remoteClass, clientRef);
         }
 
-        ClassLoader loader = implClass.getClassLoader();
-        Class[] interfaces = getRemoteInterfaces(implClass);
-        InvocationHandler handler =
+        final ClassLoader loader = implClass.getClassLoader();
+        final Class[] interfaces = getRemoteInterfaces(implClass);
+        final InvocationHandler handler =
             new RemoteObjectInvocationHandler(clientRef);
 
         /* REMIND: private remote interfaces? */
 
         try {
-            return (Remote) Proxy.newProxyInstance(loader,
-                                                   interfaces,
-                                                   handler);
+            return AccessController.doPrivileged(new PrivilegedAction<Remote>() {
+                public Remote run() {
+                    return (Remote) Proxy.newProxyInstance(loader,
+                                                           interfaces,
+                                                           handler);
+                }});
         } catch (IllegalArgumentException e) {
             throw new StubNotFoundException("unable to create proxy", e);
         }
--- a/jdk/src/share/classes/sun/tracing/ProviderSkeleton.java	Wed Apr 17 11:39:52 2013 -0700
+++ b/jdk/src/share/classes/sun/tracing/ProviderSkeleton.java	Wed Apr 17 12:04:15 2013 -0700
@@ -130,8 +130,12 @@
      */
     @SuppressWarnings("unchecked")
     public <T extends Provider> T newProxyInstance() {
-        return (T)Proxy.newProxyInstance(providerType.getClassLoader(),
-               new Class<?>[] { providerType }, this);
+        final InvocationHandler ih = this;
+        return AccessController.doPrivileged(new PrivilegedAction<T>() {
+            public T run() {
+               return (T)Proxy.newProxyInstance(providerType.getClassLoader(),
+                   new Class<?>[] { providerType }, ih);
+            }});
     }
 
     /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/reflect/Proxy/nonPublicProxy/NonPublicProxyClass.java	Wed Apr 17 12:04:15 2013 -0700
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Proxy;
+import java.lang.reflect.ReflectPermission;
+import java.security.AccessControlException;
+import java.security.CodeSource;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.Permissions;
+import java.security.Policy;
+import java.security.ProtectionDomain;
+import java.security.SecurityPermission;
+import java.util.*;
+
+/*
+ * @test
+ * @bug 8004260
+ * @summary Test proxy classes that implement non-public interface
+ *
+ * @build p.Foo
+ * @run main/othervm NonPublicProxyClass grant
+ * @run main/othervm NonPublicProxyClass deny
+ * @run main/othervm NonPublicProxyClass
+ */
+public class NonPublicProxyClass {
+    public interface PublicInterface {
+        void foo();
+    }
+    interface NonPublicInterface {
+        void bar();
+    }
+
+    public static void main(String[] args) throws Exception {
+        ClassLoader loader = ClassLoader.getSystemClassLoader();
+        Class<?> zipConstantsClass = Class.forName("java.util.zip.ZipConstants", false, null);
+        Class<?> fooClass = Class.forName("p.Foo");
+
+        NonPublicProxyClass test1 =
+            new NonPublicProxyClass(loader, PublicInterface.class, NonPublicInterface.class);
+        NonPublicProxyClass test2 =
+            new NonPublicProxyClass(loader, fooClass, PublicInterface.class);
+        NonPublicProxyClass test3 =
+            new NonPublicProxyClass(null, zipConstantsClass);
+
+        if (args.length == 1) {
+            switch (args[0]) {
+                case "grant": Policy.setPolicy(new NewInstancePolicy(true));
+                              break;
+                case "deny" : Policy.setPolicy(new NewInstancePolicy(false));
+                              break;
+                default: throw new IllegalArgumentException(args[0]);
+            }
+            System.setSecurityManager(new SecurityManager());
+        }
+
+        test1.run();
+        test2.run();
+        test3.run();
+        System.out.format("Test passed: security %s%n",
+            (args.length == 0 ? "manager not installed" : Policy.getPolicy()));
+    }
+
+    private final ClassLoader loader;
+    private final Class<?>[] interfaces;
+    private final InvocationHandler handler = newInvocationHandler();
+    private Class<?> proxyClass;
+    public NonPublicProxyClass(ClassLoader loader, Class<?> ... intfs) {
+        this.loader = loader;
+        this.interfaces = intfs;
+    }
+
+    public void run() throws Exception {
+        boolean hasAccess = loader != null || hasAccess();
+        try {
+            proxyClass = Proxy.getProxyClass(loader, interfaces);
+            if (!hasAccess) {
+                throw new RuntimeException("should have no permission to create proxy class");
+            }
+        } catch (AccessControlException e) {
+            if (hasAccess) {
+                throw e;
+            }
+            if (e.getPermission().getClass() != RuntimePermission.class ||
+                    !e.getPermission().getName().equals("getClassLoader")) {
+                throw e;
+            }
+            return;
+        }
+
+        if (Modifier.isPublic(proxyClass.getModifiers())) {
+            throw new RuntimeException(proxyClass + " must be non-public");
+        }
+        newProxyInstance();
+        newInstanceFromConstructor(proxyClass);
+    }
+
+    private boolean hasAccess() {
+        if (System.getSecurityManager() == null) {
+            return true;
+        }
+        NewInstancePolicy policy = NewInstancePolicy.class.cast(Policy.getPolicy());
+        return policy.grant;
+    }
+
+    private final static String NEW_PROXY_IN_PKG = "newProxyInPackage.";
+    private void newProxyInstance() {
+        // expect newProxyInstance to succeed if it's in the same runtime package
+        int i = proxyClass.getName().lastIndexOf('.');
+        String pkg = (i != -1) ? proxyClass.getName().substring(0, i) : "";
+        boolean hasAccess = pkg.isEmpty() || hasAccess();
+        try {
+            Proxy.newProxyInstance(loader, interfaces, handler);
+            if (!hasAccess) {
+                throw new RuntimeException("ERROR: Proxy.newProxyInstance should fail " + proxyClass);
+            }
+        } catch (AccessControlException e) {
+            if (hasAccess) {
+                throw e;
+            }
+            if (e.getPermission().getClass() != ReflectPermission.class ||
+                    !e.getPermission().getName().equals(NEW_PROXY_IN_PKG + pkg)) {
+                throw e;
+            }
+        }
+    }
+
+    private void newInstanceFromConstructor(Class<?> proxyClass)
+        throws Exception
+    {
+        // expect newInstance to succeed if it's in the same runtime package
+        boolean isSamePackage = proxyClass.getName().lastIndexOf('.') == -1;
+        try {
+            Constructor cons = proxyClass.getConstructor(InvocationHandler.class);
+            cons.newInstance(newInvocationHandler());
+            if (!isSamePackage) {
+                throw new RuntimeException("ERROR: Constructor.newInstance should not succeed");
+            }
+        }  catch (IllegalAccessException e) {
+            if (isSamePackage) {
+                throw e;
+            }
+        }
+    }
+
+    private static InvocationHandler newInvocationHandler() {
+        return new InvocationHandler() {
+            public Object invoke(Object proxy, Method method, Object[] args)
+                    throws Throwable {
+                Class<?>[] intfs = proxy.getClass().getInterfaces();
+                System.out.println("Proxy for " + Arrays.toString(intfs)
+                        + " " + method.getName() + " is being invoked");
+                return null;
+            }
+        };
+    }
+
+    static class NewInstancePolicy extends Policy {
+        final PermissionCollection permissions = new Permissions();
+        final boolean grant;
+        NewInstancePolicy(boolean grant) {
+            this.grant = grant;
+            permissions.add(new SecurityPermission("getPolicy"));
+            if (grant) {
+                permissions.add(new RuntimePermission("getClassLoader"));
+                permissions.add(new ReflectPermission(NEW_PROXY_IN_PKG + "p"));
+                permissions.add(new ReflectPermission(NEW_PROXY_IN_PKG + "java.util.zip"));
+            }
+        }
+        public PermissionCollection getPermissions(ProtectionDomain domain) {
+            return permissions;
+        }
+
+        public PermissionCollection getPermissions(CodeSource codesource) {
+            return permissions;
+        }
+
+        public boolean implies(ProtectionDomain domain, Permission perm) {
+            return permissions.implies(perm);
+        }
+
+        public String toString() {
+            StringBuilder sb = new StringBuilder("policy: ");
+            Enumeration<Permission> perms = permissions.elements();
+            while (perms.hasMoreElements()) {
+                sb.append("\n").append(perms.nextElement().toString());
+            }
+            return sb.toString();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/reflect/Proxy/nonPublicProxy/SimpleProxy.java	Wed Apr 17 12:04:15 2013 -0700
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.lang.reflect.*;
+import java.security.*;
+import java.util.Arrays;
+
+/*
+ * @test
+ * @bug 8004260
+ * @summary Test making a proxy instance that implements a non-public
+ *          interface with and without security manager installed
+ * @build p.Foo p.Bar
+ * @run main SimpleProxy
+ */
+public class SimpleProxy {
+    public static void main(String[] args) throws Exception {
+        ClassLoader loader = SimpleProxy.class.getClassLoader();
+        Class<?> fooClass = Class.forName("p.Foo");
+        Class<?> barClass = Class.forName("p.Bar");
+
+        makeProxy(loader, fooClass);
+
+        System.setSecurityManager(new SecurityManager());
+        try {
+            makeProxy(loader, barClass);
+            throw new RuntimeException("should fail to new proxy instance of a non-public interface");
+        } catch (AccessControlException e) {
+            if (e.getPermission().getClass() != ReflectPermission.class ||
+                    !e.getPermission().getName().equals("newProxyInPackage.p")) {
+                throw e;
+            }
+        }
+    }
+
+    private static void makeProxy(ClassLoader loader, Class<?> cls) {
+        Class<?>[] intfs = new Class<?>[] { cls };
+        Proxy.newProxyInstance(loader, intfs, new InvocationHandler() {
+            public Object invoke(Object proxy, Method method, Object[] args)
+                    throws Throwable {
+                Class<?>[] intfs = proxy.getClass().getInterfaces();
+                System.out.println("Proxy for " + Arrays.toString(intfs)
+                        + " " + method.getName() + " is being invoked");
+                return null;
+            }
+        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/reflect/Proxy/nonPublicProxy/p/Bar.java	Wed Apr 17 12:04:15 2013 -0700
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package p;
+interface Bar {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/reflect/Proxy/nonPublicProxy/p/Foo.java	Wed Apr 17 12:04:15 2013 -0700
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package p;
+interface Foo {
+}
--- a/jdk/test/java/rmi/server/RMIClassLoader/loadProxyClasses/security.policy	Wed Apr 17 11:39:52 2013 -0700
+++ b/jdk/test/java/rmi/server/RMIClassLoader/loadProxyClasses/security.policy	Wed Apr 17 12:04:15 2013 -0700
@@ -16,6 +16,9 @@
     permission java.lang.RuntimePermission "getClassLoader";
     permission java.lang.RuntimePermission "setContextClassLoader";
 
+    permission java.lang.reflect.ReflectPermission "newProxyInPackage.";
+    permission java.lang.reflect.ReflectPermission "newProxyInPackage.java.util.zip";
+
     // used by TestLibrary to determine test environment
     permission java.util.PropertyPermission "test.classes", "read";
     permission java.util.PropertyPermission "test.src", "read";