Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-7103570

AtomicIntegerFieldUpdater does not work when SecurityManager is installed

    Details

    • Type: Bug
    • Status: Closed
    • Priority: P4
    • Resolution: Fixed
    • Affects Version/s: 7
    • Fix Version/s: 8
    • Component/s: core-libs
    • Labels:
    • Subcomponent:
    • Resolved In Build:
      b40
    • CPU:
      x86
    • OS:
      linux_oracle_5.4, windows_7
    • Verification:
      Verified

      Backports

        Description

        FULL PRODUCT VERSION :
        java version "1.7.0_02-ea"
        Java(TM) SE Runtime Environment (build 1.7.0_02-ea-b08)
        Java HotSpot(TM) Client VM (build 22.0-b06, mixed mode, sharing)

        ADDITIONAL OS VERSION INFORMATION :
        Microsoft Windows [Version 6.1.7601]

        A DESCRIPTION OF THE PROBLEM :
        The AtomicIntegerFieldUpdater and AtomicReferenceFieldUpdater classes cannot be constructed when a SecurityManager is installed. It fails with:

        java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")

        STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
        Call AtomicIntegerFieldUpdater.newUpdater when launching java with the -Djava.security.manager argument.

        EXPECTED VERSUS ACTUAL BEHAVIOR :
        EXPECTED -
        Expected result is a new AtomicIntegerFieldUpdater.
        ACTUAL -
        Actual result is a SecurityException, wrapped by a RuntimeException.

        ERROR MESSAGES/STACK TRACES THAT OCCUR :
        Exception in thread "main" java.lang.ExceptionInInitializerError
        Caused by: java.lang.RuntimeException: java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")
                at java.util.concurrent.atomic.AtomicIntegerFieldUpdater$AtomicIntegerFieldUpdaterImpl.<init>(AtomicIntegerFieldUpdater.java:283)
                at java.util.concurrent.atomic.AtomicIntegerFieldUpdater.newUpdater(AtomicIntegerFieldUpdater.java:73)
                at dirmi.SecurityBug.<clinit>(SecurityBug.java:10)
        Caused by: java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")
                at java.security.AccessControlContext.checkPermission(AccessControlContext.java:366)
                at java.security.AccessController.checkPermission(AccessController.java:555)
                at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
                at java.lang.SecurityManager.checkMemberAccess(SecurityManager.java:1679)
                at java.lang.Class.checkMemberAccess(Class.java:2174)
                at java.lang.Class.getDeclaredField(Class.java:1896)
                at java.util.concurrent.atomic.AtomicIntegerFieldUpdater$AtomicIntegerFieldUpdaterImpl.<init>(AtomicIntegerFieldUpdater.java:276)
                ... 2 more

        REPRODUCIBILITY :
        This bug can be reproduced always.

        ---------- BEGIN SOURCE ----------
        import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;

        // Tests bug in AtomicIntegerFieldUpdater.
        public class SecurityBug {
            private static final AtomicIntegerFieldUpdater<SecurityBug> updater;

            static {
                updater = AtomicIntegerFieldUpdater.newUpdater(SecurityBug.class, "theField");
            }

            private volatile int theField;

            public static void main(String[] args) throws Exception {
                new SecurityBug();
            }
        }

        ---------- END SOURCE ----------

        CUSTOMER SUBMITTED WORKAROUND :
        Use the AtomicInteger class or relax the security policy.

          Issue Links

            Activity

            Hide
            dholmes David Holmes added a comment -
            BT2:EVALUATION

            The AtomicFieldUpdater implementation invokes class.getDeclaredField() without using a doPrivileged block. As a result, because the AtomicFieldUpdater class and the application class are in different packages, the SecurityManager will invoke AccessController.checkPermission and that will fail (unless the requisite permission has been set in the current security policy). We need to call getDeclaredField in a doPrivileged block.
            Show
            dholmes David Holmes added a comment - BT2:EVALUATION The AtomicFieldUpdater implementation invokes class.getDeclaredField() without using a doPrivileged block. As a result, because the AtomicFieldUpdater class and the application class are in different packages, the SecurityManager will invoke AccessController.checkPermission and that will fail (unless the requisite permission has been set in the current security policy). We need to call getDeclaredField in a doPrivileged block.
            Hide
            dholmes David Holmes added a comment -
            BT2:PUBLIC COMMENTS

            The access control exception comes from a call to getDeclaredField:

            java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")
                    at java.security.AccessControlContext.checkPermission(AccessControlContext.java:366)
                    at java.security.AccessController.checkPermission(AccessController.java:555)
                    at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
                    at java.lang.SecurityManager.checkMemberAccess(SecurityManager.java:1679)
                    at java.lang.Class.checkMemberAccess(Class.java:2174)
                    at java.lang.Class.getDeclaredField(Class.java:1896)
                    at java.util.concurrent.atomic.AtomicIntegerFieldUpdater$AtomicIntegerFieldUpdaterImpl.<init>(AtomicIntegerFieldUpdater.java:276)

            when this occurs from the AtomicIntegerFieldUpdater implementation access is denied. But if the application itself calls getDeclaredField directly then it works. According to the docs for getDeclaredField a security exception is thrown when a security manager, s, is present and any of the following conditions is met:
                invocation of s.checkMemberAccess(this, Member.DECLARED) denies access to the declared field
                the caller's class loader is not the same as or an ancestor of the class loader for the current class and invocation of s.checkPackageAccess() denies access to the package of this class

            Looking at SecurityManager we see that checkMemberAccess will call checkPermission if the caller's classloader and the target class's classloader are different - which they are. This explains why a direct call to getDeclaredField works.

            checkPermission simply delegates to AccessController.checkPermission. That check would pass if we had privileged system code on the stack. But the atomic updater does not use doPrivileged. It should.
            Show
            dholmes David Holmes added a comment - BT2:PUBLIC COMMENTS The access control exception comes from a call to getDeclaredField: java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "accessDeclaredMembers")         at java.security.AccessControlContext.checkPermission(AccessControlContext.java:366)         at java.security.AccessController.checkPermission(AccessController.java:555)         at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)         at java.lang.SecurityManager.checkMemberAccess(SecurityManager.java:1679)         at java.lang.Class.checkMemberAccess(Class.java:2174)         at java.lang.Class.getDeclaredField(Class.java:1896)         at java.util.concurrent.atomic.AtomicIntegerFieldUpdater$AtomicIntegerFieldUpdaterImpl.<init>(AtomicIntegerFieldUpdater.java:276) when this occurs from the AtomicIntegerFieldUpdater implementation access is denied. But if the application itself calls getDeclaredField directly then it works. According to the docs for getDeclaredField a security exception is thrown when a security manager, s, is present and any of the following conditions is met:     invocation of s.checkMemberAccess(this, Member.DECLARED) denies access to the declared field     the caller's class loader is not the same as or an ancestor of the class loader for the current class and invocation of s.checkPackageAccess() denies access to the package of this class Looking at SecurityManager we see that checkMemberAccess will call checkPermission if the caller's classloader and the target class's classloader are different - which they are. This explains why a direct call to getDeclaredField works. checkPermission simply delegates to AccessController.checkPermission. That check would pass if we had privileged system code on the stack. But the atomic updater does not use doPrivileged. It should.
            Show
            dholmes David Holmes added a comment - BT2:EVALUATION http://hg.openjdk.java.net/jdk8/tl/jdk/rev/48513d156965

              People

              • Assignee:
                dholmes David Holmes
                Reporter:
                webbuggrp Webbug Group
              • Votes:
                0 Vote for this issue
                Watchers:
                0 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved:
                  Imported:
                  Indexed: