Replacement of sun.reflect.Reflection#getCallerClass
Nick Williams
nicholas+openjdk at nicholaswilliams.net
Wed Sep 18 15:10:24 UTC 2013
On Sep 4, 2013, at 11:38 PM, Andrew Thompson wrote:
> Indeed if giving access to arbitrary Class<?> is going to introduce such headaches as exposing sun.* and trying to support arbitrary class loaders then Ralph has the right point.
> It's also an example of the advantages or mirrors that Gilad is talking about here:http://gbracha.blogspot.com/2010/03/through-looking-glass-darkly.html
The fact of the matter is, code can still access sun.* Classes if it wants to. It can either use Class#forName (which can be subverted with a SecurityManager) or it can compile against them. Sure, you're not _supposed_ to use the sun.* classes, but the compiler lets you. If getting a Class<?> is a security vulnerability, then the game's already over.
>
>
> So how about replace
>
> Class<?> getDeclaringClass()
>
> With
>
> DeclaringType getDeclaringType()
>
> Where DeclaringType is
>
> package java.lang.reflect(
> public interface DeclaringType extends Type {
>
> public ClassLoader getClassLoader() throws SecurityException;
> public String getName();
> public ProtectionDomain getProductionDomain() throws SecurityException;
> public Package getPackage();
I'm not completely opposed to this idea, but it seems unnecessary to me and it restricts future development. Somebody somewhere will come up with a legitimate reason for getting some other information from the class, and they'll have to wait until the next JDK to get the change made to DeclaringType. The solution is to keep people from misusing Class<?>.
It has been well established that a determined developer can get a Class somehow. The protections in the JVM should prevent you from actually *using* that class (instantiating, calling methods, etc.) if you're not allowed to. They should *not* prevent you from *inspecting* that class.
>
> For convenience java.lang.Class could implement this interface but security sensitive contexts could return a much more limited type when appropriate.
>
>
>
>
> On Sep 3, 2013, at 3:45 PM, Ralph Goers <ralph.goers at dslextreme.com> wrote:
>
>> In Log4j's case the information we want from each StackTraceFrame is:
>>
>> a) the class name,
>> b) the jar or directory where the class resided.
>> c) the version of the jar.
>> d) the ClassLoader associated with the class.
>>
>> Having the actually Class object allows us to get all of this information but if it is deemed more secure to just include all the individual information instead that would be fine.
>>
>> Ralph
>>
>> On Sep 3, 2013, at 12:21 PM, Mandy Chung wrote:
>>
>>> On 9/3/13 11:11 AM, Peter Levart wrote:
>>>> On 09/03/2013 07:41 PM, David M. Lloyd wrote:
>>>>>> 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:
>>>>>>
>>>>>
>>>>> 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.
>>>>
>>>> Ok, I understand. What about the other way around - would this be acceptable from security perspective (asking Mandy?):
>>>
>>> I don't think that works for log4j either. In general we should only allow a ClassLoader A to access classes loaded by a ClassLoader B only if B trusts A (i.e A is the same or an ancestor of B); otherwise some kind of permission check (e.g. package access) is required. Log4j wants to access all Class instances on the stack for diagnosibility purpose and unless Log4j is loaded by the bootstrap class loader (put -Xbootclasspath) it may not be able to get access to all classes via Class.forName call.
>>>
>>> This would probably need a coarse-grained permission than a fine-grained permission check on the indivdual stack frame subject to the ClassLoader/Class.
>>>
>>> Mandy
>>>
>>>>
>>>> - If you can see me (by name), then you're exposed (I can get you):
>>>>
>>>> public class StackTraceFrame {
>>>>
>>>> private final Class<?> declaringClass;
>>>>
>>>> @CallerSensitive
>>>> public Class<?> getDeclaringClass() {
>>>> try {
>>>> Class<?> cc = Reflection.getCallerClass();
>>>> return Class.forName(cc.getName(),
>>>> false,
>>>> declaringClass.getClassLoader())
>>>> == cc ? declaringClass : null;
>>>>
>>>> } catch (ClassNotFoundException ignore) {}
>>>> return null;
>>>> }
>>>>
>>>>
>>>> This would not present a problem for JDK system classes since they can not see client code.
>>>
>>
>
More information about the core-libs-dev
mailing list