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