RFR 8014678: Spurious AccessControlException thrown in java.lang.Class.getEnclosingMethod()

Peter Levart peter.levart at gmail.com
Wed Feb 25 14:26:28 UTC 2015


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




More information about the core-libs-dev mailing list