# HG changeset patch
# User mchung
# Date 1366225455 25200
# Node ID 50bfa0defec213ce53a4a980a35463af1f30b0f9
# Parent 6c918c9728506b24a26ba6b4d38880cb6d0ce0de
8004260: dynamic proxy class should have the same Java language access as the proxy interfaces
Reviewed-by: alanb, jrose, jdn
diff -r 6c918c972850 -r 50bfa0defec2 jdk/src/share/classes/java/lang/reflect/Proxy.java
--- 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 @@
*
To create a proxy for some interface {@code Foo}:
*
* 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<?> proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(), Foo.class);
+ * Foo f = (Foo) proxyClass.getConstructor(InvocationHandler.class).
+ * newInstance(handler);
*
* or more simply:
*
* Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
- * new Class[] { Foo.class },
+ * new Class<?>[] { Foo.class },
* handler);
*
*
@@ -91,7 +88,11 @@
* A proxy class has the following properties:
*
*
- * Proxy classes are public, final, and not abstract.
+ * Proxy classes are public, final, and not abstract if
+ * all proxy interfaces are public.
+ *
+ * Proxy classes are non-public, final, and not abstract if
+ * any of the proxy interfaces is non-public.
*
* 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() {
- 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, s , is present
+ * and any of the following conditions is met:
+ *
+ * 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.
+ * 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.
+ *
+
* @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:
- *
- * Proxy.getProxyClass(loader, interfaces).
- * getConstructor(new Class[] { InvocationHandler.class }).
- * newInstance(new Object[] { handler });
- *
+ * handler.
*
* {@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, s , is present
+ * and any of the following conditions is met:
+ *
+ * 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;
+ * 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.
+ * 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.
+ *
* @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() {
- public Object run() {
- return newInstance(cons, ih);
+ if (!Modifier.isPublic(cl.getModifiers())) {
+ AccessController.doPrivileged(new PrivilegedAction() {
+ 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} );
diff -r 6c918c972850 -r 50bfa0defec2 jdk/src/share/classes/java/lang/reflect/ReflectPermission.java
--- 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 named permission 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.
*
* The following table
* provides a summary description of what the permission allows,
@@ -47,11 +42,21 @@
*
*
* suppressAccessChecks
- * 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.
+ * 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.
* This is dangerous in that information (possibly confidential) and
- * methods normally unavailable would be accessible to malicious code.
+ * methods normally unavailable would be accessible to malicious code.
+ *
+ *
+ * newProxyInPackage.{package name}
+ * ability to create a proxy instance in the specified package of which
+ * the non-public interface that the proxy class implements.
+ * 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.
*
*
*
@@ -63,6 +68,7 @@
* @see Field#set
* @see Method#invoke
* @see Constructor#newInstance
+ * @see Proxy#newProxyInstance
*
* @since 1.2
*/
diff -r 6c918c972850 -r 50bfa0defec2 jdk/src/share/classes/sun/misc/ProxyGenerator.java
--- 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() {
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 fields = new ArrayList();
+ private List fields = new ArrayList<>();
/** MethodInfo struct for each method of generated class */
- private List methods = new ArrayList();
+ private List methods = new ArrayList<>();
/**
* maps method signature string to list of ProxyMethod objects for
* proxy methods with that signature
*/
- private Map> proxyMethods =
- new HashMap>();
+ private Map> 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> legalExceptions = new ArrayList>();
+ List> legalExceptions = new ArrayList<>();
collectCompatibleTypes(
exceptionTypes, pm.exceptionTypes, legalExceptions);
collectCompatibleTypes(
@@ -588,7 +612,7 @@
}
}
} else {
- sigmethods = new ArrayList(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> uncoveredReturnTypes = new LinkedList>();
+ LinkedList> 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> 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> computeUniqueCatchList(Class>[] exceptions) {
- List> uniqueList = new ArrayList>();
+ List> 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,
diff -r 6c918c972850 -r 50bfa0defec2 jdk/src/share/classes/sun/reflect/annotation/AnnotationParser.java
--- 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 memberValues)
+ public static Annotation annotationForMap(final Class extends Annotation> type,
+ final Map memberValues)
{
- return (Annotation) Proxy.newProxyInstance(
- type.getClassLoader(), new Class>[] { type },
- new AnnotationInvocationHandler(type, memberValues));
+ return AccessController.doPrivileged(new PrivilegedAction() {
+ public Annotation run() {
+ return (Annotation) Proxy.newProxyInstance(
+ type.getClassLoader(), new Class>[] { type },
+ new AnnotationInvocationHandler(type, memberValues));
+ }});
}
/**
diff -r 6c918c972850 -r 50bfa0defec2 jdk/src/share/classes/sun/rmi/server/Util.java
--- 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() {
+ public Remote run() {
+ return (Remote) Proxy.newProxyInstance(loader,
+ interfaces,
+ handler);
+ }});
} catch (IllegalArgumentException e) {
throw new StubNotFoundException("unable to create proxy", e);
}
diff -r 6c918c972850 -r 50bfa0defec2 jdk/src/share/classes/sun/tracing/ProviderSkeleton.java
--- 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 newProxyInstance() {
- return (T)Proxy.newProxyInstance(providerType.getClassLoader(),
- new Class>[] { providerType }, this);
+ final InvocationHandler ih = this;
+ return AccessController.doPrivileged(new PrivilegedAction() {
+ public T run() {
+ return (T)Proxy.newProxyInstance(providerType.getClassLoader(),
+ new Class>[] { providerType }, ih);
+ }});
}
/**
diff -r 6c918c972850 -r 50bfa0defec2 jdk/test/java/lang/reflect/Proxy/nonPublicProxy/NonPublicProxyClass.java
--- /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 perms = permissions.elements();
+ while (perms.hasMoreElements()) {
+ sb.append("\n").append(perms.nextElement().toString());
+ }
+ return sb.toString();
+ }
+ }
+}
diff -r 6c918c972850 -r 50bfa0defec2 jdk/test/java/lang/reflect/Proxy/nonPublicProxy/SimpleProxy.java
--- /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;
+ }
+ });
+ }
+}
diff -r 6c918c972850 -r 50bfa0defec2 jdk/test/java/lang/reflect/Proxy/nonPublicProxy/p/Bar.java
--- /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 {
+}
diff -r 6c918c972850 -r 50bfa0defec2 jdk/test/java/lang/reflect/Proxy/nonPublicProxy/p/Foo.java
--- /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 {
+}
diff -r 6c918c972850 -r 50bfa0defec2 jdk/test/java/rmi/server/RMIClassLoader/loadProxyClasses/security.policy
--- 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";