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