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

   1 /*
   2  * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.security;
  27 
  28 import java.lang.annotation.ElementType;
  29 import java.lang.annotation.Retention;
  30 import java.lang.annotation.RetentionPolicy;
  31 import java.lang.annotation.Target;
  32 import java.lang.ref.Reference;
  33 import sun.security.util.Debug;
  34 import jdk.internal.reflect.CallerSensitive;
  35 import jdk.internal.reflect.Reflection;
  36 import jdk.internal.vm.annotation.DontInline;
  37 import jdk.internal.vm.annotation.ForceInline;
  38 import jdk.internal.vm.annotation.ReservedStackAccess;
  39 
  40 /**
  41  * <p> The AccessController class is used for access control operations
  42  * and decisions.
  43  *
  44  * <p> More specifically, the AccessController class is used for
  45  * three purposes:
  46  *
  47  * <ul>
  48  * <li> to decide whether an access to a critical system
  49  * resource is to be allowed or denied, based on the security policy
  50  * currently in effect,
  51  * <li>to mark code as being "privileged", thus affecting subsequent
  52  * access determinations, and
  53  * <li>to obtain a "snapshot" of the current calling context so
  54  * access-control decisions from a different context can be made with
  55  * respect to the saved context. </ul>
  56  *
  57  * <p> The {@link #checkPermission(Permission) checkPermission} method
  58  * determines whether the access request indicated by a specified
  59  * permission should be granted or denied. A sample call appears
  60  * below. In this example, {@code checkPermission} will determine
  61  * whether or not to grant "read" access to the file named "testFile" in
  62  * the "/temp" directory.
  63  *
  64  * <pre>
  65  *
  66  * FilePermission perm = new FilePermission("/temp/testFile", "read");
  67  * AccessController.checkPermission(perm);
  68  *
  69  * </pre>
  70  *
  71  * <p> If a requested access is allowed,
  72  * {@code checkPermission} returns quietly. If denied, an
  73  * AccessControlException is
  74  * thrown. AccessControlException can also be thrown if the requested
  75  * permission is of an incorrect type or contains an invalid value.
  76  * Such information is given whenever possible.
  77  *
  78  * Suppose the current thread traversed m callers, in the order of caller 1
  79  * to caller 2 to caller m. Then caller m invoked the
  80  * {@code checkPermission} method.
  81  * The {@code checkPermission} method determines whether access
  82  * is granted or denied based on the following algorithm:
  83  *
  84  *  <pre> {@code
  85  * for (int i = m; i > 0; i--) {
  86  *
  87  *     if (caller i's domain does not have the permission)
  88  *         throw AccessControlException
  89  *
  90  *     else if (caller i is marked as privileged) {
  91  *         if (a context was specified in the call to doPrivileged)
  92  *             context.checkPermission(permission)
  93  *         if (limited permissions were specified in the call to doPrivileged) {
  94  *             for (each limited permission) {
  95  *                 if (the limited permission implies the requested permission)
  96  *                     return;
  97  *             }
  98  *         } else
  99  *             return;
 100  *     }
 101  * }
 102  *
 103  * // Next, check the context inherited when the thread was created.
 104  * // Whenever a new thread is created, the AccessControlContext at
 105  * // that time is stored and associated with the new thread, as the
 106  * // "inherited" context.
 107  *
 108  * inheritedContext.checkPermission(permission);
 109  * }</pre>
 110  *
 111  * <p> A caller can be marked as being "privileged"
 112  * (see {@link #doPrivileged(PrivilegedAction) doPrivileged} and below).
 113  * When making access control decisions, the {@code checkPermission}
 114  * method stops checking if it reaches a caller that
 115  * was marked as "privileged" via a {@code doPrivileged}
 116  * call without a context argument (see below for information about a
 117  * context argument). If that caller's domain has the
 118  * specified permission and at least one limiting permission argument (if any)
 119  * implies the requested permission, no further checking is done and
 120  * {@code checkPermission}
 121  * returns quietly, indicating that the requested access is allowed.
 122  * If that domain does not have the specified permission, an exception
 123  * is thrown, as usual. If the caller's domain had the specified permission
 124  * but it was not implied by any limiting permission arguments given in the call
 125  * to {@code doPrivileged} then the permission checking continues
 126  * until there are no more callers or another {@code doPrivileged}
 127  * call matches the requested permission and returns normally.
 128  *
 129  * <p> The normal use of the "privileged" feature is as follows. If you
 130  * don't need to return a value from within the "privileged" block, do
 131  * the following:
 132  *
 133  *  <pre> {@code
 134  * somemethod() {
 135  *     ...normal code here...
 136  *     AccessController.doPrivileged(new PrivilegedAction<Void>() {
 137  *         public Void run() {
 138  *             // privileged code goes here, for example:
 139  *             System.loadLibrary("awt");
 140  *             return null; // nothing to return
 141  *         }
 142  *     });
 143  *     ...normal code here...
 144  * }}</pre>
 145  *
 146  * <p>
 147  * PrivilegedAction is an interface with a single method, named
 148  * {@code run}.
 149  * The above example shows creation of an implementation
 150  * of that interface; a concrete implementation of the
 151  * {@code run} method is supplied.
 152  * When the call to {@code doPrivileged} is made, an
 153  * instance of the PrivilegedAction implementation is passed
 154  * to it. The {@code doPrivileged} method calls the
 155  * {@code run} method from the PrivilegedAction
 156  * implementation after enabling privileges, and returns the
 157  * {@code run} method's return value as the
 158  * {@code doPrivileged} return value (which is
 159  * ignored in this example).
 160  *
 161  * <p> If you need to return a value, you can do something like the following:
 162  *
 163  *  <pre> {@code
 164  * somemethod() {
 165  *     ...normal code here...
 166  *     String user = AccessController.doPrivileged(
 167  *         new PrivilegedAction<String>() {
 168  *         public String run() {
 169  *             return System.getProperty("user.name");
 170  *             }
 171  *         });
 172  *     ...normal code here...
 173  * }}</pre>
 174  *
 175  * <p>If the action performed in your {@code run} method could
 176  * throw a "checked" exception (those listed in the {@code throws} clause
 177  * of a method), then you need to use the
 178  * {@code PrivilegedExceptionAction} interface instead of the
 179  * {@code PrivilegedAction} interface:
 180  *
 181  *  <pre> {@code
 182  * somemethod() throws FileNotFoundException {
 183  *     ...normal code here...
 184  *     try {
 185  *         FileInputStream fis = AccessController.doPrivileged(
 186  *         new PrivilegedExceptionAction<FileInputStream>() {
 187  *             public FileInputStream run() throws FileNotFoundException {
 188  *                 return new FileInputStream("someFile");
 189  *             }
 190  *         });
 191  *     } catch (PrivilegedActionException e) {
 192  *         // e.getException() should be an instance of FileNotFoundException,
 193  *         // as only "checked" exceptions will be "wrapped" in a
 194  *         // PrivilegedActionException.
 195  *         throw (FileNotFoundException) e.getException();
 196  *     }
 197  *     ...normal code here...
 198  *  }}</pre>
 199  *
 200  * <p> Be *very* careful in your use of the "privileged" construct, and
 201  * always remember to make the privileged code section as small as possible.
 202  * You can pass {@code Permission} arguments to further limit the
 203  * scope of the "privilege" (see below).
 204  *
 205  *
 206  * <p> Note that {@code checkPermission} always performs security checks
 207  * within the context of the currently executing thread.
 208  * Sometimes a security check that should be made within a given context
 209  * will actually need to be done from within a
 210  * <i>different</i> context (for example, from within a worker thread).
 211  * The {@link #getContext() getContext} method and
 212  * AccessControlContext class are provided
 213  * for this situation. The {@code getContext} method takes a "snapshot"
 214  * of the current calling context, and places
 215  * it in an AccessControlContext object, which it returns. A sample call is
 216  * the following:
 217  *
 218  * <pre>
 219  *
 220  * AccessControlContext acc = AccessController.getContext()
 221  *
 222  * </pre>
 223  *
 224  * <p>
 225  * AccessControlContext itself has a {@code checkPermission} method
 226  * that makes access decisions based on the context <i>it</i> encapsulates,
 227  * rather than that of the current execution thread.
 228  * Code within a different context can thus call that method on the
 229  * previously-saved AccessControlContext object. A sample call is the
 230  * following:
 231  *
 232  * <pre>
 233  *
 234  * acc.checkPermission(permission)
 235  *
 236  * </pre>
 237  *
 238  * <p> There are also times where you don't know a priori which permissions
 239  * to check the context against. In these cases you can use the
 240  * doPrivileged method that takes a context. You can also limit the scope
 241  * of the privileged code by passing additional {@code Permission}
 242  * parameters.
 243  *
 244  *  <pre> {@code
 245  * somemethod() {
 246  *     AccessController.doPrivileged(new PrivilegedAction<Object>() {
 247  *         public Object run() {
 248  *             // Code goes here. Any permission checks within this
 249  *             // run method will require that the intersection of the
 250  *             // caller's protection domain and the snapshot's
 251  *             // context have the desired permission. If a requested
 252  *             // permission is not implied by the limiting FilePermission
 253  *             // argument then checking of the thread continues beyond the
 254  *             // caller of doPrivileged.
 255  *         }
 256  *     }, acc, new FilePermission("/temp/*", read));
 257  *     ...normal code here...
 258  * }}</pre>
 259  * <p> Passing a limiting {@code Permission} argument of an instance of
 260  * {@code AllPermission} is equivalent to calling the equivalent
 261  * {@code doPrivileged} method without limiting {@code Permission}
 262  * arguments. Passing a zero length array of {@code Permission} disables
 263  * the code privileges so that checking always continues beyond the caller of
 264  * that {@code doPrivileged} method.
 265  *
 266  * @see AccessControlContext
 267  *
 268  * @author Li Gong
 269  * @author Roland Schemers
 270  * @since 1.2
 271  */
 272 
 273 public final class AccessController {
 274 
 275     /**
 276      * Don't allow anyone to instantiate an AccessController
 277      */
 278     private AccessController() { }
 279 
 280     /**
 281      * Performs the specified {@code PrivilegedAction} with privileges
 282      * enabled. The action is performed with <i>all</i> of the permissions
 283      * possessed by the caller's protection domain.
 284      *
 285      * <p> If the action's {@code run} method throws an (unchecked)
 286      * exception, it will propagate through this method.
 287      *
 288      * <p> Note that any DomainCombiner associated with the current
 289      * AccessControlContext will be ignored while the action is performed.
 290      *
 291      * @param <T> the type of the value returned by the PrivilegedAction's
 292      *                  {@code run} method.
 293      *
 294      * @param action the action to be performed.
 295      *
 296      * @return the value returned by the action's {@code run} method.
 297      *
 298      * @exception NullPointerException if the action is {@code null}
 299      *
 300      * @see #doPrivileged(PrivilegedAction,AccessControlContext)
 301      * @see #doPrivileged(PrivilegedExceptionAction)
 302      * @see #doPrivilegedWithCombiner(PrivilegedAction)
 303      * @see java.security.DomainCombiner
 304      */
 305 
 306     @CallerSensitive
 307     public static <T> T doPrivileged(PrivilegedAction<T> action)
 308     {
 309         return executePrivileged(action, null, Reflection.getCallerClass());
 310     }
 311 
 312     /**
 313      * Performs the specified {@code PrivilegedAction} with privileges
 314      * enabled. The action is performed with <i>all</i> of the permissions
 315      * possessed by the caller's protection domain.
 316      *
 317      * <p> If the action's {@code run} method throws an (unchecked)
 318      * exception, it will propagate through this method.
 319      *
 320      * <p> This method preserves the current AccessControlContext's
 321      * DomainCombiner (which may be null) while the action is performed.
 322      *
 323      * @param <T> the type of the value returned by the PrivilegedAction's
 324      *                  {@code run} method.
 325      *
 326      * @param action the action to be performed.
 327      *
 328      * @return the value returned by the action's {@code run} method.
 329      *
 330      * @exception NullPointerException if the action is {@code null}
 331      *
 332      * @see #doPrivileged(PrivilegedAction)
 333      * @see java.security.DomainCombiner
 334      *
 335      * @since 1.6
 336      */
 337     @CallerSensitive
 338     public static <T> T doPrivilegedWithCombiner(PrivilegedAction<T> action) {
 339         AccessControlContext acc = getStackAccessControlContext();
 340         if (acc == null) {
 341             return AccessController.doPrivileged(action);
 342         }
 343         DomainCombiner dc = acc.getAssignedCombiner();
 344         return AccessController.doPrivileged(action,
 345                                              preserveCombiner(dc, Reflection.getCallerClass()));
 346     }
 347 
 348 
 349     /**
 350      * Performs the specified {@code PrivilegedAction} with privileges
 351      * enabled and restricted by the specified {@code AccessControlContext}.
 352      * The action is performed with the intersection of the permissions
 353      * possessed by the caller's protection domain, and those possessed
 354      * by the domains represented by the specified {@code AccessControlContext}.
 355      * <p>
 356      * If the action's {@code run} method throws an (unchecked) exception,
 357      * it will propagate through this method.
 358      * <p>
 359      * If a security manager is installed and the specified
 360      * {@code AccessControlContext} was not created by system code and the
 361      * caller's {@code ProtectionDomain} has not been granted the
 362      * {@literal "createAccessControlContext"}
 363      * {@link java.security.SecurityPermission}, then the action is performed
 364      * with no permissions.
 365      *
 366      * @param <T> the type of the value returned by the PrivilegedAction's
 367      *                  {@code run} method.
 368      * @param action the action to be performed.
 369      * @param context an <i>access control context</i>
 370      *                representing the restriction to be applied to the
 371      *                caller's domain's privileges before performing
 372      *                the specified action.  If the context is
 373      *                {@code null}, then no additional restriction is applied.
 374      *
 375      * @return the value returned by the action's {@code run} method.
 376      *
 377      * @exception NullPointerException if the action is {@code null}
 378      *
 379      * @see #doPrivileged(PrivilegedAction)
 380      * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
 381      */
 382     @CallerSensitive
 383     public static <T> T doPrivileged(PrivilegedAction<T> action,
 384                                      AccessControlContext context)
 385     {
 386         Class <?> caller = Reflection.getCallerClass();
 387         context = checkContext(context, caller);
 388         return executePrivileged(action, context, caller);
 389     }
 390 
 391 
 392     /**
 393      * Performs the specified {@code PrivilegedAction} with privileges
 394      * enabled and restricted by the specified
 395      * {@code AccessControlContext} and with a privilege scope limited
 396      * by specified {@code Permission} arguments.
 397      *
 398      * The action is performed with the intersection of the permissions
 399      * possessed by the caller's protection domain, and those possessed
 400      * by the domains represented by the specified
 401      * {@code AccessControlContext}.
 402      * <p>
 403      * If the action's {@code run} method throws an (unchecked) exception,
 404      * it will propagate through this method.
 405      * <p>
 406      * If a security manager is installed and the specified
 407      * {@code AccessControlContext} was not created by system code and the
 408      * caller's {@code ProtectionDomain} has not been granted the
 409      * {@literal "createAccessControlContext"}
 410      * {@link java.security.SecurityPermission}, then the action is performed
 411      * with no permissions.
 412      *
 413      * @param <T> the type of the value returned by the PrivilegedAction's
 414      *                  {@code run} method.
 415      * @param action the action to be performed.
 416      * @param context an <i>access control context</i>
 417      *                representing the restriction to be applied to the
 418      *                caller's domain's privileges before performing
 419      *                the specified action.  If the context is
 420      *                {@code null},
 421      *                then no additional restriction is applied.
 422      * @param perms the {@code Permission} arguments which limit the
 423      *              scope of the caller's privileges. The number of arguments
 424      *              is variable.
 425      *
 426      * @return the value returned by the action's {@code run} method.
 427      *
 428      * @throws NullPointerException if action or perms or any element of
 429      *         perms is {@code null}
 430      *
 431      * @see #doPrivileged(PrivilegedAction)
 432      * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
 433      *
 434      * @since 1.8
 435      */
 436     @CallerSensitive
 437     public static <T> T doPrivileged(PrivilegedAction<T> action,
 438         AccessControlContext context, Permission... perms) {
 439 
 440         AccessControlContext parent = getContext();
 441         if (perms == null) {
 442             throw new NullPointerException("null permissions parameter");
 443         }
 444         Class <?> caller = Reflection.getCallerClass();
 445         return AccessController.doPrivileged(action, createWrapper(null,
 446             caller, parent, context, perms));
 447     }
 448 
 449 
 450     /**
 451      * Performs the specified {@code PrivilegedAction} with privileges
 452      * enabled and restricted by the specified
 453      * {@code AccessControlContext} and with a privilege scope limited
 454      * by specified {@code Permission} arguments.
 455      *
 456      * The action is performed with the intersection of the permissions
 457      * possessed by the caller's protection domain, and those possessed
 458      * by the domains represented by the specified
 459      * {@code AccessControlContext}.
 460      * <p>
 461      * If the action's {@code run} method throws an (unchecked) exception,
 462      * it will propagate through this method.
 463      *
 464      * <p> This method preserves the current AccessControlContext's
 465      * DomainCombiner (which may be null) while the action is performed.
 466      * <p>
 467      * If a security manager is installed and the specified
 468      * {@code AccessControlContext} was not created by system code and the
 469      * caller's {@code ProtectionDomain} has not been granted the
 470      * {@literal "createAccessControlContext"}
 471      * {@link java.security.SecurityPermission}, then the action is performed
 472      * with no permissions.
 473      *
 474      * @param <T> the type of the value returned by the PrivilegedAction's
 475      *                  {@code run} method.
 476      * @param action the action to be performed.
 477      * @param context an <i>access control context</i>
 478      *                representing the restriction to be applied to the
 479      *                caller's domain's privileges before performing
 480      *                the specified action.  If the context is
 481      *                {@code null},
 482      *                then no additional restriction is applied.
 483      * @param perms the {@code Permission} arguments which limit the
 484      *              scope of the caller's privileges. The number of arguments
 485      *              is variable.
 486      *
 487      * @return the value returned by the action's {@code run} method.
 488      *
 489      * @throws NullPointerException if action or perms or any element of
 490      *         perms is {@code null}
 491      *
 492      * @see #doPrivileged(PrivilegedAction)
 493      * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
 494      * @see java.security.DomainCombiner
 495      *
 496      * @since 1.8
 497      */
 498     @CallerSensitive
 499     public static <T> T doPrivilegedWithCombiner(PrivilegedAction<T> action,
 500         AccessControlContext context, Permission... perms) {
 501 
 502         AccessControlContext parent = getContext();
 503         DomainCombiner dc = parent.getCombiner();
 504         if (dc == null && context != null) {
 505             dc = context.getCombiner();
 506         }
 507         if (perms == null) {
 508             throw new NullPointerException("null permissions parameter");
 509         }
 510         Class <?> caller = Reflection.getCallerClass();
 511         return AccessController.doPrivileged(action, createWrapper(dc, caller,
 512             parent, context, perms));
 513     }
 514 
 515     /**
 516      * Performs the specified {@code PrivilegedExceptionAction} with
 517      * privileges enabled.  The action is performed with <i>all</i> of the
 518      * permissions possessed by the caller's protection domain.
 519      *
 520      * <p> If the action's {@code run} method throws an <i>unchecked</i>
 521      * exception, it will propagate through this method.
 522      *
 523      * <p> Note that any DomainCombiner associated with the current
 524      * AccessControlContext will be ignored while the action is performed.
 525      *
 526      * @param <T> the type of the value returned by the
 527      *                  PrivilegedExceptionAction's {@code run} method.
 528      *
 529      * @param action the action to be performed
 530      *
 531      * @return the value returned by the action's {@code run} method
 532      *
 533      * @exception PrivilegedActionException if the specified action's
 534      *         {@code run} method threw a <i>checked</i> exception
 535      * @exception NullPointerException if the action is {@code null}
 536      *
 537      * @see #doPrivileged(PrivilegedAction)
 538      * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
 539      * @see #doPrivilegedWithCombiner(PrivilegedExceptionAction)
 540      * @see java.security.DomainCombiner
 541      */
 542     @CallerSensitive
 543     public static <T> T
 544         doPrivileged(PrivilegedExceptionAction<T> action)
 545         throws PrivilegedActionException
 546     {
 547         AccessControlContext context = null;
 548         Class <?> caller = Reflection.getCallerClass();
 549         try {
 550             return executePrivileged(action, context, caller);
 551         } catch (RuntimeException e) {
 552             throw e;
 553         } catch (Exception e) {
 554             throw wrapException(e);
 555         }
 556     }
 557 
 558     /**
 559      * Performs the specified {@code PrivilegedExceptionAction} with
 560      * privileges enabled.  The action is performed with <i>all</i> of the
 561      * permissions possessed by the caller's protection domain.
 562      *
 563      * <p> If the action's {@code run} method throws an <i>unchecked</i>
 564      * exception, it will propagate through this method.
 565      *
 566      * <p> This method preserves the current AccessControlContext's
 567      * DomainCombiner (which may be null) while the action is performed.
 568      *
 569      * @param <T> the type of the value returned by the
 570      *                  PrivilegedExceptionAction's {@code run} method.
 571      *
 572      * @param action the action to be performed.
 573      *
 574      * @return the value returned by the action's {@code run} method
 575      *
 576      * @exception PrivilegedActionException if the specified action's
 577      *         {@code run} method threw a <i>checked</i> exception
 578      * @exception NullPointerException if the action is {@code null}
 579      *
 580      * @see #doPrivileged(PrivilegedAction)
 581      * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
 582      * @see java.security.DomainCombiner
 583      *
 584      * @since 1.6
 585      */
 586     @CallerSensitive
 587     public static <T> T doPrivilegedWithCombiner(PrivilegedExceptionAction<T> action)
 588         throws PrivilegedActionException
 589     {
 590         AccessControlContext acc = getStackAccessControlContext();
 591         if (acc == null) {
 592             return AccessController.doPrivileged(action);
 593         }
 594         DomainCombiner dc = acc.getAssignedCombiner();
 595         return AccessController.doPrivileged(action,
 596                                              preserveCombiner(dc, Reflection.getCallerClass()));
 597     }
 598 
 599     /**
 600      * preserve the combiner across the doPrivileged call
 601      */
 602     private static AccessControlContext preserveCombiner(DomainCombiner combiner,
 603                                                          Class<?> caller)
 604     {
 605         return createWrapper(combiner, caller, null, null, null);
 606     }
 607 
 608     /**
 609      * Create a wrapper to contain the limited privilege scope data.
 610      */
 611     private static AccessControlContext
 612         createWrapper(DomainCombiner combiner, Class<?> caller,
 613                       AccessControlContext parent, AccessControlContext context,
 614                       Permission[] perms)
 615     {
 616         ProtectionDomain callerPD = getCallerPD(caller);
 617         // check if caller is authorized to create context
 618         if (context != null && !context.isAuthorized() &&
 619             System.getSecurityManager() != null &&
 620             !callerPD.impliesCreateAccessControlContext())
 621         {
 622             return getInnocuousAcc();
 623         } else {
 624             return new AccessControlContext(callerPD, combiner, parent,
 625                                             context, perms);
 626         }
 627     }
 628 
 629     private static class AccHolder {
 630         // An AccessControlContext with no granted permissions.
 631         // Only initialized on demand when getInnocuousAcc() is called.
 632         static final AccessControlContext innocuousAcc =
 633             new AccessControlContext(new ProtectionDomain[] {
 634                                      new ProtectionDomain(null, null) });
 635     }
 636     private static AccessControlContext getInnocuousAcc() {
 637         return AccHolder.innocuousAcc;
 638     }
 639 
 640     private static native ProtectionDomain getProtectionDomain(final Class <?> caller);
 641 
 642     private static ProtectionDomain getCallerPD(final Class <?> caller) {
 643         ProtectionDomain callerPd = doPrivileged
 644             (new PrivilegedAction<>() {
 645             public ProtectionDomain run() {
 646                 return caller.getProtectionDomain();
 647             }
 648         });
 649 
 650         return callerPd;
 651     }
 652 
 653     /**
 654      * Performs the specified {@code PrivilegedExceptionAction} with
 655      * privileges enabled and restricted by the specified
 656      * {@code AccessControlContext}.  The action is performed with the
 657      * intersection of the permissions possessed by the caller's
 658      * protection domain, and those possessed by the domains represented by the
 659      * specified {@code AccessControlContext}.
 660      * <p>
 661      * If the action's {@code run} method throws an <i>unchecked</i>
 662      * exception, it will propagate through this method.
 663      * <p>
 664      * If a security manager is installed and the specified
 665      * {@code AccessControlContext} was not created by system code and the
 666      * caller's {@code ProtectionDomain} has not been granted the
 667      * {@literal "createAccessControlContext"}
 668      * {@link java.security.SecurityPermission}, then the action is performed
 669      * with no permissions.
 670      *
 671      * @param <T> the type of the value returned by the
 672      *                  PrivilegedExceptionAction's {@code run} method.
 673      * @param action the action to be performed
 674      * @param context an <i>access control context</i>
 675      *                representing the restriction to be applied to the
 676      *                caller's domain's privileges before performing
 677      *                the specified action.  If the context is
 678      *                {@code null}, then no additional restriction is applied.
 679      *
 680      * @return the value returned by the action's {@code run} method
 681      *
 682      * @exception PrivilegedActionException if the specified action's
 683      *         {@code run} method threw a <i>checked</i> exception
 684      * @exception NullPointerException if the action is {@code null}
 685      *
 686      * @see #doPrivileged(PrivilegedAction)
 687      * @see #doPrivileged(PrivilegedAction,AccessControlContext)
 688      */
 689     @CallerSensitive
 690     public static <T> T
 691         doPrivileged(PrivilegedExceptionAction<T> action,
 692                      AccessControlContext context)
 693         throws PrivilegedActionException
 694     {
 695         Class <?> caller = Reflection.getCallerClass();
 696         context = checkContext(context, caller);
 697         try {
 698             return executePrivileged(action, context, caller);
 699         } catch (RuntimeException e) {
 700             throw e;
 701         } catch (Exception e) {
 702             throw wrapException(e);
 703         }
 704     }
 705 
 706     private static AccessControlContext checkContext(AccessControlContext context,
 707         Class <?> caller)
 708     {
 709         // check if caller is authorized to create context
 710         if (context != null && !context.isAuthorized() &&
 711             context != getInnocuousAcc() &&
 712             System.getSecurityManager() != null)
 713         {
 714             ProtectionDomain callerPD = getProtectionDomain(caller);
 715             if (callerPD != null && !callerPD.impliesCreateAccessControlContext()) {
 716                 return getInnocuousAcc();
 717             }
 718         }
 719         return context;
 720     }
 721 
 722     private static boolean isPrivileged() {
 723         AccessControlContext ctx = getStackAccessControlContext();
 724         return ctx == null || ctx.isPrivileged();
 725     }
 726 
 727     @Hidden
 728     @ForceInline
 729     private static <T> T
 730         executePrivileged(PrivilegedAction<T> action,
 731                           AccessControlContext context,
 732                           Class <?> caller)
 733     {
 734         assert isPrivileged();
 735         T result = action.run();
 736         assert isPrivileged();
 737 
 738         // Keep these alive across the run() call so they can be
 739         // retrieved by getStackAccessControlContext().
 740         Reference.reachabilityFence(context);
 741         Reference.reachabilityFence(caller);
 742         Reference.reachabilityFence(action);
 743         return result;
 744     }
 745 
 746     @Hidden
 747     @ForceInline
 748     private static <T> T
 749         executePrivileged(PrivilegedExceptionAction<T> action,
 750                           AccessControlContext context,
 751                           Class <?> caller)
 752         throws Exception
 753     {
 754         assert isPrivileged();
 755         T result = action.run();
 756         assert isPrivileged();
 757 
 758         // Keep these alive across the run() call so they can be
 759         // retrieved by getStackAccessControlContext().
 760         Reference.reachabilityFence(context);
 761         Reference.reachabilityFence(caller);
 762         Reference.reachabilityFence(action);
 763         return result;
 764     }
 765 
 766 
 767     /**
 768      * Internal marker for hidden implementation frames.
 769      */
 770     /*non-public*/
 771     @Target(ElementType.METHOD)
 772     @Retention(RetentionPolicy.RUNTIME)
 773     @interface Hidden {
 774     }
 775 
 776 
 777     @Hidden
 778     @ForceInline
 779     @ReservedStackAccess
 780     private static PrivilegedActionException wrapException(Exception e) {
 781         // Nice place for tail-call elimination, if only there was a
 782         // version of <init> that returned "this" instead of "void".
 783         return new PrivilegedActionException(e);
 784     }
 785 
 786     /**
 787      * Performs the specified {@code PrivilegedExceptionAction} with
 788      * privileges enabled and restricted by the specified
 789      * {@code AccessControlContext} and with a privilege scope limited by
 790      * specified {@code Permission} arguments.
 791      *
 792      * The action is performed with the intersection of the permissions
 793      * possessed by the caller's protection domain, and those possessed
 794      * by the domains represented by the specified
 795      * {@code AccessControlContext}.
 796      * <p>
 797      * If the action's {@code run} method throws an (unchecked) exception,
 798      * it will propagate through this method.
 799      * <p>
 800      * If a security manager is installed and the specified
 801      * {@code AccessControlContext} was not created by system code and the
 802      * caller's {@code ProtectionDomain} has not been granted the
 803      * {@literal "createAccessControlContext"}
 804      * {@link java.security.SecurityPermission}, then the action is performed
 805      * with no permissions.
 806      *
 807      * @param <T> the type of the value returned by the
 808      *                  PrivilegedExceptionAction's {@code run} method.
 809      * @param action the action to be performed.
 810      * @param context an <i>access control context</i>
 811      *                representing the restriction to be applied to the
 812      *                caller's domain's privileges before performing
 813      *                the specified action.  If the context is
 814      *                {@code null},
 815      *                then no additional restriction is applied.
 816      * @param perms the {@code Permission} arguments which limit the
 817      *              scope of the caller's privileges. The number of arguments
 818      *              is variable.
 819      *
 820      * @return the value returned by the action's {@code run} method.
 821      *
 822      * @throws PrivilegedActionException if the specified action's
 823      *         {@code run} method threw a <i>checked</i> exception
 824      * @throws NullPointerException if action or perms or any element of
 825      *         perms is {@code null}
 826      *
 827      * @see #doPrivileged(PrivilegedAction)
 828      * @see #doPrivileged(PrivilegedAction,AccessControlContext)
 829      *
 830      * @since 1.8
 831      */
 832     @CallerSensitive
 833     public static <T> T doPrivileged(PrivilegedExceptionAction<T> action,
 834                                      AccessControlContext context, Permission... perms)
 835         throws PrivilegedActionException
 836     {
 837         AccessControlContext parent = getContext();
 838         if (perms == null) {
 839             throw new NullPointerException("null permissions parameter");
 840         }
 841         Class <?> caller = Reflection.getCallerClass();
 842         return AccessController.doPrivileged(action, createWrapper(null, caller, parent, context, perms));
 843     }
 844 
 845 
 846     /**
 847      * Performs the specified {@code PrivilegedExceptionAction} with
 848      * privileges enabled and restricted by the specified
 849      * {@code AccessControlContext} and with a privilege scope limited by
 850      * specified {@code Permission} arguments.
 851      *
 852      * The action is performed with the intersection of the permissions
 853      * possessed by the caller's protection domain, and those possessed
 854      * by the domains represented by the specified
 855      * {@code AccessControlContext}.
 856      * <p>
 857      * If the action's {@code run} method throws an (unchecked) exception,
 858      * it will propagate through this method.
 859      *
 860      * <p> This method preserves the current AccessControlContext's
 861      * DomainCombiner (which may be null) while the action is performed.
 862      * <p>
 863      * If a security manager is installed and the specified
 864      * {@code AccessControlContext} was not created by system code and the
 865      * caller's {@code ProtectionDomain} has not been granted the
 866      * {@literal "createAccessControlContext"}
 867      * {@link java.security.SecurityPermission}, then the action is performed
 868      * with no permissions.
 869      *
 870      * @param <T> the type of the value returned by the
 871      *                  PrivilegedExceptionAction's {@code run} method.
 872      * @param action the action to be performed.
 873      * @param context an <i>access control context</i>
 874      *                representing the restriction to be applied to the
 875      *                caller's domain's privileges before performing
 876      *                the specified action.  If the context is
 877      *                {@code null},
 878      *                then no additional restriction is applied.
 879      * @param perms the {@code Permission} arguments which limit the
 880      *              scope of the caller's privileges. The number of arguments
 881      *              is variable.
 882      *
 883      * @return the value returned by the action's {@code run} method.
 884      *
 885      * @throws PrivilegedActionException if the specified action's
 886      *         {@code run} method threw a <i>checked</i> exception
 887      * @throws NullPointerException if action or perms or any element of
 888      *         perms is {@code null}
 889      *
 890      * @see #doPrivileged(PrivilegedAction)
 891      * @see #doPrivileged(PrivilegedAction,AccessControlContext)
 892      * @see java.security.DomainCombiner
 893      *
 894      * @since 1.8
 895      */
 896     @CallerSensitive
 897     public static <T> T doPrivilegedWithCombiner(PrivilegedExceptionAction<T> action,
 898                                                  AccessControlContext context,
 899                                                  Permission... perms)
 900         throws PrivilegedActionException
 901     {
 902         AccessControlContext parent = getContext();
 903         DomainCombiner dc = parent.getCombiner();
 904         if (dc == null && context != null) {
 905             dc = context.getCombiner();
 906         }
 907         if (perms == null) {
 908             throw new NullPointerException("null permissions parameter");
 909         }
 910         Class <?> caller = Reflection.getCallerClass();
 911         return AccessController.doPrivileged(action, createWrapper(dc, caller,
 912             parent, context, perms));
 913     }
 914 
 915     /**
 916      * Returns the AccessControl context. i.e., it gets
 917      * the protection domains of all the callers on the stack,
 918      * starting at the first class with a non-null
 919      * ProtectionDomain.
 920      *
 921      * @return the access control context based on the current stack or
 922      *         null if there was only privileged system code.
 923      */
 924 
 925     private static native AccessControlContext getStackAccessControlContext();
 926 
 927 
 928     /**
 929      * Returns the "inherited" AccessControl context. This is the context
 930      * that existed when the thread was created. Package private so
 931      * AccessControlContext can use it.
 932      */
 933 
 934     static native AccessControlContext getInheritedAccessControlContext();
 935 
 936     /**
 937      * This method takes a "snapshot" of the current calling context, which
 938      * includes the current Thread's inherited AccessControlContext and any
 939      * limited privilege scope, and places it in an AccessControlContext object.
 940      * This context may then be checked at a later point, possibly in another thread.
 941      *
 942      * @see AccessControlContext
 943      *
 944      * @return the AccessControlContext based on the current context.
 945      */
 946 
 947     public static AccessControlContext getContext()
 948     {
 949         AccessControlContext acc = getStackAccessControlContext();
 950         if (acc == null) {
 951             // all we had was privileged system code. We don't want
 952             // to return null though, so we construct a real ACC.
 953             return new AccessControlContext(null, true);
 954         } else {
 955             return acc.optimize();
 956         }
 957     }
 958 
 959     /**
 960      * Determines whether the access request indicated by the
 961      * specified permission should be allowed or denied, based on
 962      * the current AccessControlContext and security policy.
 963      * This method quietly returns if the access request
 964      * is permitted, or throws an AccessControlException otherwise. The
 965      * getPermission method of the AccessControlException returns the
 966      * {@code perm} Permission object instance.
 967      *
 968      * @param perm the requested permission.
 969      *
 970      * @exception AccessControlException if the specified permission
 971      *            is not permitted, based on the current security policy.
 972      * @exception NullPointerException if the specified permission
 973      *            is {@code null} and is checked based on the
 974      *            security policy currently in effect.
 975      */
 976 
 977     public static void checkPermission(Permission perm)
 978         throws AccessControlException
 979     {
 980         //System.err.println("checkPermission "+perm);
 981         //Thread.currentThread().dumpStack();
 982 
 983         if (perm == null) {
 984             throw new NullPointerException("permission can't be null");
 985         }
 986 
 987         AccessControlContext stack = getStackAccessControlContext();
 988         // if context is null, we had privileged system code on the stack.
 989         if (stack == null) {
 990             Debug debug = AccessControlContext.getDebug();
 991             boolean dumpDebug = false;
 992             if (debug != null) {
 993                 dumpDebug = !Debug.isOn("codebase=");
 994                 dumpDebug &= !Debug.isOn("permission=") ||
 995                     Debug.isOn("permission=" + perm.getClass().getCanonicalName());
 996             }
 997 
 998             if (dumpDebug && Debug.isOn("stack")) {
 999                 Thread.dumpStack();
1000             }
1001 
1002             if (dumpDebug && Debug.isOn("domain")) {
1003                 debug.println("domain (context is null)");
1004             }
1005 
1006             if (dumpDebug) {
1007                 debug.println("access allowed "+perm);
1008             }
1009             return;
1010         }
1011 
1012         AccessControlContext acc = stack.optimize();
1013         acc.checkPermission(perm);
1014     }
1015 }
--- EOF ---