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