On 02/25/2015 03:22 PM, Peter Levart wrote:
Hi Joel,

On 02/24/2015 12:26 PM, Joel Borggrén-Franck wrote:
Hi,

Here is a fix for an old issue with Class.getEnclosingMethod() and 
Class.getEnclosingConstructor(). The problem is that we throw a spurious 
AccessControlException in some cases when looking up enclosingMethod/Ctor in 
the presence of a SecurityManager.

  Consider the following classes:

class C {}

class A {
    public void someMetod() {
         class B {}
     }
}

If client C has a Class<?> token for B it can call 
classForB.getEnclosingMethod(). While the client C must have permissions to look at 
declared members of A, in the nested call java.lang.Class will be looking at declared 
members of A while constructing the answer, and java.lang.Class might not have 
permissions to do this, even though the “real” caller C has the correct permissions. 
So we and up with a call stack that looks like

Caller:                               Call:

j.l.Class(for A.class)          A.class::checkMemberAccess(classloader for 
j.l.Class); // this can throw ACE if A is loaded in a separate loader from 
java.lang.Class
j.l.Class(for B.class)          A.class::getDeclaredMethods(); // j.l.Class is 
the caller here
C                                       B.class::getEnclosingMethod();
.... application code ….

The solution here is to insert a doPrivileged block around the call where 
j.l.Class gets the members to construct the answer.

Webrev:http://cr.openjdk.java.net/~jfranck/8014678/

Bug is not open but the tests show how this is reproduced.

cheers
/Joel

Is the AccessControlException result of the fact that client code C is loaded by same class loader as A and therefore can access declared memebers of A without special permissions, but if the caller of getDeclaredMethods() is j.l.Class (system code), then it is not loaded by same class loader as A and the permission *is* checked, but C does not have it?

You are elevating the permission of the call to getDeclaredMethods() and therefore give client C access memeber of A even in situations where classloaders of C and A differ and C does not have special permission.

I think the right solution should be to pass the caller of getEnclosingMethod() to the logic of getDecalredMethods() without elevating the privilege. You'd have to create a private getDeclaredMethods() method taking additional 'caller' parameter to which both public methods getEnclosingMethod() and getDecalredMethods() would delegate.

Regards, Peter


Ah, never mind. I missed the explicit access check that getEnclosingMethod() already performs on it's own before calling getDeclaredMethods(). But the check is for the same permission and could be performed implicitly by getDeclaredMethods() if the caller of getEnclosingMethod() was passed to it. Just an optimization opportunity therefore.

Peter

Reply via email to