river-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Peter Firmstone <j...@zeus.net.au>
Subject Re: Learnings from a RevokeableDynamicPolicy & A Future Roadmap
Date Mon, 09 Aug 2010 21:30:49 GMT
Fred Oliver wrote:
> Peter,
> Thanks for the long answer. I'm still missing some implementation hints.
> In the case I suggested, downloaded code creates a socket on a port
> using the standard Java classes, gets the socket streams and begins
> communicating with the outside world. At this point, it is too late to
> stop the code from communicating by revoking permissions.
> If I understand correctly, instead, the downloaded code would not
> receive socket permissions at all (because they cannot be revoked
> after the socket is open), and would not be allowed to use the socket
> classes directly. Instead, a River factory class would be provided,
> and the downloaded code would be required to use that factory class to
> obtain a delegate for the socket. The delegate socket could then
> connect and return delegates for the streams to the downloaded code.
> In order to obtain permission for itself (to create and connect), the
> delegates would need to use doPrivileged() blocks? 

> Further, the
> revocation events are delivered to one or more of the delegates to
> force the socket to close.
That was the original intent, however, now I'm thinking the delegate 
catch AccessControlException, thrown by a helper class, called 
MethodAccessContoller, which the delegate calls prior to entering the 
privileged block, performs any clean up, then re-throws the exception.  
Code that doesn't need to do any clean up, doesn't need to catch the 

> Have I got the picture?
> The scope of the proposal is then to allow permission revocation to
> apply to a limited (but extendable) set of delegate factory classes
> which downloaded code must be written to use?
Yes, and to a limited subset of existing Java Permissions, which will be 
advised in the javadoc following auditing, although I guess there's a 
small risk that a standard JVM Permission that provides adequate 
protection today, may not in a future version.

Fred, you've just managed to clarify it in simple terms, having cleared 
that up, hopefully people can provide their insights into the risks 
associated with not calling AccessController.checkPermission on every 
method invocation on the delegate.

Basically: Method call from new thread? Permission check.  Permission 
revoked? Permission check again.  Previously checked Thread, no relevant 
revocation's since (of same Class<Permission>)? Don't check again, 
return quickly.

The assumption I've made is, it will be very difficult for an attacker 
to predict when a thread will access a method on the delegate, then 
later, be called by that very same thread, so his class can call the 
delegate unchecked.  Any thoughts on this?  Am I overlooking something?

I'm actually wondering about in the case of the given example, whether 
it is better to catch the AccessControlException, then throw an 
IOException, containing the relevant information, or to re-throw the 

After all it will be a client originated Thread that calls the proxy 
code, which is more likely to catch an IOException than an 


> Fred
> On Mon, Aug 9, 2010 at 7:12 AM, Peter Firmstone <jini@zeus.net.au> wrote:
>> Fred Oliver wrote:
>>> Peter,
>>> I'm not clear on the scope of the proposal. Do you depend on
>>> enumerating all of the classes for which delegates would be needed?
>>> How would you interpose the delegate?
>> Revokeability is intended for downloaded code.  I have some different
>> thoughts about possible implementations.  The aim is to force re checking of
>> a Permission if a reduction of trust has occurred. To never allow references
>> to objects with privileged functionality to escape into unprivileged code.
>>  The best place is to contain the privileged functionality within the
>> platform, the second best place, the client implementation or remotely in
>> the Server's service provider implementation.
>> Many Java classes are subject to Permission checks only in their
>> constructors, or obtained from checked methods or GuardedObjects, these
>> Permission's are not safe to grant if they are to be later revoked, object
>> references may still exist, enabling privileged functionality in untrusted
>> client code.  What is needed are new Permission's that protect the methods
>> and creation of these classes by using a delegate to wrap the class,
>> depriving access via existing unchecked methods.   I think a builder class
>> that returns OutputStreams (InputStreams, or any other etc), could build
>> many different types of OutputStreams but utilise the same delegate.  This
>> could be provided as part of the Apache River platform.
>> What I want to do, is enable a client to provide Permission's temporarily
>> for a period of time to a ProtectionDomain, then revoke that Permission
>> later.  I would want to do this if I utilise services from different servers
>> that utilise the same proxy code, so I can re-use the ClassLoader and
>> ProtectionDomain, to avoid having to use a new ClassLoader with re
>> verification of  the same bytecode.  This is based around provisioning of
>> proxy codebases, using Entry's to advertise the required codebase, version
>> and Permission's required.
>> I had thought about requiring all delegates register with the revokeable
>> policy, however now I'm having a change of heart, and think instead a class
>> or delegate could use a MethodAccessController, with two methods
>> checkPermission() and getPermission().  The RevokeableDynamicPolicy
>> implementer can provide the implementation for the MethodAccessController
>> interface.  Each delegate gets it's own MethodAccessController object
>> (during construction) which has been designated a Permission to check (at
>> construction time), from the policy.  The MethodAccessController
>> implementation will have to keep a static set internally of all objects, the
>> policy will require a static method to Enumerate over these and set them to
>> check when the Permission Class matches that of a revoked Permission,
>> probably by passing a Set of Classes.
>> This Permission check would be optimised, to call
>> AccessController.checkPermission(Permission) only under the following
>> conditions.
>>  1. If this is the first time the current thread has called a method
>>     (or constructor) on the delegate object.
>>  2. If revocation has occurred for a Permission with the same Class in
>>     any ProtectionDomain, since the last permission check performed on
>>     that thread.  The MethodAccessController keeps track of the
>>     threads with an object weak hash map.
>> The $1,000,000.00 question: Is the optimisation of only checking a thread
>> once, on the assumption that if the ProtectionDomain's on that thread's
>> stack are trustworthy to access the method, the code involved in this thread
>> can still be trusted until a Permission that implies it has become revoked?
>>  Remembering that the code was originally trusted, the object constructed
>> with the Permission check performed, utilised by that code for a period of
>> time, but now now that Permission has been revoked any method called on the
>> delegate throws an AccessControlException.
>> The only way the code could still have the Permission is if the
>> ProtectionDomain doesn't exist on the thread's stack, at the time of the
>> permission check, the check field is cleared for that thread and later, the
>> thread invokes the method with the ProtectionDomain in question on it's
>> stack, however to do so, the code in question must already hold a reference,
>> but not be involved in the current operations, it seems the probability
>> would be very low, the reference would have to be passed from another
>> thread, if an attacker could place this in the code, they'd be better off
>> attacking during the privileged period.  The Permission revoked code would
>> stop privileged operations during re verification of trust for another proxy
>> object and server.
>> Static fields within the code could be used to store information between
>> service proxy's, this has a parallel to applets, where this was fixed with
>> separate ClassLoader, the client has that option however.
>> Publicly shared proxy and service implementations can have their source
>> audited.
>>> As an example, I think you propose that if code in a domain has a
>>> socket open on a port for which access is later revoked, the code
>>> should be denied further read/write access to the socket.
>>> -Should the socket be left open or closed?
>> Closed, to free the port.  If somehow it is shared between threads, the
>> other thread will receive an IOException.
>>> -Was a delegate introduced and where?
>> The best place is in a builder or factory method, since constructors create
>> a dependency link.  I'm thinking of a implementing new Platform class or
>> builder for the various Stream classes, along with new Permission's
>>> -Can the code use reflection to bypass the delegate?
>> Yes, if it has Permission.
>>> -Is reflection denied generally?
>> Yes, it should not be granted to code that will have Permission's revoked.
>>> Thanks,
>> Your welcome, & thanks for asking too ;)
>> Cheers,
>> Peter.
>>> Fred
>>> On Sat, Aug 7, 2010 at 2:10 AM, Peter Firmstone <jini@zeus.net.au> wrote:
>>>> Please help identify any fallacies or oversights in the following
>>>> arguments.
>>>> A Permission may be revoked, at any point in time after a revocation,
>>>> untrusted code may hold a reference to a privileged object.
>>>> Some Permission's protect methods, such as Thread.interrupt(), these are
>>>> effectively revoked with the existing Java security model, however other
>>>> objects are only protected in their constructor, the responsibility being
>>>> on
>>>> the trusted code, not to let their references escape, such as
>>>> FileOutputStream.
>>>> The moment code holding a reference becomes untrusted, the reference has
>>>> escaped.
>>>> Instead of using a GuardedObject, or checking permission in constructors,
>>>> to
>>>> deal with Permission's that can be revoked, we need to encapsulate the
>>>> object that needs protection with a SecurityDelegate.
>>>> During a checkPermission call, the current Thread's AccessControlContext
>>>> is
>>>> obtained, and (gross simplification) is asked to checkPermission.  The
>>>> AccessControlContext contains all the ProtectionDomain's on the stack,
>>>> all
>>>> ProtectionDomains on the stack must have the Permission for it to
>>>> succeed.
>>>>  The ProtectionDomain's contained by the AccessControlContext are related
>>>> to
>>>> the class and object methods called and returned, the ProtectionDomain's
>>>> are
>>>> dynamically added or removed.
>>>> So the thinking behind the SecurityDelegate's private check method is
>>>> that
>>>> an object must be protected in a dynamically changing environment:
>>>>  1. Has the RevokeableDynamicPolicy advised that a check must be
>>>>    performed?
>>>>  2. Is this the same thread that the last security check was made
>>>>    against?  If we haven't been advised that there is a reduction of
>>>>    trust in our dynamic Security environment and the last
>>>>    checkPermission call succeeded on this thread, then we can assume
>>>>    that this Tread is still safe.
>>>>  3. If this thread is different or new, then we must checkPermission,
>>>>    regardless of whether trust has changed recently or not.
>>>> The costs:
>>>>  1. Multi-threading is penalised (although a WeakMap could be
>>>>    utilised, with threads as keys, and boolean check values, where
>>>>    all are set true by the notify() call).
>>>>  2. The three "if" calls on every method invocation, check, null and
>>>>    == Thread.
>>>>  3. Replicating the check method on all implementers (this will
>>>>    require a helper class to implement the check).
>>>>  4. The RevokeableDynamicPolicy will need to notify all
>>>>    SecurityDelegate's every time a reduction in trust occurs, it will
>>>>    rely on GC to clean up and remove SecurityDelegates.
>>>> The assumption is if the current Thread was trustworthy last call and the
>>>> environment hasn't experienced a reduction of trust, we can still trust
>>>> this
>>>> thread.  There is of course a risk that a Thread may have a new
>>>> ProtectionDomain on it's stack that isn't trusted, however this could
>>>> still
>>>> happen in the case of the guarded object, where the environment doesn't
>>>> experience a reduction of trust and the trusted code must be trusted not
>>>> to
>>>> let the reference escape it's own ProtectionDomain.  Any code that
>>>> experiences a reduction of trust will receive an AccessControlException.
>>>> Cheers,
>>>> Peter.

View raw message