Path: blob/master/jcl/src/java.base/share/classes/java/security/AccessController.java
12513 views
/*[INCLUDE-IF Sidecar18-SE]*/1/*******************************************************************************2* Copyright (c) 1998, 2021 IBM Corp. and others3*4* This program and the accompanying materials are made available under5* the terms of the Eclipse Public License 2.0 which accompanies this6* distribution and is available at https://www.eclipse.org/legal/epl-2.0/7* or the Apache License, Version 2.0 which accompanies this distribution and8* is available at https://www.apache.org/licenses/LICENSE-2.0.9*10* This Source Code may also be made available under the following11* Secondary Licenses when the conditions for such availability set12* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU13* General Public License, version 2 with the GNU Classpath14* Exception [1] and GNU General Public License, version 2 with the15* OpenJDK Assembly Exception [2].16*17* [1] https://www.gnu.org/software/classpath/license.html18* [2] http://openjdk.java.net/legal/assembly-exception.html19*20* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception21*******************************************************************************/22package java.security;2324import java.security.AccessControlContext.AccessCache;25import sun.security.util.SecurityConstants;2627/*[IF Sidecar19-SE]28import jdk.internal.reflect.CallerSensitive;29/*[ELSE]*/30import sun.reflect.CallerSensitive;31/*[ENDIF]*/3233/**34* Checks access to system resources. Supports marking of code35* as privileged. Makes context snapshots to allow checking from36* other contexts.37*38* @author OTI39* @version initial40*/41/*[IF JAVA_SPEC_VERSION >= 17]*/42@Deprecated(since="17", forRemoval=true)43/*[ENDIF] JAVA_SPEC_VERSION >= 17 */44public final class AccessController {45static {46// Initialize vm-internal caches47initializeInternal();48}4950static final int OBJS_INDEX_ACC = 0;51static final int OBJS_INDEX_PDS = 1;52static final int OBJS_ARRAY_SIZE = 3;53static final int OBJS_INDEX_PERMS_OR_CACHECHECKED = 2;5455private static native void initializeInternal();5657/* [PR CMVC 188787] Enabling -Djava.security.debug option within WAS keeps JVM busy */58static final class DebugRecursionDetection {59private static ThreadLocal<String> tlDebug = new ThreadLocal<>();60static ThreadLocal<String> getTlDebug() {61return tlDebug;62}63}6465/*[PR 1FDIC6B] J9JCL:WIN95 - AccessController missing private no-arg constructor */66/**67* Prevents this class from being instantiated.68*/69private AccessController() {70super();71}7273/**74* The object array returned has following format:75*76* Pre-JEP140 format: AccessControlContext/ProtectionDomain..., and the length of the object array is NOT divisible by OBJS_ARRAY_SIZE77* First element is an AccessControlContext object which might be null, either from a full permission privileged frame or from current thread if there is no such privileged frames78* ProtectionDomain elements after AccessControlContext object could be in one of following two formats:79* For doPrivileged methods - flag forDoPrivilegedWithCombiner is false:80* the ProtectionDomain element might be null, first ProtectionDomain element is a duplicate of the ProtectionDomain of the caller of doPrivileged81* rest of ProtectionDomain elements are from the callers discovered during stack walking82* the start index of the actual ProtectionDomain element is 2 of the object array returned83* For doPrivilegedWithCombiner methods - flag forDoPrivilegedWithCombiner is true:84* there are only two ProtectionDomain elements, first one is the ProtectionDomain of the caller of doPrivileged85* and the other is the ProtectionDomain of the caller of doPrivilegedWithCombiner86* the fourth element of the object array is NULL for padding to ensure that the length of the object array is NOT divisible by OBJS_ARRAY_SIZE either87*88* JEP 140 format: AccessControlContext/ProtectionDomain[]/Permission[]89* The length of the object array is always divisible by OBJS_ARRAY_SIZE.90* Depends on number of limited permission privileged frames, the result are in following format:91* First element is an AccessControlContext object92* Second element could be in one of following two formats:93* For doPrivileged methods - flag forDoPrivilegedWithCombiner is false:94* an array of ProtectionDomain objects in which first ProtectionDomain element is a duplicate of the ProtectionDomain of the caller of doPrivileged95* the start index of the actual ProtectionDomain element is 1 of this ProtectionDomain objects array96* For doPrivilegedWithCombiner methods - flag forDoPrivilegedWithCombiner is true:97* an array of ProtectionDomain objects with only two elements98* first one is the ProtectionDomain of the caller of doPrivileged99* and the other is the ProtectionDomain of the caller of doPrivilegedWithCombiner100* Third element is an array of Limited Permission objects101* Repeating this format:102* AccessControlContext object,103* ProtectionDomain objects array with same format above when flag forDoPrivilegedWithCombiner is false104* or just the ProtectionDomain of the caller of doPrivileged in case of flag forDoPrivilegedWithCombiner is true105* Permission object array106* Until a full permission privileged frame or the end of the stack reached.107*108* Note: 1. The reason to have Pre-JEP140 and JEP 140 format is to keep similar format and processing logic109* when there is no limited doPrivileged method (JEP 140 implementation) involved.110* This helped to address performance issue raised by JAZZ 66091: Perf work for LIR 28261 (Limited doPrivileged / JEP 140)111* 2. The reason to duplicate the ProtectionDomain object of the caller of doPrivileged is to avoid creating a new object array112* without NULL and duplicate ProtectionDomain objects discovered during stack walking while still keeping same order of113* those objects.114*115* A full permission privileged frame is any frame running one of the following methods:116*117* <code><ul>118* <li>java/security/AccessController.doPrivileged(Ljava/security/PrivilegedAction;)Ljava/lang/Object;</li>119* <li>java/security/AccessController.doPrivileged(Ljava/security/PrivilegedExceptionAction;)Ljava/lang/Object;</li>120* <li>java/security/AccessController.doPrivileged(Ljava/security/PrivilegedAction;Ljava/security/AccessControlContext;)Ljava/lang/Object;</li>121* <li>java/security/AccessController.doPrivileged(Ljava/security/PrivilegedExceptionAction;Ljava/security/AccessControlContext;)Ljava/lang/Object;</li>122* </ul></code>123*124* A limited permission privileged frame is any frame running one of the following methods:125*126* <code><ul>127* <li>java/security/AccessController.doPrivileged(Ljava/security/PrivilegedAction;Ljava/security/AccessControlContext;[Ljava/security/Permission;)Ljava/lang/Object;</li>128* <li>java/security/AccessController.doPrivileged(Ljava/security/PrivilegedExceptionAction;Ljava/security/AccessControlContext;[Ljava/security/Permission;)Ljava/lang/Object;</li>129* </ul></code>130*131* @param depth The stack depth at which to start. Depth 0 is the current frame (the caller of this native).132* @param forDoPrivilegedWithCombiner The flag to indicate if it is for doPrivilegedWithCombiner method133*134* @return an Object[] as description above135*/136private static native Object[] getAccSnapshot(int depth, boolean forDoPrivilegedWithCombiner);137138/**139* This native retrieves the ProtectionDomain object of the non-reflection/MethodHandleInvoke caller as per depth specified.140* For example, when depth is set to 1 for method doPrivilegedWithCombiner, the ProtectionDomain object of the caller of doPrivilegedWithCombiner is returned141* Note: it is only for limited doPrivilegedWithCombiner methods for now.142*143* @param depth The stack depth at which to start.144*145* @return a ProtectionDomain object as per description above146*/147private static native ProtectionDomain getCallerPD(int depth);148149/**150* provide debug info according to debug settings before throwing AccessControlException151*152* @param debug overall debug flag returned from DebugRecursionDetection.getTlDebug()153* @param perm the permission to check154* @param pDomain the pDomain to check155* @param createACCdenied if true, actual cause of this ACE was SecurityPermission("createAccessControlContext") denied156* @exception AccessControlException always throw an AccessControlException157*/158private static void throwACE(boolean debug, Permission perm, ProtectionDomain pDomain, boolean createACCdenied) {159if (debug) {160DebugRecursionDetection.getTlDebug().set(""); //$NON-NLS-1$161AccessControlContext.debugPrintAccess();162if (createACCdenied) {163System.err.println("access denied " + perm + " due to untrusted AccessControlContext since " + SecurityConstants.CREATE_ACC_PERMISSION + " is denied."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$164} else {165System.err.println("access denied " + perm); //$NON-NLS-1$166}167DebugRecursionDetection.getTlDebug().remove();168}169if (debug && ((AccessControlContext.debugSetting() & AccessControlContext.DEBUG_ACCESS_FAILURE) != 0)) {170DebugRecursionDetection.getTlDebug().set(""); //$NON-NLS-1$171new Exception("Stack trace").printStackTrace(); //$NON-NLS-1$172if (createACCdenied) {173System.err.println("domain that failed " + SecurityConstants.CREATE_ACC_PERMISSION + " check " + pDomain); //$NON-NLS-1$ //$NON-NLS-2$174} else {175System.err.println("domain that failed " + pDomain); //$NON-NLS-1$176}177DebugRecursionDetection.getTlDebug().remove();178}179if (createACCdenied) {180/*[MSG "K002d", "Access denied {0} due to untrusted AccessControlContext since {1} is denied"]*/181throw new AccessControlException(com.ibm.oti.util.Msg.getString("K002d", perm, SecurityConstants.CREATE_ACC_PERMISSION), perm); //$NON-NLS-1$182} else {183/*[MSG "K002c", "Access denied {0}"]*/184throw new AccessControlException(com.ibm.oti.util.Msg.getString("K002c", perm), perm); //$NON-NLS-1$185}186}187188/**189* Helper method to check whether the running program is allowed to access the resource190* being guarded by the given Permission argument191* Assuming perm is not null.192*193* @param perm the permission to be checked194* @param activeDC the DomainCombiner to be invoked195* @param acc the AccessControlContext to be checked196* @param objects the object array returned from native getAccSnapshot197* @param frame the doPrivileged frame are being checked198* @param checked the cached check result199* @param objPDomains the object array containing ProtectionDomain objects200* @param debug the debug flag201* @param startPos the start index of the actual ProtectionDomain objects202* 1 is JEP140 format, 2 is Pre-JEP140 format203*204* @return true if access is granted by a limited permission, otherwise return false205*/206private static boolean checkPermissionHelper(Permission perm, AccessControlContext acc, DomainCombiner activeDC, Object[] objects, int frame, AccessCache checked, Object[] objPDomains, int debug, int startPos) {207boolean limitedPermImplied = false;208boolean debugEnabled = (debug & AccessControlContext.DEBUG_ENABLED) != 0;209ProtectionDomain[] pDomains = generatePDarray(activeDC, acc, objPDomains, debugEnabled, startPos);210if (debugEnabled && (0 != (AccessControlContext.debugSetting() & AccessControlContext.DEBUG_ACCESS_DOMAIN))) {211DebugRecursionDetection.getTlDebug().set(""); //$NON-NLS-1$212AccessControlContext.debugPrintAccess();213if (null == pDomains || 0 == pDomains.length) {214System.err.println("domain (context is null)"); //$NON-NLS-1$215} else {216/*[PR 121690] -Djava.security.debug=access:domain should print domains in checkPermission() */217for (int i = 0; i < pDomains.length; ++i) {218System.err.println("domain " + i + " " + pDomains[i]); //$NON-NLS-1$ //$NON-NLS-2$219}220}221DebugRecursionDetection.getTlDebug().remove();222}223int length = pDomains == null ? 0 : pDomains.length;224if ((null != acc)225&& (null != acc.context)226&& (AccessControlContext.STATE_AUTHORIZED != acc.authorizeState)227&& (null != System.getSecurityManager())228) {229/*[PR JAZZ 72492] PMR 24367,001,866: Unexpected Security Permission "createAccessControlContext" exception thrown from 1.6SR14 onwards */230// startPos: 1 is JEP140 format, 2 is Pre-JEP140 format231ProtectionDomain callerPD = (ProtectionDomain) objPDomains[startPos - 1];232if (null != callerPD && !callerPD.implies(SecurityConstants.CREATE_ACC_PERMISSION)) {233/*[PR CMVC 197399] Improve checking order */234// new behavior introduced by this fix235// an ACE is thrown if there is a untrusted PD but without SecurityPermission createAccessControlContext236throwACE((debug & AccessControlContext.DEBUG_ACCESS_DENIED) != 0, perm, callerPD, true);237}238}239240if (2 == startPos) { // Pre-JEP140 format241if (null != acc && (null != acc.doPrivilegedAcc || null != acc.nextStackAcc || acc.isLimitedContext)) {242checked = new AccessCache(); /* checked was null initially when Pre-JEP140 format */243return AccessControlContext.checkPermissionWithCache(perm, activeDC, pDomains, debug, acc, false, null, null, checked);244} else {245if (pDomains != null) {246for (int i = 0; i < length ; ++i) {247// invoke PD within acc.context first248/*[IF Sidecar19-SE]*/249if ((pDomains[length - i - 1] != null) && !pDomains[length - i - 1].impliesWithAltFilePerm(perm)) {250/*[ELSE]*/251if ((pDomains[length - i - 1] != null) && !pDomains[length - i - 1].implies(perm)) {252/*[ENDIF] Sidecar19-SE*/253throwACE((debug & AccessControlContext.DEBUG_ACCESS_DENIED) != 0, perm, pDomains[length - i - 1], false);254}255}256}257}258} else {259if (AccessControlContext.checkPermissionWithCache(perm, activeDC,260pDomains, debug, (AccessControlContext)objects[frame * OBJS_ARRAY_SIZE],261(null != objects[frame * OBJS_ARRAY_SIZE + OBJS_INDEX_PERMS_OR_CACHECHECKED]),262(Permission[])objects[frame * OBJS_ARRAY_SIZE + OBJS_INDEX_PERMS_OR_CACHECHECKED],263null, checked)264) {265limitedPermImplied = true;266}267}268return limitedPermImplied;269}270271/**272* Helper to print debug stack information for checkPermission().273*274* @param debug the debug flags in effect275* @param perm the permission to check276*/277private static void debugPrintStack(boolean debug, Permission perm) {278if (debug && ((AccessControlContext.debugSetting() & AccessControlContext.DEBUG_ACCESS_STACK) != 0)) {279DebugRecursionDetection.getTlDebug().set(""); //$NON-NLS-1$280new Exception("Stack trace for " + perm).printStackTrace(); //$NON-NLS-1$281DebugRecursionDetection.getTlDebug().remove();282}283}284285/**286* Helper to print debug information for checkPermission() when in the pre JEP 140 format.287*288* @param objects the AccessControlContext and ProtectionDomain array obtained from the stack289* @param perm the permission to check290* @return if debugging is enabled291*/292private static boolean debugHelperPreJEP140(Object[] objects, Permission perm) {293boolean debug = true;294if (AccessControlContext.debugCodeBaseArray != null) {295debug = false;296for (int i = 2; i < objects.length; ++i) {297Object pd = objects[i];298if (pd != null) {299CodeSource cs = ((ProtectionDomain) pd).getCodeSource();300if ((cs != null) && AccessControlContext.debugCodeBase(cs.getLocation())) {301debug = true;302break;303}304}305}306AccessControlContext acc = (AccessControlContext) objects[0];307if (!debug) {308debug = (acc != null) && acc.hasDebugCodeBase();309}310}311312if (debug && !AccessControlContext.debugPermission(perm)) {313debug = false;314}315316debugPrintStack(debug, perm);317return debug;318}319320/**321* Helper to print debug information for checkPermission() when in the JEP 140 format.322*323* @param objects the AccessControlContext and ProtectionDomain array obtained from the stack324* @param perm the permission to check325* @return if debugging is enabled326*/327private static boolean debugHelperJEP140(Object[] objects, Permission perm) {328boolean debug = true;329if (AccessControlContext.debugCodeBaseArray != null) {330debug = false;331done:332for (int j = 0; j < objects.length / OBJS_ARRAY_SIZE; ++j) {333AccessControlContext acc = (AccessControlContext) objects[j * OBJS_ARRAY_SIZE];334Object[] objPDomains = (Object[]) objects[j * OBJS_ARRAY_SIZE + OBJS_INDEX_PDS];335for (int i = 1; i < objPDomains.length; ++i) {336Object pd = objPDomains[i];337if (pd != null) {338CodeSource cs = ((ProtectionDomain) pd).getCodeSource();339if ((cs != null) && AccessControlContext.debugCodeBase(cs.getLocation())) {340debug = true;341break done;342}343}344}345if ((acc != null) && acc.hasDebugCodeBase()) {346debug = true;347break;348}349}350}351352if (debug) {353debug = AccessControlContext.debugPermission(perm);354}355356debugPrintStack(debug, perm);357return debug;358}359360/**361* Checks whether the running program is allowed to362* access the resource being guarded by the given363* Permission argument.364*365* @param perm the permission to check366* @exception AccessControlException if access is not allowed.367* NullPointerException if perm is null368*/369public static void checkPermission(Permission perm) throws AccessControlException {370if (perm == null) {371throw new NullPointerException();372}373// DEBUG_ENABLED is set if there is nothing to match, or if there is a matching codebase or permission object374int debug = AccessControlContext.DEBUG_DISABLED;375if (AccessControlContext.debugSetting() != 0) {376if (null == DebugRecursionDetection.getTlDebug().get()) {377debug = AccessControlContext.DEBUG_ACCESS_DENIED | AccessControlContext.DEBUG_ENABLED;378}379}380381Object[] objects = getAccSnapshot(1, false);382boolean isPreJEP140Format = (0 == objects.length % OBJS_ARRAY_SIZE) ? false : true;383384DomainCombiner activeDC = null;385AccessControlContext topACC = (AccessControlContext) objects[0];386if ((topACC != null)387&& (topACC.domainCombiner != null)388) {389/* only AccessControlContext with STATE_AUTHORIZED authorizeState could have non-null domainCombiner390* the domainCombiner from the closest doPrivileged is used for all later ProtectionDomain combine() calls391*/392activeDC = topACC.domainCombiner;393}394395if (isPreJEP140Format) {396if ((debug != AccessControlContext.DEBUG_DISABLED) && !debugHelperPreJEP140(objects, perm)) {397debug = AccessControlContext.DEBUG_ACCESS_DENIED; // Disable DEBUG_ENABLED398}399400checkPermissionHelper(perm, topACC, activeDC, null, 0, null, objects, debug, 2); // the actual ProtectionDomain element starts at index 2401} else {402int frameNbr = objects.length / OBJS_ARRAY_SIZE;403404if ((debug != AccessControlContext.DEBUG_DISABLED) && !debugHelperJEP140(objects, perm)) {405debug = AccessControlContext.DEBUG_ACCESS_DENIED; // Disable DEBUG_ENABLED406}407408AccessCache checked = new AccessCache();409for (int j = 0; j < frameNbr; ++j) {410AccessControlContext acc = (AccessControlContext) objects[j * OBJS_ARRAY_SIZE];411Object[] objPDomains = (Object[]) objects[j * OBJS_ARRAY_SIZE + OBJS_INDEX_PDS];412if (checkPermissionHelper(perm, acc, activeDC, objects, j, checked, objPDomains, debug, 1)) { // the actual ProtectionDomain element starts at index 1413break;414}415}416}417if ((debug & AccessControlContext.DEBUG_ENABLED) != 0) {418DebugRecursionDetection.getTlDebug().set(""); //$NON-NLS-1$419AccessControlContext.debugPrintAccess();420System.err.println("access allowed " + perm); //$NON-NLS-1$421DebugRecursionDetection.getTlDebug().remove();422}423}424425/**426* Used to keep the context live during doPrivileged().427*428* @param context the context to retain429*430* @see #doPrivileged(PrivilegedAction, AccessControlContext)431*/432private static void keepalive(AccessControlContext context) {433return;434}435436/**437* @param perms the permissions to retain438*/439private static void keepalive(Permission... perms) {440return;441}442443/**444* Answers the access controller context of the current thread,445* including the inherited ones. It basically retrieves all the446* protection domains from the calling stack and creates an447* <code>AccessControlContext</code> with them.448*449* @return an AccessControlContext which captures the current state450*451* @see AccessControlContext452*/453public static AccessControlContext getContext() {454return getContextHelper(false);455}456457/**458* This is a helper method for getContext() and doPrivilegedWithCombiner methods.459* Answers the access controller context of the current thread including the inherited ones.460* Refer native getAccSnapshot() for return data format accordingly to the flag forDoPrivilegedWithCombiner.461*462* @param forDoPrivilegedWithCombiner The flag to indicate if it is for doPrivilegedWithCombiner method463* @return an AccessControlContext which captures the current state464*/465@CallerSensitive466private static AccessControlContext getContextHelper(boolean forDoPrivilegedWithCombiner) {467Object[] domains = getAccSnapshot(2, forDoPrivilegedWithCombiner);468boolean isPreJEP140Format = (0 == domains.length % OBJS_ARRAY_SIZE) ? false : true;469DomainCombiner activeDC = null;470AccessControlContext topACC = (AccessControlContext) domains[0];471if ((topACC != null)472&& (topACC.domainCombiner != null)473) {474/* only AccessControlContext with STATE_AUTHORIZED authorizeState could have non-null domainCombiner475* the domainCombiner from the closest doPrivileged is used for all later ProtectionDomain combine() calls476*/477activeDC = topACC.domainCombiner;478}479if (isPreJEP140Format) {480/*[PR JAZZ 66930] j.s.AccessControlContext.checkPermission() invoke untrusted ProtectionDomain.implies */481// The actual ProtectionDomain element starts at index 2482ProtectionDomain[] pDomains = generatePDarray(activeDC, topACC, domains, false, 2);483AccessControlContext accTmp;484int newAuthorizedState = getNewAuthorizedState(topACC, (ProtectionDomain) domains[1]);485if ((topACC != null) && ((topACC.doPrivilegedAcc != null) || (topACC.nextStackAcc != null) || topACC.isLimitedContext)) {486accTmp = new AccessControlContext(topACC, pDomains, newAuthorizedState);487} else {488accTmp = new AccessControlContext(pDomains, newAuthorizedState);489}490if ((topACC != null) && (topACC.domainCombiner != null)) {491accTmp.domainCombiner = topACC.domainCombiner;492}493return accTmp;494}495int frameNbr = domains.length / OBJS_ARRAY_SIZE;496AccessControlContext accContext = null;497AccessControlContext accLower = null;498for (int j = 0; j < frameNbr; ++j) {499AccessControlContext acc = (AccessControlContext) domains[j * OBJS_ARRAY_SIZE];500/*[PR JAZZ 66930] j.s.AccessControlContext.checkPermission() invoke untrusted ProtectionDomain.implies */501// the actual ProtectionDomain element starts at index 1502ProtectionDomain[] pDomains = generatePDarray(activeDC, acc, (Object[]) domains[j * OBJS_ARRAY_SIZE + OBJS_INDEX_PDS], false, 1);503AccessControlContext accTmp;504int newAuthorizedState = getNewAuthorizedState(acc, (ProtectionDomain)((Object[]) domains[j * OBJS_ARRAY_SIZE + OBJS_INDEX_PDS])[0]);505if (((null != acc) && acc.isLimitedContext) || (1 < frameNbr)) {506// there is a limited doPrivilege frame507accTmp = new AccessControlContext(acc, pDomains, newAuthorizedState);508} else {509// not set doPrivilegedAcc for non limited doPrivilege510// all ProtectionDomains already included within pDomains511accTmp = new AccessControlContext(pDomains, newAuthorizedState);512}513if (null != acc && null != acc.domainCombiner) {514accTmp.domainCombiner = acc.domainCombiner;515if (activeDC == null) {516// This activeDC will be set to accContext.domainCombiner.517activeDC = acc.domainCombiner;518}519}520if (null != domains[j * OBJS_ARRAY_SIZE + OBJS_INDEX_PERMS_OR_CACHECHECKED]) {521// this is frame with limited permissions522accTmp.isLimitedContext = true;523accTmp.limitedPerms = (Permission[]) domains[j * OBJS_ARRAY_SIZE + OBJS_INDEX_PERMS_OR_CACHECHECKED];524}525526if (null == accLower) {527accContext = accTmp;528} else {529accLower.nextStackAcc = accTmp;530}531accLower = accTmp;532}533if ((accContext != null) && (accContext.domainCombiner == null) && (activeDC != null)) {534// the domainCombiner from the closest doPrivileged is set for returning AccessControlContext object, otherwise null is set.535accContext.domainCombiner = activeDC;536}537return accContext;538}539540/**541* Helper method to generate ProtectionDomain array for a new AccessControlContext object542*543* @param activeDC the DomainCombiner to be invoked544* @param acc the AccessControlContext object to be checked545* @param domains the incoming ProtectionDomain object array546* @param debug the debug flag547* @param startPos the start index of the actual ProtectionDomain object548*549* @return a ProtectionDomain object array550*/551private static ProtectionDomain[] generatePDarray(DomainCombiner activeDC, AccessControlContext acc, Object[] domains, boolean debug, int startPos) {552ProtectionDomain[] pDomains = null;553/*[PR JAZZ 66930] j.s.AccessControlContext.checkPermission() invoke untrusted ProtectionDomain.implies */554DomainCombiner actDC = null;555if (activeDC != null) {556actDC = activeDC;557} else {558if ((acc != null)559&& (acc.domainCombiner != null)560) {561// only AccessControlContext with STATE_AUTHORIZED authorizeState could have non-null domainCombiner562actDC = acc.domainCombiner;563}564}565566if (actDC != null) {567if (debug) {568DebugRecursionDetection.getTlDebug().set(""); //$NON-NLS-1$569AccessControlContext.debugPrintAccess();570System.err.println("AccessController invoking the Combiner"); //$NON-NLS-1$571DebugRecursionDetection.getTlDebug().remove();572}573ProtectionDomain[] pds = null;574if (acc != null) {575pds = acc.context;576}577pDomains = actDC.combine(toArrayOfProtectionDomains(domains, null, startPos), pds);578} else {579pDomains = toArrayOfProtectionDomains(domains, acc, startPos);580}581if (null != pDomains && 0 == pDomains.length) {582pDomains = null;583}584return pDomains;585}586587/**588* Helper method to determine the newAuthorizedState according to incoming acc and callerPD.589*590* @param acc the AccessControlContext object to be checked591* @param callerPD the caller's ProtectionDomain object592*593* @return AccessControlContext.STATE_AUTHORIZED or STATE_NOT_AUTHORIZED (can't be STATE_UNKNOWN)594*/595private static int getNewAuthorizedState(AccessControlContext acc, ProtectionDomain callerPD) {596int newAuthorizedState;597/*[PR JAZZ 87596] PMR 18839,756,000 - Need to trust AccessControlContext created without active SecurityManager */598if ((null != acc) && (null != System.getSecurityManager())) {599newAuthorizedState = acc.authorizeState;600if (AccessControlContext.STATE_UNKNOWN == newAuthorizedState) {601// only change AccessControlContext.authorizeState when it is unknown initially602if (null == callerPD || callerPD.implies(SecurityConstants.CREATE_ACC_PERMISSION)) {603newAuthorizedState = AccessControlContext.STATE_AUTHORIZED;604} else {605newAuthorizedState = AccessControlContext.STATE_NOT_AUTHORIZED;606}607}608} else {609newAuthorizedState = AccessControlContext.STATE_AUTHORIZED;610}611return newAuthorizedState;612}613614/**615* Helper method to combine the ProtectionDomain objects616*617* @param domains the incoming ProtectionDomain object array618* @param acc the AccessControlContext whose context is an ProtectionDomain object array619* @param startPos the start index of the domains620*621* @return an ProtectionDomain object array622*/623static ProtectionDomain[] toArrayOfProtectionDomains(Object[] domains, AccessControlContext acc, int startPos) {624final ProtectionDomain[] accDomains = acc == null ? null : acc.context;625ProtectionDomain[] answer = null;626627if (domains == null) {628if (accDomains != null && accDomains.length != 0) {629answer = accDomains;630}631} else if (accDomains == null) {632int domainCount = domains.length - startPos;633for (int i = 0; i < domainCount; ++i) {634if (domains[startPos + i] == null) {635domainCount = i;636break;637}638}639if (domainCount > 0) {640answer = new ProtectionDomain[domainCount];641System.arraycopy(domains, startPos, answer, 0, domainCount);642}643} else {644final int domainCount = domains.length;645final int accDomainCount = accDomains.length;646int newDomainCount = 0;647answer = new ProtectionDomain[domainCount + accDomainCount];648for (int i = startPos; i < domainCount; ++i) {649Object domain = domains[i];650if (domain == null) {651break;652}653for (int j = accDomainCount;;) {654j -= 1;655if (j < 0) {656answer[newDomainCount] = (ProtectionDomain) domain;657newDomainCount += 1;658break;659} else if (accDomains[j] == domain) {660break;661}662}663}664if (newDomainCount + accDomainCount == 0) {665answer = null;666} else if (newDomainCount == 0) {667answer = accDomains;668} else {669if (newDomainCount < domainCount) {670ProtectionDomain[] copy = new ProtectionDomain[newDomainCount + accDomainCount];671System.arraycopy(answer, 0, copy, 0, newDomainCount);672answer = copy;673}674System.arraycopy(accDomains, 0, answer, newDomainCount, accDomainCount);675}676}677678return answer;679}680681/**682* Performs the privileged action specified by <code>action</code>.683* <p>684* When permission checks are made, if the permission has been granted by all685* frames below and including the one representing the call to this method,686* then the permission is granted. In other words, the check stops here.687*688* Any unchecked exception generated by this method will propagate up the chain.689* @param <T> the type of value returned by PrivilegedAction.run690*691* @param action The PrivilegedAction to performed692*693* @return the result of the PrivilegedAction694*695* @exception NullPointerException if action is null696*697* @see #doPrivileged(PrivilegedAction)698*/699/*[PR 1GO8C5O] required for initializeInternal */700@CallerSensitive701public static <T> T doPrivileged(PrivilegedAction<T> action) {702return action.run();703}704705/**706* Performs the privileged action specified by <code>action</code>.707* <p>708* When permission checks are made, if the permission has been granted by all709* frames below and including the one representing the call to this method,710* then the permission is granted iff it is granted by the AccessControlContext711* <code>context</code>. In other words, no more checking of the current stack712* is performed. Instead, the passed in context is checked.713*714* Any unchecked exception generated by this method will propagate up the chain.715* @param <T> the type of value returned by PrivilegedAction.run716*717* @param action The PrivilegedAction to performed718* @param context The AccessControlContext to check719*720* @return the result of the PrivilegedAction721*722* @exception NullPointerException if action is null723*724* @see #doPrivileged(PrivilegedAction)725*/726@CallerSensitive727public static <T> T doPrivileged(PrivilegedAction<T> action, AccessControlContext context) {728T result = action.run();729/*[PR 108112] context is not kept alive*/730keepalive(context);731return result;732}733734/**735* Performs the privileged action specified by <code>action</code>.736* <p>737* When permission checks are made, if the permission has been granted by all738* frames below and including the one representing the call to this method,739* then the permission is granted. In other words, the check stops here.740*741* Any unchecked exception generated by this method will propagate up the chain.742* However, checked exceptions will be caught an re-thrown as PrivilegedActionExceptions743* @param <T> the type of value returned by PrivilegedExceptionAction.run744*745* @param action The PrivilegedExceptionAction to performed746*747* @return the result of the PrivilegedExceptionAction748*749* @throws PrivilegedActionException when a checked exception occurs when performing the action750* NullPointerException if action is null751*752* @see #doPrivileged(PrivilegedAction)753*/754@CallerSensitive755public static <T> T doPrivileged(PrivilegedExceptionAction<T> action)756throws PrivilegedActionException757{758try {759return action.run();760} catch (RuntimeException ex) {761throw ex;762} catch (Exception ex) {763throw new PrivilegedActionException(ex);764}765}766767/**768* Performs the privileged action specified by <code>action</code>.769* <p>770* When permission checks are made, if the permission has been granted by all771* frames below and including the one representing the call to this method,772* then the permission is granted iff it is granted by the AccessControlContext773* <code>context</code>. In other words, no more checking of the current stack774* is performed. Instead, the passed in context is checked.775*776* Any unchecked exception generated by this method will propagate up the chain.777* However, checked exceptions will be caught an re-thrown as PrivilegedActionExceptions778* @param <T> the type of value returned by PrivilegedExceptionAction.run779*780* @param action The PrivilegedExceptionAction to performed781* @param context The AccessControlContext to check782*783* @return the result of the PrivilegedExceptionAction784*785* @throws PrivilegedActionException when a checked exception occurs when performing the action786* NullPointerException if action is null787*788* @see #doPrivileged(PrivilegedAction)789*/790@CallerSensitive791public static <T> T doPrivileged (PrivilegedExceptionAction<T> action, AccessControlContext context)792throws PrivilegedActionException793{794try {795T result = action.run();796/*[PR 108112] context is not kept alive*/797keepalive(context);798return result;799} catch (RuntimeException ex) {800throw ex;801} catch (Exception ex) {802throw new PrivilegedActionException(ex);803}804}805806/**807* Performs the privileged action specified by <code>action</code>, retaining808* any current DomainCombiner.809* <p>810* When permission checks are made, if the permission has been granted by all811* frames below and including the one representing the call to this method,812* then the permission is granted. In other words, the check stops here.813*814* Any unchecked exception generated by this method will propagate up the chain.815* @param <T> the type of value returned by PrivilegedAction.run816*817* @param action The PrivilegedAction to performed818*819* @return the result of the PrivilegedAction820*821* @see #doPrivileged(PrivilegedAction)822*/823@CallerSensitive824public static <T> T doPrivilegedWithCombiner(PrivilegedAction<T> action) {825return doPrivileged(action, getContextHelper(true));826}827828/**829* Performs the privileged action specified by <code>action</code>, retaining830* any current DomainCombiner.831* <p>832* When permission checks are made, if the permission has been granted by all833* frames below and including the one representing the call to this method,834* then the permission is granted. In other words, the check stops here.835*836* Any unchecked exception generated by this method will propagate up the chain.837* However, checked exceptions will be caught an re-thrown as PrivilegedActionExceptions838* @param <T> the type of value returned by PrivilegedExceptionAction.run839*840* @param action The PrivilegedExceptionAction to performed841*842* @return the result of the PrivilegedExceptionAction843*844* @throws PrivilegedActionException when a checked exception occurs when performing the action845*846* @see #doPrivileged(PrivilegedAction)847*/848@CallerSensitive849public static <T> T doPrivilegedWithCombiner(PrivilegedExceptionAction<T> action)850throws PrivilegedActionException851{852return doPrivileged(action, getContextHelper(true));853}854855/**856* Helper method to check if any permission is null857*858* @param perms The Permission arguments to limit the scope of the caller's privileges.859*860* @exception NullPointerException if any perm is null861*862*/863private static void checkPermsNPE(Permission... perms) {864for (int i = 0; i < perms.length; ++i) {865if (null == perms[i]) {866throw new NullPointerException();867}868}869}870871/**872* Performs the privileged action specified by <code>action</code>.873* <p>874* When permission checks are made, if the permission has been granted by all875* frames below and including the one representing the call to this method,876* then the permission is granted iff it is granted by the AccessControlContext877* <code>context</code> and also granted by one of the permissions arguments.878*879* Any unchecked exception generated by this method will propagate up the chain.880* @param <T> the type of value returned by PrivilegedAction.run881*882* @param action The PrivilegedAction to performed883* @param context The AccessControlContext to check884* @param perms The Permission arguments to limit the scope of the caller's privileges.885*886* @return the result of the PrivilegedAction887* @since 1.8888*889* @exception NullPointerException if action is null890*891* @see #doPrivileged(PrivilegedAction)892* @see #doPrivileged(PrivilegedAction, AccessControlContext)893*/894@CallerSensitive895public static <T> T doPrivileged(PrivilegedAction<T> action,896AccessControlContext context, Permission... perms)897{898checkPermsNPE(perms);899T result = action.run();900keepalive(context);901keepalive(perms);902return result;903}904905/**906* Performs the privileged action specified by <code>action</code>, retaining907* any current DomainCombiner.908* <p>909* When permission checks are made, if the permission has been granted by all910* frames below and including the one representing the call to this method,911* then the permission is granted iff it is granted by one of the permissions arguments.912*913* Any unchecked exception generated by this method will propagate up the chain.914* @param <T> the type of value returned by PrivilegedAction.run915*916* @param action The PrivilegedAction to performed917* @param context The AccessControlContext to check918* @param perms The Permission arguments to limit the scope of the caller's privileges.919*920* @return the result of the PrivilegedAction921* @since 1.8922*923* @see #doPrivileged(PrivilegedAction)924* @see #doPrivileged(PrivilegedAction, AccessControlContext)925*/926@CallerSensitive927public static <T> T doPrivilegedWithCombiner(PrivilegedAction<T> action,928AccessControlContext context, Permission... perms)929{930checkPermsNPE(perms);931ProtectionDomain domain = getCallerPD(1);932ProtectionDomain[] pdArray = (domain == null) ? null : new ProtectionDomain[] { domain };933return doPrivileged(action, new AccessControlContext(context, pdArray, getNewAuthorizedState(context, domain)), perms);934}935936/**937* Performs the privileged action specified by <code>action</code>.938* <p>939* When permission checks are made, if the permission has been granted by all940* frames below and including the one representing the call to this method,941* then the permission is granted iff it is granted by the AccessControlContext942* <code>context</code> and also granted by one of the permissions arguments.943*944* Any unchecked exception generated by this method will propagate up the chain.945* However, checked exceptions will be caught an re-thrown as PrivilegedActionExceptions946* @param <T> the type of value returned by PrivilegedExceptionAction.run947*948* @param action The PrivilegedExceptionAction to performed949* @param context The AccessControlContext to check950* @param perms The Permission arguments to limit the scope of the caller's privileges.951*952* @return the result of the PrivilegedExceptionAction953* @since 1.8954*955* @throws PrivilegedActionException when a checked exception occurs when performing the action956* NullPointerException if action is null957*958* @see #doPrivileged(PrivilegedAction)959* @see #doPrivileged(PrivilegedAction, AccessControlContext)960*/961@CallerSensitive962public static <T> T doPrivileged(PrivilegedExceptionAction<T> action,963AccessControlContext context, Permission... perms)964throws PrivilegedActionException965{966try {967checkPermsNPE(perms);968T result = action.run();969keepalive(context);970keepalive(perms);971return result;972} catch (RuntimeException ex) {973throw ex;974} catch (Exception ex) {975throw new PrivilegedActionException(ex);976}977}978979/**980* Performs the privileged action specified by <code>action</code>, retaining981* any current DomainCombiner.982* <p>983* When permission checks are made, if the permission has been granted by all984* frames below and including the one representing the call to this method,985* then the permission is granted and also granted by one of the permissions arguments.986*987* Any unchecked exception generated by this method will propagate up the chain.988* However, checked exceptions will be caught an re-thrown as PrivilegedActionExceptions989* @param <T> the type of value returned by PrivilegedExceptionAction.run990*991* @param action The PrivilegedExceptionAction to performed992* @param context The AccessControlContext to check993* @param perms The Permission arguments to limit the scope of the caller's privileges.994*995* @return the result of the PrivilegedExceptionAction996* @since 1.8997*998* @throws PrivilegedActionException when a checked exception occurs when performing the action999*1000* @see #doPrivileged(PrivilegedAction)1001* @see #doPrivileged(PrivilegedAction, AccessControlContext)1002*/1003public static <T> T doPrivilegedWithCombiner(PrivilegedExceptionAction<T> action,1004AccessControlContext context, Permission... perms)1005throws PrivilegedActionException1006{1007checkPermsNPE(perms);1008ProtectionDomain domain = getCallerPD(1);1009ProtectionDomain[] pdArray = (domain == null) ? null : new ProtectionDomain[] { domain };1010return doPrivileged(action, new AccessControlContext(context, pdArray, getNewAuthorizedState(context, domain)), perms);1011}10121013}101410151016