On 09/03/2013 12:16 PM, Peter Levart wrote:
On 09/03/2013 04:39 PM, Nick Williams wrote:
>Do you mean sun.reflect.CallerSensitive can go away?  This is very
important part of the design that we need to detect which methods are
caller-sensitive.   I keep seeing you suggest this and it is unclear
to me if you only mean to remove java.lang.@CallerSensitive in your
proposal.
Yes, that's what I mean. If you carefully examine the (existing)
native code that backs getCallerClass, you see that @CallerSensitive
is/only/  used as an enforcement mechanism. When I first read about
@CallerSensitive, I/thought/  you could take a call stack like this one:

@CallerSensitive getCallerClass()
@CallerSensitive someMethod1()
@CallerSensitive someMethod2()
@CallerSensitive someMethod3()
@CallerSensitive someMethod4()
actualCallerMethod()

And calling getCallerClass would return the class for
actualCallerMethod(). However, I was wrong. getCallerClass/always/
returns someMethod1(). @CallerSensitive is/not/  used to determine
when to stop looking for the caller. It's just an enforcement
mechanism to ensure that only built-in JVM classes can call
getCallerClass.

*AND* that Reflection.getCallerClass() can only be called from within
methods annotated with @CallerSensitive.

Now for that part, the public API equivalent
(StackTraceFrame.getCallerClass() or whatever it is called) need not be
restricted to methods annotated with any annotation, but that means that
this public API should not be used to implement security decisions since
MethodHandles API allows caller to be spoofed unless looking-up a method
annotated with @CallerSensitive...

Using an annotation for security decisions is pretty far off from the standard security model in any case. Why not use a regular permission check? If performance is a concern, the check need only be made one time when an instance is acquired that has these methods on it.

  This is/not/  how I did it, this is how it already was. Because of
this, you could delete the @CallerSensitive annotation completely and
getCallerClass still be fully functional the way it is. It just
wouldn't be restricted to annotated methods anymore.

For security unrelated things (like logging and similar) public API need
not include any enabling annotation, but it needs to be documented that
it should not be used for security decisions.

s/need not/should not/, IMO

***

Regarding ability to obtain j.l.Class instances for classes that client
code would otherwise have no access to:

What about a simple restriction on methods returning such instances that
Class objects are only returned when they are resolvable from the
ClassLoader of client code. If they are not resolvable, null is
returned. For example, the equivalent of:

public class StackTraceFrame {

     private final Class<?> declaringClass;

     @CallerSensitive
     public Class<?> getDeclaringClass() {
         try {
             return Class.forName(declaringClass.getName(),
                                  false,
Reflection.getCallerClass().getClassLoader())
                    == declaringClass ? declaringClass : null;
             }
         } catch (ClassNotFoundException ignore) {}
         return null;
     }

     // the name can be exposed without fear...
     public String getDeclaringClassName() {
         return declaringClass.getName();
     }


This example could be implemented more efficiently then above code
(using private Class/ClassLoader API).

I don't think this will hold up. Why would (for example) a logging API have access to every class loader that might need to log something? In any system of appreciable size, there is typically at least *some* class loader isolation, often a lot of it. Utilities like logging or security code that need to do this kind of check do not typically have direct access to classes which are "higher on the stack", so to speak.

--
- DML

Reply via email to