A Bug in AccessControlContext.equals() and hashCode()?
Jeff Nisewanger
jeffrey.nisewanger at oracle.com
Tue Jul 1 19:42:45 UTC 2014
On 6/25/2014 9:02 PM, Xiaomin Ding wrote:
>> On 6/16/2014 10:40 PM, David M. Lloyd wrote:
>> On 06/16/2014 09:19 AM, Frank Ding wrote:
>>> Hi Jeff,
>>> Thanks for your reply. One further question is that you confirmed
>>> that two AccessControlContext objects considered equal via method
>>> equals() should return same results for
>>> AccessControlContext.checkPermission() but test shows that 2
>>> AccessControlContext objects are equal regardless of isLimited,
>>> limitedContext, parent, permissions, or privilegedContext. Does it make
>>> sense and apply to Java 8 AccessControlContext with JEP140?
>> Is it not true that a limited privileged context simply adds a
>> protection domain that restricts permissions to the limited set? This
>> seems to be the "obvious" implementation of the feature.
>>
>> If so, then equals() should have taken it into account as a matter of
>> course.
>> --
>> - DML
> Hi Jeff,
> Could you pls let us know your insight?
JDK 8 introduced, via JEP 140, some new variants of the doPrivileged()
method. The older
doPrivileged() methods simply stop the access control algorithm during a
security check
so that earlier method's ProtectionDomains on the call stack (or
inherited from the parent
thread etc.) are not considered and will not cause a security check to
be denied.
The new "limited" variants from JEP 140 take one or more Permission
instances as
parameters that describe which specific permission checks should stop
the stack walk.
Other security checks that do not match the new Permission parameters
will cause the
stack walk to continue as if the doPrivileged() method had not been
used. This allows code
to use doPrivileged() to assert a limited subset of its own permissions
without asserting all
of them.
As Frank noted, an AccessControlContext instance may have some
additional internal fields
initialized when it is created within the scope of a limited version of
the doPrivileged() method.
These fields are checked in JDK 8 as part of the equals() and
checkPermission() implementations.
Read the full class-level documentation carefully at the top of the
javadoc page
for java.security.AccessController. It describes the call stack walking
algorithm
used during a security check and how that works with the new JDK 8
limited doPrivileged() methods
that were added by JEP 140.
Here are some javadoc links:
http://docs.oracle.com/javase/8/docs/api/java/security/AccessController.html
http://docs.oracle.com/javase/8/docs/api/java/security/AccessController.html#getContext--
http://docs.oracle.com/javase/8/docs/api/java/security/AccessController.html#doPrivileged-java.security.PrivilegedAction-java.security.AccessControlContext-java.security.Permission...-
For additional background on the new JDK 8 feature that allows limiting
the access provided by
the use of doPrivileged() please see the following technote subsection:
http://docs.oracle.com/javase/8/docs/technotes/guides/security/doprivileged.html#asserting_a_subset_of_privileges
And this is the original feature request:
http://bugs.java.com/bugdatabase/view_bug.do?bug_id=7083329
Two AccessControlContext instances can be created or obtained under
differing circumstances
and still be considered equal() if they would always check the same
internal ProtectionDomains
during a call to checkPermission(). AccessControlContexts created within
the influence of one
of the new JEP 140 methods add some complexity.
For instance, if you call AccessController.getContext() when there is a
JDK 8 "limited" version of the
doPrivileged() method on the thread's call stack it will return an
AccessControlContext that conceptually
captures and encapsulates the ProtectionDomains of the methods on the
call stack leading back
to the doPrivileged() call and it will also include the limiting
permission parameters of that
doPrivileged() call and the earlier call stack elements above the
doPrivileged() call. This allows
a later direct call to the AccessControlContext's checkPermission()
method on any thread
to behave the same as a call to AccessController.checkPermission() on
the original thread.
You might think that this "fancy" AccessControlContext containing the
limited doPrivileged() state
could not be equal to a "simple" AccessControlContext captured by
AccessController.getContext()
on a thread without any doPrivileged() method on the call stack or with
a non-limited doPrivileged()
method on the call stack. However, this may not be true. If the
ProtectionDomains on the call stack
leading back to the doPrivileged() method are a superset of the
ProtectionDomains that are reachable
beyond the limited doPrivileged() then those later ProtectionDomains are
redundant and the conceptually
"fancy" instance will have actually been created with the same internal
state as the "simple" instance.
More information about the security-dev
mailing list