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