src/java.base/share/classes/java/security/AccessController.java
branchdlong-java-do-priv-branch
changeset 56897 840ad2a9015a
parent 47216 71c04702a3d5
--- a/src/java.base/share/classes/java/security/AccessController.java	Wed Sep 12 10:27:03 2018 -0700
+++ b/src/java.base/share/classes/java/security/AccessController.java	Wed Sep 19 14:47:37 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * 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
@@ -25,9 +25,13 @@
 
 package java.security;
 
+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
@@ -296,7 +300,10 @@
      */
 
     @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
@@ -369,8 +376,13 @@
      * @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);
+    }
 
 
     /**
@@ -524,10 +536,20 @@
      * @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
@@ -603,6 +625,7 @@
     private static class AccHolder {
         // An AccessControlContext with no granted permissions.
         // Only initialized on demand when getInnocuousAcc() is called.
+// TODO: set isAuthorized
         static final AccessControlContext innocuousAcc =
             new AccessControlContext(new ProtectionDomain[] {
                                      new ProtectionDomain(null, null) });
@@ -611,6 +634,8 @@
         return AccHolder.innocuousAcc;
     }
 
+    private static native ProtectionDomain getProtectionDomain(final Class <?> caller);
+
     private static ProtectionDomain getCallerPD(final Class <?> caller) {
         ProtectionDomain callerPd = doPrivileged
             (new PrivilegedAction<>() {
@@ -659,11 +684,86 @@
      * @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;
+    }
 
+    @ForceInline
+    private static <T> T
+        executePrivileged(PrivilegedAction<T> action,
+                          AccessControlContext context,
+                          Class <?> caller)
+    {
+{
+AccessControlContext ctx = getStackAccessControlContext();
+assert ctx == null || ctx.isPrivileged();
+}
+        T result = action.run();
+{
+AccessControlContext ctx = getStackAccessControlContext();
+assert ctx == null || ctx.isPrivileged();
+}
+        Reference.reachabilityFence(context);
+        Reference.reachabilityFence(caller);
+        Reference.reachabilityFence(action); // FIXME: for debugging
+        return result;
+    }
+
+    @ForceInline
+    private static <T> T
+        executePrivileged(PrivilegedExceptionAction<T> action,
+                          AccessControlContext context,
+                          Class <?> caller)
+        throws Exception
+    {
+{
+AccessControlContext ctx = getStackAccessControlContext();
+assert ctx == null || ctx.isPrivileged();
+}
+        T result = action.run();
+{
+AccessControlContext ctx = getStackAccessControlContext();
+assert ctx == null || ctx.isPrivileged();
+}
+        Reference.reachabilityFence(context);
+        Reference.reachabilityFence(caller);
+        Reference.reachabilityFence(action); // FIXME: for debugging
+        return result;
+    }
+
+    @ForceInline
+    @ReservedStackAccess
+    private static PrivilegedActionException wrapException(Exception e) {
+        return new PrivilegedActionException(e);
+    }
 
     /**
      * Performs the specified {@code PrivilegedExceptionAction} with