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