@CallerSensitive一些理解

    @CallerSensitive
    public static Lookup lookup() {
        return new Lookup(Reflection.getCallerClass());
    }

    @CallerSensitive
    public static native Class<?> getCallerClass();

JEP 176: Mechanical Checking of Caller-Sensitive Methods中的说明:

Improve the security of the JDK's method-handle implementation by replacing 
the existing hand-maintained list of caller-sensitive methods with a mechanism 
that accurately identifies such methods and allows their callers to be discovered reliably.

使用能够精确识别caller-sensitive方法并且保证这些方法的调用者可靠地被发现的一种机制 代替 现存的手动维护的caller-sensitive方法表,提高JDK method-handler实现的安全性。

A caller-sensitive method varies its behavior according to the class of its immediate caller. 
It discovers its caller's class by invoking the sun.reflect.Reflection.getCallerClass method.

caller-sensitive方法会根据其直接调用者的类型改变其行为。通过调用sun.reflect.Reflection.getCallerClass方法可以获得调用者class类型。

Most caller-sensitive methods act in some way as an agent for the caller. 
When invoked via reflection, these methods must be handled specially in order to 
ensure that the class of the actual caller, rather than some class of the reflection mechanism itself, 
is returned by the getCallerClass method.

大多数caller-sensitive方法某种程度上是作为调用者的代理。当通过反射调用时,这些方法必须经过特殊处理以确保getCallerClass返回的是实际调用者的class类型,而不是反射机制本身的某些类。

另外,据JVM注解@CallSensitive文章,有一个类似的解释:

这个注解是为了堵住漏洞用的。曾经有黑客通过构造双重反射来提升权限,
原理是当时反射只检查固定深度的调用者的类,看它有没有特权,
例如固定看两层的调用者(getCallerClass(2))。如果我的类本来没足够
权限群访问某些信息,那我就可以通过双重反射去达到目的:反射相关
的类是有很高权限的,而在 我->反射1->反射2 这样的调用链上,反射2
检查权限时看到的是反射1的类,这就被欺骗了,导致安全漏洞。
使用CallerSensitive后,getCallerClass不再用固定深度去寻找
actual caller(“我”),而是把所有跟反射相关的接口方法都标注上
CallerSensitive,搜索时凡看到该注解都直接跳过,这样就有效解决了
前面举例的问题


作者:王侦
链接:https://www.jianshu.com/p/fe292d874e04
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
 

JVM注解@CallSensitive

HEL_WOR 2015-12-06 23:28:57 10819 收藏 3
展开
转载请注明 http://blog.csdn.net/HEL_WOR/article/details/50199797

@CallSensitive是JVM中专用的注解,在类加载过过程中是可以常常看到这个注解的身影的。
这是在Sun.reflect中的定义:

@Retention(RetentionPolicy.RUNTIME)
@Target({ java.lang.annotation.ElementType.METHOD })
public @interface CallerSensitive {
}
1
2
3
4
而对@CallSensitive的使用如下:

@CallerSensitive
public final ClassLoader getParent() {
if (this.parent == null)
return null;
SecurityManager localSecurityManager = System.getSecurityManager();
if (localSecurityManager != null)
checkClassLoaderPermission(this.parent, Reflection.getCallerClass());
return this.parent;
}
1
2
3
4
5
6
7
8
9
至少在刚刚看见这个注解时我是不明白@CallSensitive有什么用处,一来这是JVM里专用的一个注解,二来在JVM规范和一些书上也没有看到对这个注解的解释,第三是发现百度不出来对这个注解的解释。

这里有两个解释:
What does the sun.reflect.CallerSensitive annotation mean?
JEP 176: Mechanical Checking of Caller-Sensitive Methods

StackOverFlow里的回答,答案只是提到了@CallSensitive用来找到真正发起反射请求的类的,但没有提到具体怎么寻找的,而在OpenJDK文档里,有下面这句话。

When invoked via reflection, these methods must be handled specially in order to ensure that the class of the actual caller, rather than some class of the reflection mechanism itself, is returned by the getCallerClass method. The logic for doing this involves pattern matching against a hand-maintained list of caller-sensitive methods,

我原本的理解是这个注解用来区分开反射和自省的,并且只有调用方有这个注解我才会回应它,但感觉总有地方说不过去。所以我去问了莫枢:

这个注解是为了堵住漏洞用的。曾经有黑客通过构造双重反射来提升权限,原理是当时反射只检查固定深度的调用者的类,看它有没有特权,例如固定看两层的调用者(getCallerClass(2))。如果我的类本来没足够权限群访问某些信息,那我就可以通过双重反射去达到目的:反射相关的类是有很高权限的,而在 我->反射1->反射2 这样的调用链上,反射2检查权限时看到的是反射1的类,这就被欺骗了,导致安全漏洞。使用CallerSensitive后,getCallerClass不再用固定深度去寻找actual caller(“我”),而是把所有跟反射相关的接口方法都标注上CallerSensitive,搜索时凡看到该注解都直接跳过,这样就有效解决了前面举例的问题

下面是我的理解:
当”我“->反射1->反射2->反射3->反射4->…反射->N,从”我“开始后的每个引用对象,当我引用下一个对象(对象1)时,首先会被装载,验证,这个时候把这个对象在这个过程中没调用过的反射接口都标记上@callSentitive,然后对象1引用对象2后重复这个过程一直到N,那么在N调用GetCallCalss时跳过这中间所有已经被标记的对象,最后到达未被标记的“我”。

如果是这样的话,我倒是比较好奇当初用固定深度检查调用类有无权限时,从“我”->对象1 -> 对象2,如果对象1有很高的权限,那”我”是如何有权限调用对象1的?有点想读和写的权限控制,有点模糊,先复习下那部分再来补充吧。
————————————————
版权声明:本文为CSDN博主「HEL_WOR」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/HEL_WOR/java/article/details/50199797

原文地址:https://www.cnblogs.com/makai/p/12857746.html