Tim Blackman wrote:
On Jul 31, 2010, at 11:53 PM, Peter Firmstone wrote:
<snip>
A RevokeableDynamicPolicy supports the addition or removal of PermissionGrant's
<snip>
Hmmm.
I remember talking with Bob and Mike Warres about this. The problem with
removing permission grants is that when code is granted a permission, it can
very likely squirrel away something -- an object, or another capability
available through the granted permission -- that will permit it to perform the
same operation again without the JVM checking for the permission again. Our
conclusion was that there was probably no effective way to implement removal of
permission grants.
Perhaps there is something about the particulars of what you have done here to
negate this argument -- and I have not had the time to check the details of
your stuff myself to be sure -- but my guess is that it will be difficult or
impossible to do this in an airtight manner.
First I'd better point out that this is still an experiment and may not
make a release, but I'm glad you've responded, as security is a
difficult issue and all help is appreciated.
The SecurityDelegate's I mentioned earlier, are of course a compromise,
many existing security guards on existing Java classes are on
constructors or methods that return object's, however object's such as
OutputStream and the likes, have unguarded methods, so once these
objects have been released, the reference can be stored, by what may
later become untrusted, and the methods called by untrusted objects.
The SecurityDelegate is a wrapper class that implements the same
interface as the guarded object, but once notified of a Permission
revocation ensures the next thread to access the guarded object, through
the SecurityDelegate has AccessController.checkPermission called again.
Because of the cost of the Permission check, it's too expensive to call
on every method invocation.
However there is still a flaw in this, consider for a moment an object
protected by a SecurityDelegate, permission's are revoked, the policy
notifies all SecurityDelegate's of a revocation, they ensure the next
method call rechecks permission. The flaw is that once the
SecurityDelegate, containing the protected object is in untrusted hands,
we don't know how many references to it exist. The next call might have
permission, however there is no guarantee that another following will.
The mixing of untrusted and trusted code is the risk.
While it cannot be eliminated entirely, every method requiring
protection, should execute a private method something like the following
(Constructors and methods excluded for clarity):
class ProtectedOutputStream extends OutputStream implements
SecurityDelegate {
private final OutputStream protected;
private volatile boolean check = true;
private volatile Thread currentThread = null;
public void notify(){
check = true;
}
private void check(){
if ( check == true) {
AccessController.checkPermission(perm);
currentThread = Thread.currentThread();
check = false;
return;
}
if ( currentThread != null ) {
if (Thread.currentThread() == currentThread ) {
return;
}
}
AccessController.checkPermission(perm);
currentThread = Thread.currentThread();
return;
}
public void write(byte[] b) {
check();
protected.write(b);
}
}
Still, I'm not sure if this is enough to protect the object, there are
some Thread timing issues I've ignored here, but those aside, I don't
want to call the AccessController every invocation, for obvious
efficiency reasons.
Thought's and ideas?
Cheers,
Peter.