Replacement of sun.reflect.Reflection#getCallerClass

Peter Levart peter.levart at gmail.com
Thu Sep 19 21:47:02 UTC 2013


On 09/19/2013 09:55 PM, David M. Lloyd wrote:
>> Imagine:
>>
>>
>>          // this throws IllegalAccessException. If it didn't...
>>          MethodHandle mh = MethodHandles.lookup()
>>              .in(String.class)
>>              .findVirtual(
>>                  Field.class,
>>                  "get",
>>                  MethodType.methodType(Object.class, Object.class)
>>              );
>>
>>          Field valueField = String.class.getDeclaredField("value");
>>
>>          String abc = "abc";
>>
>>          // ... then the following would invoke: valueField.get(abc) and
>> pretend that
>>          // it was invoked from the String class, which would succeed...
>>          char[] abcArray = (char[])(Object) mh.invokeExact(valueField,
>> (Object) abc);
>>
>>          // ...and you could observe the following:
>>          abcArray[0] = 'A';
>>          assert abc.charAt(0) == 'A';
>
> This must have changed since JDK 7 because I don't see any of this 
> behavior with the classic getCallerClass(int) method.  In other words 
> using "in" does not appear to affect the frames reported by 
> getCallerClass(int) (or SecurityManager.getClassContext() or 
> Thread.getStackTrace()) at all.

It only affects frames seen in caller sensitive methods. In other 
methods, the JDK7 reported caller is the one invoking the MH, I think, 
but that's not important, since other methods are not caller sensitive. 
In JDK8 you can't even get the caller unless you are in the @CS 
annotated method.

>
> It looks like this new behavior is a result of @CallerSensitive and 
> changes associated with it (in particular those weird pseudo-class 
> names are not reported in 7); I'd say the fatal flaw exposed here is 
> in those changes, not in the original method behavior.  It seems like 
> we've gone way off course if this is the case.

I think the behavior is equivalent. In JDK7 all caller-sensitive methods 
are maintained as a hard-coded list/switch inside MHs implementation. 
They are marked with @CS annotation in JDK8 instead, which is easier to 
maintain.

>
> Especially consider that SecurityManager.getClassContext() is a 
> supported, non-deprecated API designed for the express purpose of 
> access checking, which (as far as I can test) works similarly to 
> getCallerClass(int).  If method handles could spoof callers in this 
> way then we've blown yet another massive hole in Java security.

They can't spoof callers. As you can see in above example, such spoofing 
look-ups of @CS methods are prevented.

>
> -- 
> - DML


Regards, Peter




More information about the core-libs-dev mailing list