< prev index next >

src/java.base/share/classes/java/security/AccessController.java

Print this page
rev 52360 : 8212605: Pure-Java implementation of AccessController.doPrivileged

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.  Oracle designates this

@@ -23,13 +23,21 @@
  * questions.
  */
 
 package java.security;
 
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.ref.Reference;
 import sun.security.util.Debug;
 import jdk.internal.reflect.CallerSensitive;
 import jdk.internal.reflect.Reflection;
+import jdk.internal.vm.annotation.DontInline;
+import jdk.internal.vm.annotation.ForceInline;
+import jdk.internal.vm.annotation.ReservedStackAccess;
 
 /**
  * <p> The AccessController class is used for access control operations
  * and decisions.
  *

@@ -294,11 +302,14 @@
      * @see #doPrivilegedWithCombiner(PrivilegedAction)
      * @see java.security.DomainCombiner
      */
 
     @CallerSensitive
-    public static native <T> T doPrivileged(PrivilegedAction<T> action);
+    public static <T> T doPrivileged(PrivilegedAction<T> action)
+    {
+        return executePrivileged(action, null, Reflection.getCallerClass());
+    }
 
     /**
      * Performs the specified {@code PrivilegedAction} with privileges
      * enabled. The action is performed with <i>all</i> of the permissions
      * possessed by the caller's protection domain.

@@ -367,12 +378,17 @@
      *
      * @see #doPrivileged(PrivilegedAction)
      * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
      */
     @CallerSensitive
-    public static native <T> T doPrivileged(PrivilegedAction<T> action,
-                                            AccessControlContext context);
+    public static <T> T doPrivileged(PrivilegedAction<T> action,
+                                     AccessControlContext context)
+    {
+        Class <?> caller = Reflection.getCallerClass();
+        context = checkContext(context, caller);
+        return executePrivileged(action, context, caller);
+    }
 
 
     /**
      * Performs the specified {@code PrivilegedAction} with privileges
      * enabled and restricted by the specified

@@ -522,14 +538,24 @@
      * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
      * @see #doPrivilegedWithCombiner(PrivilegedExceptionAction)
      * @see java.security.DomainCombiner
      */
     @CallerSensitive
-    public static native <T> T
+    public static <T> T
         doPrivileged(PrivilegedExceptionAction<T> action)
-        throws PrivilegedActionException;
-
+        throws PrivilegedActionException
+    {
+        AccessControlContext context = null;
+        Class <?> caller = Reflection.getCallerClass();
+        try {
+            return executePrivileged(action, context, caller);
+        } catch (RuntimeException e) {
+            throw e;
+        } catch (Exception e) {
+            throw wrapException(e);
+        }
+    }
 
     /**
      * Performs the specified {@code PrivilegedExceptionAction} with
      * privileges enabled.  The action is performed with <i>all</i> of the
      * permissions possessed by the caller's protection domain.

@@ -609,10 +635,12 @@
     }
     private static AccessControlContext getInnocuousAcc() {
         return AccHolder.innocuousAcc;
     }
 
+    private static native ProtectionDomain getProtectionDomain(final Class <?> caller);
+
     private static ProtectionDomain getCallerPD(final Class <?> caller) {
         ProtectionDomain callerPd = doPrivileged
             (new PrivilegedAction<>() {
             public ProtectionDomain run() {
                 return caller.getProtectionDomain();

@@ -657,15 +685,105 @@
      *
      * @see #doPrivileged(PrivilegedAction)
      * @see #doPrivileged(PrivilegedAction,AccessControlContext)
      */
     @CallerSensitive
-    public static native <T> T
+    public static <T> T
         doPrivileged(PrivilegedExceptionAction<T> action,
                      AccessControlContext context)
-        throws PrivilegedActionException;
+        throws PrivilegedActionException
+    {
+        Class <?> caller = Reflection.getCallerClass();
+        context = checkContext(context, caller);
+        try {
+            return executePrivileged(action, context, caller);
+        } catch (RuntimeException e) {
+            throw e;
+        } catch (Exception e) {
+            throw wrapException(e);
+        }
+    }
+
+    private static AccessControlContext checkContext(AccessControlContext context,
+        Class <?> caller)
+    {
+        // check if caller is authorized to create context
+        if (context != null && !context.isAuthorized() &&
+            context != getInnocuousAcc() &&
+            System.getSecurityManager() != null)
+        {
+            ProtectionDomain callerPD = getProtectionDomain(caller);
+            if (callerPD != null && !callerPD.impliesCreateAccessControlContext()) {
+                return getInnocuousAcc();
+            }
+        }
+        return context;
+    }
+
+    private static boolean isPrivileged() {
+        AccessControlContext ctx = getStackAccessControlContext();
+        return ctx == null || ctx.isPrivileged();
+    }
 
+    @Hidden
+    @ForceInline
+    private static <T> T
+        executePrivileged(PrivilegedAction<T> action,
+                          AccessControlContext context,
+                          Class <?> caller)
+    {
+        assert isPrivileged();
+        T result = action.run();
+        assert isPrivileged();
+
+        // Keep these alive across the run() call so they can be
+        // retrieved by getStackAccessControlContext().
+        Reference.reachabilityFence(context);
+        Reference.reachabilityFence(caller);
+        Reference.reachabilityFence(action);
+        return result;
+    }
+
+    @Hidden
+    @ForceInline
+    private static <T> T
+        executePrivileged(PrivilegedExceptionAction<T> action,
+                          AccessControlContext context,
+                          Class <?> caller)
+        throws Exception
+    {
+        assert isPrivileged();
+        T result = action.run();
+        assert isPrivileged();
+
+        // Keep these alive across the run() call so they can be
+        // retrieved by getStackAccessControlContext().
+        Reference.reachabilityFence(context);
+        Reference.reachabilityFence(caller);
+        Reference.reachabilityFence(action);
+        return result;
+    }
+
+
+    /**
+     * Internal marker for hidden implementation frames.
+     */
+    /*non-public*/
+    @Target(ElementType.METHOD)
+    @Retention(RetentionPolicy.RUNTIME)
+    @interface Hidden {
+    }
+
+
+    @Hidden
+    @ForceInline
+    @ReservedStackAccess
+    private static PrivilegedActionException wrapException(Exception e) {
+        // Nice place for tail-call elimination, if only there was a
+        // version of <init> that returned "this" instead of "void".
+        return new PrivilegedActionException(e);
+    }
 
     /**
      * Performs the specified {@code PrivilegedExceptionAction} with
      * privileges enabled and restricted by the specified
      * {@code AccessControlContext} and with a privilege scope limited by
< prev index next >