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 Tue, 17 Aug 2010 00:06:15 GMT
Fred Oliver wrote:
> To at least partially answer my own question, I think that the answer
> is that the socket can't be closed (at least in all cases).
>
> If the delegate for a resource has multiple users (codebases,
> principals, etc.) then closing the resource because permission for one
> of the users has been revoked denies access to the resource by the
> remaining valid users. (This allows a denial of service attack.) And
> then, if you can't close the resource (socket), you can't kick loose
> the no longer trusted thread blocked reading from it. You may be able
> to determine the special case of no user retaining access (everyone's
> access was revoked) and can then close the resource.
>
> In the standard security model, there are no checks for
> reading/writing sockets. Allowing revocation means that checks must be
> added for each individual read or write call on the socket streams. Is
> that level of performance satisfactory?
>   

I've just spotted a possible performance improvement.

We can eliminate the end() call in the finally block, put all the 
checkPermission calls there instead.  This substantially reduces the 
caching operations.  Perhaps we can manage the Socket some other way, we 
just block unauthorised access using the delegate?

try {
    // Do some processing
    return something;
} finally {
    ECM.checkPermission(Collection<Permission> permissions);
}

The current expense for making a Permission call via ECM (remembering 
the first is always going to be expensive), currently requires the three 
ECM calls in succession:

begin();
checkPermission(perm);
end();

begin():

   1. Associate the thread with the reaper.


checkPermission(perm):

   1. Obtain the read lock;
   2. Add the current thread to the execution cache.
   3. Associate the current AccessControlContext with the current thread
   4. Check if the AccessControlContext has been checked for this
      Permission previously.
   5. If it has been checked before, return, else do
      AccessController.checkPermission(perm), cache the result if it
      succeeds.

Each end():

   1. Obtain the read lock;
   2. Remove the thread and reaper from the cache.
   3. Remove the thread association with the AccessControlContext.
   4. Remove the thread from the execution cache.

      
This could be simplified to (no reaper or thread caching):

checkPermission(perms)

   1. Obtain the read lock;
   2. For each Permission, check if the current AccessControlContext has
      been checked for this Permission previously, if so return.
      (HashMap lookup - fast).
   3. If the AccessControlContext hasn't been checked previously, do
      AccessController.checkPermission(perm), cache the result if it
      succeeds, then return.

So for performance reasons, it looks like we need to be considering some 
other way to manage the Socket, the ECM would serve us better if we kept 
it simple?

I think your earlier suggestion of an event notification might be more 
useful, if provided as a parameter in the checkPermission call, in the 
event of failure, an event would be generated, the delegate could then 
decide what action to take.  If it only had one user, then it knows to 
close the Socket, if it has multiple users, it might just keep score.

This stops the transmission of data from unauthorised code, but it 
doesn't close the socket.

Cheers,

Peter.
>   
>> If there is untrusted code on a thread's stack, and if the thread
>> called a delegate, and if the delegate is in the between ECM.begin()
>> and ECM.end(), then the delegate's reaper will be called, and it can
>> close the socket.
>>
>> If the revocation happened elsewhere (e.g. the untrusted code is not
>> on any stack, or is occupied with some other task), how does the
>> socket get closed?
>>
>> Fred
>>     



Mime
View raw message