Hi Doug,
<aside: FYI copies of my replies to security-dev are being held for
approval as I'm not a subscriber.>
Doug Lea said the following on 04/16/10 21:43:
On 04/15/10 18:34, Martin Buchholz wrote:
People are using Atomic field updaters to update fields in classes in
other classloaders.
I think the policy on this awaits interpretation by Jeff
or other members of security team. FWIW, my take is that
if users know that they may cross class loaders, then they
should wrap these in doPrivileged anyway. As in ...
I'm coming around to agreeing with the proposed fix. My take is that the
real security check should take place at the time the field is set:
field_x_updater.set(obj, val);
At this point the calling code must have the necessary permissions to
set field x of the given obj of type T. And I believe we do indeed check
this.
When the AtomicXXXXFieldUpdater constructor binds itself to the Field
object for T.x that's an optimization. There's no reason we couldn't do
this on each call to set() - other than it would perform terribly. So in
that sense the security checks that take place at construction are
incidental** and so we should be as permissive as we can make them
_provided_ that the actual set() call will make the necessary permission
checks.
** This particular check is also incidental because we happen to use a
public reflection method to get the Field object. We could just as
easily have used a magic VM hook.
David
-----
Now, they could work around the problem by creating their atomic
updater inside a doPrivileged, but probably we intend for them not to
have to do that.
That won't work. The doPrivileged doesn't give them any additional
permissions in their code, so it has no affect.
That's not my understanding. doPrivileged is useful whenever you want to
perform an operation with permissions checked only on the current stack
frame, and not on any other code executing up the stack.
But if David is right about this not always sufficing ...
To be specific it will depend on the exact call stack. In general
you'll get
the least permissions based on your stack. So if application code with no
permissions calls library code with permissions, the doPrivileged in the
library code says "only look at my permissions" - and so the call can
work.
But if the application code with no permissions calls doPrivileged
then it
still has no permissions. A doPrivileged by the application code will
only
have an effect if the application code has the necessary permissions but
there is a frame with fewer permissions further up the stack.
... then it may be necessary to issue the doPriviliged
inside the constructor in all cases, just in case it does
cross class loaders?
-Doug