Path: blob/master/src/java.base/share/classes/java/security/AccessController.java
41152 views
/*1* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package java.security;2627import java.lang.annotation.ElementType;28import java.lang.annotation.Retention;29import java.lang.annotation.RetentionPolicy;30import java.lang.annotation.Target;31import java.lang.ref.Reference;3233import jdk.internal.vm.annotation.Hidden;34import sun.security.util.Debug;35import sun.security.util.SecurityConstants;36import jdk.internal.reflect.CallerSensitive;37import jdk.internal.reflect.Reflection;38import jdk.internal.vm.annotation.DontInline;39import jdk.internal.vm.annotation.ForceInline;40import jdk.internal.vm.annotation.ReservedStackAccess;4142/**43* <p> The AccessController class is used for access control operations44* and decisions.45*46* <p> More specifically, the AccessController class is used for47* three purposes:48*49* <ul>50* <li> to decide whether an access to a critical system51* resource is to be allowed or denied, based on the security policy52* currently in effect,53* <li>to mark code as being "privileged", thus affecting subsequent54* access determinations, and55* <li>to obtain a "snapshot" of the current calling context so56* access-control decisions from a different context can be made with57* respect to the saved context. </ul>58*59* <p> The {@link #checkPermission(Permission) checkPermission} method60* determines whether the access request indicated by a specified61* permission should be granted or denied. A sample call appears62* below. In this example, {@code checkPermission} will determine63* whether or not to grant "read" access to the file named "testFile" in64* the "/temp" directory.65*66* <pre>67*68* FilePermission perm = new FilePermission("/temp/testFile", "read");69* AccessController.checkPermission(perm);70*71* </pre>72*73* <p> If a requested access is allowed,74* {@code checkPermission} returns quietly. If denied, an75* AccessControlException is76* thrown. AccessControlException can also be thrown if the requested77* permission is of an incorrect type or contains an invalid value.78* Such information is given whenever possible.79*80* Suppose the current thread traversed m callers, in the order of caller 181* to caller 2 to caller m. Then caller m invoked the82* {@code checkPermission} method.83* The {@code checkPermission} method determines whether access84* is granted or denied based on the following algorithm:85*86* <pre> {@code87* for (int i = m; i > 0; i--) {88*89* if (caller i's domain does not have the permission)90* throw AccessControlException91*92* else if (caller i is marked as privileged) {93* if (a context was specified in the call to doPrivileged)94* context.checkPermission(permission)95* if (limited permissions were specified in the call to doPrivileged) {96* for (each limited permission) {97* if (the limited permission implies the requested permission)98* return;99* }100* } else101* return;102* }103* }104*105* // Next, check the context inherited when the thread was created.106* // Whenever a new thread is created, the AccessControlContext at107* // that time is stored and associated with the new thread, as the108* // "inherited" context.109*110* inheritedContext.checkPermission(permission);111* }</pre>112*113* <p> A caller can be marked as being "privileged"114* (see {@link #doPrivileged(PrivilegedAction) doPrivileged} and below).115* When making access control decisions, the {@code checkPermission}116* method stops checking if it reaches a caller that117* was marked as "privileged" via a {@code doPrivileged}118* call without a context argument (see below for information about a119* context argument). If that caller's domain has the120* specified permission and at least one limiting permission argument (if any)121* implies the requested permission, no further checking is done and122* {@code checkPermission}123* returns quietly, indicating that the requested access is allowed.124* If that domain does not have the specified permission, an exception125* is thrown, as usual. If the caller's domain had the specified permission126* but it was not implied by any limiting permission arguments given in the call127* to {@code doPrivileged} then the permission checking continues128* until there are no more callers or another {@code doPrivileged}129* call matches the requested permission and returns normally.130*131* <p> The normal use of the "privileged" feature is as follows. If you132* don't need to return a value from within the "privileged" block, do133* the following:134*135* <pre> {@code136* somemethod() {137* ...normal code here...138* AccessController.doPrivileged(new PrivilegedAction<Void>() {139* public Void run() {140* // privileged code goes here, for example:141* System.loadLibrary("awt");142* return null; // nothing to return143* }144* });145* ...normal code here...146* }}</pre>147*148* <p>149* PrivilegedAction is an interface with a single method, named150* {@code run}.151* The above example shows creation of an implementation152* of that interface; a concrete implementation of the153* {@code run} method is supplied.154* When the call to {@code doPrivileged} is made, an155* instance of the PrivilegedAction implementation is passed156* to it. The {@code doPrivileged} method calls the157* {@code run} method from the PrivilegedAction158* implementation after enabling privileges, and returns the159* {@code run} method's return value as the160* {@code doPrivileged} return value (which is161* ignored in this example).162*163* <p> If you need to return a value, you can do something like the following:164*165* <pre> {@code166* somemethod() {167* ...normal code here...168* String user = AccessController.doPrivileged(169* new PrivilegedAction<String>() {170* public String run() {171* return System.getProperty("user.name");172* }173* });174* ...normal code here...175* }}</pre>176*177* <p>If the action performed in your {@code run} method could178* throw a "checked" exception (those listed in the {@code throws} clause179* of a method), then you need to use the180* {@code PrivilegedExceptionAction} interface instead of the181* {@code PrivilegedAction} interface:182*183* <pre> {@code184* somemethod() throws FileNotFoundException {185* ...normal code here...186* try {187* FileInputStream fis = AccessController.doPrivileged(188* new PrivilegedExceptionAction<FileInputStream>() {189* public FileInputStream run() throws FileNotFoundException {190* return new FileInputStream("someFile");191* }192* });193* } catch (PrivilegedActionException e) {194* // e.getException() should be an instance of FileNotFoundException,195* // as only "checked" exceptions will be "wrapped" in a196* // PrivilegedActionException.197* throw (FileNotFoundException) e.getException();198* }199* ...normal code here...200* }}</pre>201*202* <p> Be *very* careful in your use of the "privileged" construct, and203* always remember to make the privileged code section as small as possible.204* You can pass {@code Permission} arguments to further limit the205* scope of the "privilege" (see below).206*207*208* <p> Note that {@code checkPermission} always performs security checks209* within the context of the currently executing thread.210* Sometimes a security check that should be made within a given context211* will actually need to be done from within a212* <i>different</i> context (for example, from within a worker thread).213* The {@link #getContext() getContext} method and214* AccessControlContext class are provided215* for this situation. The {@code getContext} method takes a "snapshot"216* of the current calling context, and places217* it in an AccessControlContext object, which it returns. A sample call is218* the following:219*220* <pre>221*222* AccessControlContext acc = AccessController.getContext()223*224* </pre>225*226* <p>227* AccessControlContext itself has a {@code checkPermission} method228* that makes access decisions based on the context <i>it</i> encapsulates,229* rather than that of the current execution thread.230* Code within a different context can thus call that method on the231* previously-saved AccessControlContext object. A sample call is the232* following:233*234* <pre>235*236* acc.checkPermission(permission)237*238* </pre>239*240* <p> There are also times where you don't know a priori which permissions241* to check the context against. In these cases you can use the242* doPrivileged method that takes a context. You can also limit the scope243* of the privileged code by passing additional {@code Permission}244* parameters.245*246* <pre> {@code247* somemethod() {248* AccessController.doPrivileged(new PrivilegedAction<Object>() {249* public Object run() {250* // Code goes here. Any permission checks within this251* // run method will require that the intersection of the252* // caller's protection domain and the snapshot's253* // context have the desired permission. If a requested254* // permission is not implied by the limiting FilePermission255* // argument then checking of the thread continues beyond the256* // caller of doPrivileged.257* }258* }, acc, new FilePermission("/temp/*", read));259* ...normal code here...260* }}</pre>261* <p> Passing a limiting {@code Permission} argument of an instance of262* {@code AllPermission} is equivalent to calling the equivalent263* {@code doPrivileged} method without limiting {@code Permission}264* arguments. Passing a zero length array of {@code Permission} disables265* the code privileges so that checking always continues beyond the caller of266* that {@code doPrivileged} method.267*268* @see AccessControlContext269*270* @author Li Gong271* @author Roland Schemers272* @since 1.2273* @deprecated This class is only useful in conjunction with274* {@linkplain SecurityManager the Security Manager}, which is deprecated275* and subject to removal in a future release. Consequently, this class276* is also deprecated and subject to removal. There is no replacement for277* the Security Manager or this class.278*/279280@Deprecated(since="17", forRemoval=true)281public final class AccessController {282283/**284* Don't allow anyone to instantiate an AccessController285*/286private AccessController() { }287288/**289* Performs the specified {@code PrivilegedAction} with privileges290* enabled. The action is performed with <i>all</i> of the permissions291* possessed by the caller's protection domain.292*293* <p> If the action's {@code run} method throws an (unchecked)294* exception, it will propagate through this method.295*296* <p> Note that any DomainCombiner associated with the current297* AccessControlContext will be ignored while the action is performed.298*299* @param <T> the type of the value returned by the PrivilegedAction's300* {@code run} method.301*302* @param action the action to be performed.303*304* @return the value returned by the action's {@code run} method.305*306* @throws NullPointerException if the action is {@code null}307*308* @see #doPrivileged(PrivilegedAction,AccessControlContext)309* @see #doPrivileged(PrivilegedExceptionAction)310* @see #doPrivilegedWithCombiner(PrivilegedAction)311* @see java.security.DomainCombiner312*/313314@CallerSensitive315public static <T> T doPrivileged(PrivilegedAction<T> action)316{317return executePrivileged(action, null, Reflection.getCallerClass());318}319320/**321* Performs the specified {@code PrivilegedAction} with privileges322* enabled. The action is performed with <i>all</i> of the permissions323* possessed by the caller's protection domain.324*325* <p> If the action's {@code run} method throws an (unchecked)326* exception, it will propagate through this method.327*328* <p> This method preserves the current AccessControlContext's329* DomainCombiner (which may be null) while the action is performed.330*331* @param <T> the type of the value returned by the PrivilegedAction's332* {@code run} method.333*334* @param action the action to be performed.335*336* @return the value returned by the action's {@code run} method.337*338* @throws NullPointerException if the action is {@code null}339*340* @see #doPrivileged(PrivilegedAction)341* @see java.security.DomainCombiner342*343* @since 1.6344*/345@CallerSensitive346public static <T> T doPrivilegedWithCombiner(PrivilegedAction<T> action) {347@SuppressWarnings("removal")348AccessControlContext acc = getStackAccessControlContext();349if (acc == null) {350return AccessController.doPrivileged(action);351}352@SuppressWarnings("removal")353DomainCombiner dc = acc.getAssignedCombiner();354return AccessController.doPrivileged(action,355preserveCombiner(dc, Reflection.getCallerClass()));356}357358359/**360* Performs the specified {@code PrivilegedAction} with privileges361* enabled and restricted by the specified {@code AccessControlContext}.362* The action is performed with the intersection of the permissions363* possessed by the caller's protection domain, and those possessed364* by the domains represented by the specified {@code AccessControlContext}.365* <p>366* If the action's {@code run} method throws an (unchecked) exception,367* it will propagate through this method.368* <p>369* If a security manager is installed and the specified370* {@code AccessControlContext} was not created by system code and the371* caller's {@code ProtectionDomain} has not been granted the372* {@literal "createAccessControlContext"}373* {@link java.security.SecurityPermission}, then the action is performed374* with no permissions.375*376* @param <T> the type of the value returned by the PrivilegedAction's377* {@code run} method.378* @param action the action to be performed.379* @param context an <i>access control context</i>380* representing the restriction to be applied to the381* caller's domain's privileges before performing382* the specified action. If the context is383* {@code null}, then no additional restriction is applied.384*385* @return the value returned by the action's {@code run} method.386*387* @throws NullPointerException if the action is {@code null}388*389* @see #doPrivileged(PrivilegedAction)390* @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)391*/392@CallerSensitive393public static <T> T doPrivileged(PrivilegedAction<T> action,394@SuppressWarnings("removal") AccessControlContext context)395{396Class<?> caller = Reflection.getCallerClass();397context = checkContext(context, caller);398return executePrivileged(action, context, caller);399}400401402/**403* Performs the specified {@code PrivilegedAction} with privileges404* enabled and restricted by the specified405* {@code AccessControlContext} and with a privilege scope limited406* by specified {@code Permission} arguments.407*408* The action is performed with the intersection of the permissions409* possessed by the caller's protection domain, and those possessed410* by the domains represented by the specified411* {@code AccessControlContext}.412* <p>413* If the action's {@code run} method throws an (unchecked) exception,414* it will propagate through this method.415* <p>416* If a security manager is installed and the specified417* {@code AccessControlContext} was not created by system code and the418* caller's {@code ProtectionDomain} has not been granted the419* {@literal "createAccessControlContext"}420* {@link java.security.SecurityPermission}, then the action is performed421* with no permissions.422*423* @param <T> the type of the value returned by the PrivilegedAction's424* {@code run} method.425* @param action the action to be performed.426* @param context an <i>access control context</i>427* representing the restriction to be applied to the428* caller's domain's privileges before performing429* the specified action. If the context is430* {@code null},431* then no additional restriction is applied.432* @param perms the {@code Permission} arguments which limit the433* scope of the caller's privileges. The number of arguments434* is variable.435*436* @return the value returned by the action's {@code run} method.437*438* @throws NullPointerException if action or perms or any element of439* perms is {@code null}440*441* @see #doPrivileged(PrivilegedAction)442* @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)443*444* @since 1.8445*/446@CallerSensitive447public static <T> T doPrivileged(PrivilegedAction<T> action,448@SuppressWarnings("removal") AccessControlContext context,449Permission... perms) {450451@SuppressWarnings("removal")452AccessControlContext parent = getContext();453if (perms == null) {454throw new NullPointerException("null permissions parameter");455}456Class<?> caller = Reflection.getCallerClass();457@SuppressWarnings("removal")458DomainCombiner dc = (context == null) ? null : context.getCombiner();459return AccessController.doPrivileged(action, createWrapper(dc,460caller, parent, context, perms));461}462463464/**465* Performs the specified {@code PrivilegedAction} with privileges466* enabled and restricted by the specified467* {@code AccessControlContext} and with a privilege scope limited468* by specified {@code Permission} arguments.469*470* The action is performed with the intersection of the permissions471* possessed by the caller's protection domain, and those possessed472* by the domains represented by the specified473* {@code AccessControlContext}.474* <p>475* If the action's {@code run} method throws an (unchecked) exception,476* it will propagate through this method.477*478* <p> This method preserves the current AccessControlContext's479* DomainCombiner (which may be null) while the action is performed.480* <p>481* If a security manager is installed and the specified482* {@code AccessControlContext} was not created by system code and the483* caller's {@code ProtectionDomain} has not been granted the484* {@literal "createAccessControlContext"}485* {@link java.security.SecurityPermission}, then the action is performed486* with no permissions.487*488* @param <T> the type of the value returned by the PrivilegedAction's489* {@code run} method.490* @param action the action to be performed.491* @param context an <i>access control context</i>492* representing the restriction to be applied to the493* caller's domain's privileges before performing494* the specified action. If the context is495* {@code null},496* then no additional restriction is applied.497* @param perms the {@code Permission} arguments which limit the498* scope of the caller's privileges. The number of arguments499* is variable.500*501* @return the value returned by the action's {@code run} method.502*503* @throws NullPointerException if action or perms or any element of504* perms is {@code null}505*506* @see #doPrivileged(PrivilegedAction)507* @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)508* @see java.security.DomainCombiner509*510* @since 1.8511*/512@CallerSensitive513public static <T> T doPrivilegedWithCombiner(PrivilegedAction<T> action,514@SuppressWarnings("removal") AccessControlContext context,515Permission... perms) {516517@SuppressWarnings("removal")518AccessControlContext parent = getContext();519@SuppressWarnings("removal")520DomainCombiner dc = parent.getCombiner();521if (dc == null && context != null) {522dc = context.getCombiner();523}524if (perms == null) {525throw new NullPointerException("null permissions parameter");526}527Class<?> caller = Reflection.getCallerClass();528return AccessController.doPrivileged(action, createWrapper(dc, caller,529parent, context, perms));530}531532/**533* Performs the specified {@code PrivilegedExceptionAction} with534* privileges enabled. The action is performed with <i>all</i> of the535* permissions possessed by the caller's protection domain.536*537* <p> If the action's {@code run} method throws an <i>unchecked</i>538* exception, it will propagate through this method.539*540* <p> Note that any DomainCombiner associated with the current541* AccessControlContext will be ignored while the action is performed.542*543* @param <T> the type of the value returned by the544* PrivilegedExceptionAction's {@code run} method.545*546* @param action the action to be performed547*548* @return the value returned by the action's {@code run} method549*550* @throws PrivilegedActionException if the specified action's551* {@code run} method threw a <i>checked</i> exception552* @throws NullPointerException if the action is {@code null}553*554* @see #doPrivileged(PrivilegedAction)555* @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)556* @see #doPrivilegedWithCombiner(PrivilegedExceptionAction)557* @see java.security.DomainCombiner558*/559@CallerSensitive560public static <T> T561doPrivileged(PrivilegedExceptionAction<T> action)562throws PrivilegedActionException563{564@SuppressWarnings("removal")565AccessControlContext context = null;566Class<?> caller = Reflection.getCallerClass();567try {568return executePrivileged(action, context, caller);569} catch (RuntimeException e) {570throw e;571} catch (Exception e) {572throw wrapException(e);573}574}575576/**577* Performs the specified {@code PrivilegedExceptionAction} with578* privileges enabled. The action is performed with <i>all</i> of the579* permissions possessed by the caller's protection domain.580*581* <p> If the action's {@code run} method throws an <i>unchecked</i>582* exception, it will propagate through this method.583*584* <p> This method preserves the current AccessControlContext's585* DomainCombiner (which may be null) while the action is performed.586*587* @param <T> the type of the value returned by the588* PrivilegedExceptionAction's {@code run} method.589*590* @param action the action to be performed.591*592* @return the value returned by the action's {@code run} method593*594* @throws PrivilegedActionException if the specified action's595* {@code run} method threw a <i>checked</i> exception596* @throws NullPointerException if the action is {@code null}597*598* @see #doPrivileged(PrivilegedAction)599* @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)600* @see java.security.DomainCombiner601*602* @since 1.6603*/604@CallerSensitive605public static <T> T doPrivilegedWithCombiner(PrivilegedExceptionAction<T> action)606throws PrivilegedActionException607{608@SuppressWarnings("removal")609AccessControlContext acc = getStackAccessControlContext();610if (acc == null) {611return AccessController.doPrivileged(action);612}613@SuppressWarnings("removal")614DomainCombiner dc = acc.getAssignedCombiner();615return AccessController.doPrivileged(action,616preserveCombiner(dc, Reflection.getCallerClass()));617}618619/**620* preserve the combiner across the doPrivileged call621*/622@SuppressWarnings("removal")623private static AccessControlContext preserveCombiner(DomainCombiner combiner,624Class<?> caller)625{626return createWrapper(combiner, caller, null, null, null);627}628629/**630* Create a wrapper to contain the limited privilege scope data.631*/632@SuppressWarnings("removal")633private static AccessControlContext634createWrapper(DomainCombiner combiner, Class<?> caller,635AccessControlContext parent, AccessControlContext context,636Permission[] perms)637{638ProtectionDomain callerPD = getProtectionDomain(caller);639// check if caller is authorized to create context640if (System.getSecurityManager() != null &&641context != null && !context.isAuthorized() &&642!callerPD.implies(SecurityConstants.CREATE_ACC_PERMISSION))643{644return getInnocuousAcc();645} else {646return new AccessControlContext(callerPD, combiner, parent,647context, perms);648}649}650651private static class AccHolder {652// An AccessControlContext with no granted permissions.653// Only initialized on demand when getInnocuousAcc() is called.654@SuppressWarnings("removal")655static final AccessControlContext innocuousAcc =656new AccessControlContext(new ProtectionDomain[] {657new ProtectionDomain(null, null) });658}659@SuppressWarnings("removal")660private static AccessControlContext getInnocuousAcc() {661return AccHolder.innocuousAcc;662}663664private static native ProtectionDomain getProtectionDomain(final Class<?> caller);665666/**667* Performs the specified {@code PrivilegedExceptionAction} with668* privileges enabled and restricted by the specified669* {@code AccessControlContext}. The action is performed with the670* intersection of the permissions possessed by the caller's671* protection domain, and those possessed by the domains represented by the672* specified {@code AccessControlContext}.673* <p>674* If the action's {@code run} method throws an <i>unchecked</i>675* exception, it will propagate through this method.676* <p>677* If a security manager is installed and the specified678* {@code AccessControlContext} was not created by system code and the679* caller's {@code ProtectionDomain} has not been granted the680* {@literal "createAccessControlContext"}681* {@link java.security.SecurityPermission}, then the action is performed682* with no permissions.683*684* @param <T> the type of the value returned by the685* PrivilegedExceptionAction's {@code run} method.686* @param action the action to be performed687* @param context an <i>access control context</i>688* representing the restriction to be applied to the689* caller's domain's privileges before performing690* the specified action. If the context is691* {@code null}, then no additional restriction is applied.692*693* @return the value returned by the action's {@code run} method694*695* @throws PrivilegedActionException if the specified action's696* {@code run} method threw a <i>checked</i> exception697* @throws NullPointerException if the action is {@code null}698*699* @see #doPrivileged(PrivilegedAction)700* @see #doPrivileged(PrivilegedAction,AccessControlContext)701*/702@CallerSensitive703public static <T> T704doPrivileged(PrivilegedExceptionAction<T> action,705@SuppressWarnings("removal") AccessControlContext context)706throws PrivilegedActionException707{708Class<?> caller = Reflection.getCallerClass();709context = checkContext(context, caller);710try {711return executePrivileged(action, context, caller);712} catch (RuntimeException e) {713throw e;714} catch (Exception e) {715throw wrapException(e);716}717}718719@SuppressWarnings("removal")720private static AccessControlContext checkContext(AccessControlContext context,721Class<?> caller)722{723// check if caller is authorized to create context724if (System.getSecurityManager() != null &&725context != null && !context.isAuthorized() &&726context != getInnocuousAcc())727{728ProtectionDomain callerPD = getProtectionDomain(caller);729if (callerPD != null && !callerPD.implies(SecurityConstants.CREATE_ACC_PERMISSION)) {730return getInnocuousAcc();731}732}733return context;734}735736/**737* The value needs to be physically located in the frame, so that it738* can be found by a stack walk.739*/740@Hidden741private static native void ensureMaterializedForStackWalk(Object o);742743/**744* Sanity check that the caller context is indeed privileged.745*746* Used by executePrivileged to make sure the frame is properly747* recognized by the VM.748*/749private static boolean isPrivileged() {750@SuppressWarnings("removal")751AccessControlContext ctx = getStackAccessControlContext();752return ctx == null || ctx.isPrivileged();753}754755/**756* Execute the action as privileged.757*758* The VM recognizes this method as special, so any changes to the759* name or signature require corresponding changes in760* getStackAccessControlContext().761*/762@Hidden763@ForceInline764private static <T> T765executePrivileged(PrivilegedAction<T> action,766@SuppressWarnings("removal") AccessControlContext context,767Class<?> caller)768{769// Ensure context has a physical value in the frame770if (context != null) {771ensureMaterializedForStackWalk(context);772}773774assert isPrivileged(); // sanity check invariant775T result = action.run();776assert isPrivileged(); // sanity check invariant777778// Keep these alive across the run() call so they can be779// retrieved by getStackAccessControlContext().780Reference.reachabilityFence(context);781Reference.reachabilityFence(caller);782return result;783}784785/**786* Execute the action as privileged.787*788* The VM recognizes this method as special, so any changes to the789* name or signature require corresponding changes in790* getStackAccessControlContext().791*/792@Hidden793@ForceInline794private static <T> T795executePrivileged(PrivilegedExceptionAction<T> action,796@SuppressWarnings("removal") AccessControlContext context,797Class<?> caller)798throws Exception799{800// Ensure context has a physical value in the frame801if (context != null) {802ensureMaterializedForStackWalk(context);803}804805assert isPrivileged(); // sanity check invariant806T result = action.run();807assert isPrivileged(); // sanity check invariant808809// Keep these alive across the run() call so they can be810// retrieved by getStackAccessControlContext().811Reference.reachabilityFence(context);812Reference.reachabilityFence(caller);813return result;814}815816817/**818* Wrap an exception. The annotations are used in a best effort to819* avoid StackOverflowError in the caller. Inlining the callees as820* well and tail-call elimination could also help here, but are not821* needed for correctness, only quality of implementation.822*/823@Hidden824@ForceInline825@ReservedStackAccess826private static PrivilegedActionException wrapException(Exception e) {827return new PrivilegedActionException(e);828}829830/**831* Performs the specified {@code PrivilegedExceptionAction} with832* privileges enabled and restricted by the specified833* {@code AccessControlContext} and with a privilege scope limited by834* specified {@code Permission} arguments.835*836* The action is performed with the intersection of the permissions837* possessed by the caller's protection domain, and those possessed838* by the domains represented by the specified839* {@code AccessControlContext}.840* <p>841* If the action's {@code run} method throws an (unchecked) exception,842* it will propagate through this method.843* <p>844* If a security manager is installed and the specified845* {@code AccessControlContext} was not created by system code and the846* caller's {@code ProtectionDomain} has not been granted the847* {@literal "createAccessControlContext"}848* {@link java.security.SecurityPermission}, then the action is performed849* with no permissions.850*851* @param <T> the type of the value returned by the852* PrivilegedExceptionAction's {@code run} method.853* @param action the action to be performed.854* @param context an <i>access control context</i>855* representing the restriction to be applied to the856* caller's domain's privileges before performing857* the specified action. If the context is858* {@code null},859* then no additional restriction is applied.860* @param perms the {@code Permission} arguments which limit the861* scope of the caller's privileges. The number of arguments862* is variable.863*864* @return the value returned by the action's {@code run} method.865*866* @throws PrivilegedActionException if the specified action's867* {@code run} method threw a <i>checked</i> exception868* @throws NullPointerException if action or perms or any element of869* perms is {@code null}870*871* @see #doPrivileged(PrivilegedAction)872* @see #doPrivileged(PrivilegedAction,AccessControlContext)873*874* @since 1.8875*/876@CallerSensitive877public static <T> T doPrivileged(PrivilegedExceptionAction<T> action,878@SuppressWarnings("removal") AccessControlContext context,879Permission... perms)880throws PrivilegedActionException881{882@SuppressWarnings("removal")883AccessControlContext parent = getContext();884if (perms == null) {885throw new NullPointerException("null permissions parameter");886}887Class<?> caller = Reflection.getCallerClass();888@SuppressWarnings("removal")889DomainCombiner dc = (context == null) ? null : context.getCombiner();890return AccessController.doPrivileged(action, createWrapper(dc, caller, parent, context, perms));891}892893894/**895* Performs the specified {@code PrivilegedExceptionAction} with896* privileges enabled and restricted by the specified897* {@code AccessControlContext} and with a privilege scope limited by898* specified {@code Permission} arguments.899*900* The action is performed with the intersection of the permissions901* possessed by the caller's protection domain, and those possessed902* by the domains represented by the specified903* {@code AccessControlContext}.904* <p>905* If the action's {@code run} method throws an (unchecked) exception,906* it will propagate through this method.907*908* <p> This method preserves the current AccessControlContext's909* DomainCombiner (which may be null) while the action is performed.910* <p>911* If a security manager is installed and the specified912* {@code AccessControlContext} was not created by system code and the913* caller's {@code ProtectionDomain} has not been granted the914* {@literal "createAccessControlContext"}915* {@link java.security.SecurityPermission}, then the action is performed916* with no permissions.917*918* @param <T> the type of the value returned by the919* PrivilegedExceptionAction's {@code run} method.920* @param action the action to be performed.921* @param context an <i>access control context</i>922* representing the restriction to be applied to the923* caller's domain's privileges before performing924* the specified action. If the context is925* {@code null},926* then no additional restriction is applied.927* @param perms the {@code Permission} arguments which limit the928* scope of the caller's privileges. The number of arguments929* is variable.930*931* @return the value returned by the action's {@code run} method.932*933* @throws PrivilegedActionException if the specified action's934* {@code run} method threw a <i>checked</i> exception935* @throws NullPointerException if action or perms or any element of936* perms is {@code null}937*938* @see #doPrivileged(PrivilegedAction)939* @see #doPrivileged(PrivilegedAction,AccessControlContext)940* @see java.security.DomainCombiner941*942* @since 1.8943*/944@CallerSensitive945public static <T> T doPrivilegedWithCombiner(PrivilegedExceptionAction<T> action,946@SuppressWarnings("removal") AccessControlContext context,947Permission... perms)948throws PrivilegedActionException949{950@SuppressWarnings("removal")951AccessControlContext parent = getContext();952@SuppressWarnings("removal")953DomainCombiner dc = parent.getCombiner();954if (dc == null && context != null) {955dc = context.getCombiner();956}957if (perms == null) {958throw new NullPointerException("null permissions parameter");959}960Class<?> caller = Reflection.getCallerClass();961return AccessController.doPrivileged(action, createWrapper(dc, caller,962parent, context, perms));963}964965/**966* Returns the AccessControl context. i.e., it gets967* the protection domains of all the callers on the stack,968* starting at the first class with a non-null969* ProtectionDomain.970*971* @return the access control context based on the current stack or972* null if there was only privileged system code.973*/974975@SuppressWarnings("removal")976private static native AccessControlContext getStackAccessControlContext();977978979/**980* Returns the "inherited" AccessControl context. This is the context981* that existed when the thread was created. Package private so982* AccessControlContext can use it.983*/984985@SuppressWarnings("removal")986static native AccessControlContext getInheritedAccessControlContext();987988/**989* This method takes a "snapshot" of the current calling context, which990* includes the current Thread's inherited AccessControlContext and any991* limited privilege scope, and places it in an AccessControlContext object.992* This context may then be checked at a later point, possibly in another thread.993*994* @see AccessControlContext995*996* @return the AccessControlContext based on the current context.997*/998999@SuppressWarnings("removal")1000public static AccessControlContext getContext()1001{1002AccessControlContext acc = getStackAccessControlContext();1003if (acc == null) {1004// all we had was privileged system code. We don't want1005// to return null though, so we construct a real ACC.1006return new AccessControlContext(null, true);1007} else {1008return acc.optimize();1009}1010}10111012/**1013* Determines whether the access request indicated by the1014* specified permission should be allowed or denied, based on1015* the current AccessControlContext and security policy.1016* This method quietly returns if the access request1017* is permitted, or throws an AccessControlException otherwise. The1018* getPermission method of the AccessControlException returns the1019* {@code perm} Permission object instance.1020*1021* @param perm the requested permission.1022*1023* @throws AccessControlException if the specified permission1024* is not permitted, based on the current security policy.1025* @throws NullPointerException if the specified permission1026* is {@code null} and is checked based on the1027* security policy currently in effect.1028*/10291030@SuppressWarnings("removal")1031public static void checkPermission(Permission perm)1032throws AccessControlException1033{1034//System.err.println("checkPermission "+perm);1035//Thread.currentThread().dumpStack();10361037if (perm == null) {1038throw new NullPointerException("permission can't be null");1039}10401041AccessControlContext stack = getStackAccessControlContext();1042// if context is null, we had privileged system code on the stack.1043if (stack == null) {1044Debug debug = AccessControlContext.getDebug();1045boolean dumpDebug = false;1046if (debug != null) {1047dumpDebug = !Debug.isOn("codebase=");1048dumpDebug &= !Debug.isOn("permission=") ||1049Debug.isOn("permission=" + perm.getClass().getCanonicalName());1050}10511052if (dumpDebug && Debug.isOn("stack")) {1053Thread.dumpStack();1054}10551056if (dumpDebug && Debug.isOn("domain")) {1057debug.println("domain (context is null)");1058}10591060if (dumpDebug) {1061debug.println("access allowed "+perm);1062}1063return;1064}10651066AccessControlContext acc = stack.optimize();1067acc.checkPermission(perm);1068}1069}107010711072