1 /* 2 * Copyright (c) 1997, 2019, 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 */ 275 276 public final class AccessController { 277 278 /** 279 * Don't allow anyone to instantiate an AccessController 280 */ 281 private AccessController() { } 282 283 /** 284 * Performs the specified {@code PrivilegedAction} with privileges 285 * enabled. The action is performed with <i>all</i> of the permissions 286 * possessed by the caller's protection domain. 287 * 288 * <p> If the action's {@code run} method throws an (unchecked) 289 * exception, it will propagate through this method. 290 * 291 * <p> Note that any DomainCombiner associated with the current 292 * AccessControlContext will be ignored while the action is performed. 293 * 294 * @param <T> the type of the value returned by the PrivilegedAction's 295 * {@code run} method. 296 * 297 * @param action the action to be performed. 298 * 299 * @return the value returned by the action's {@code run} method. 300 * 301 * @exception NullPointerException if the action is {@code null} 302 * 303 * @see #doPrivileged(PrivilegedAction,AccessControlContext) 304 * @see #doPrivileged(PrivilegedExceptionAction) 305 * @see #doPrivilegedWithCombiner(PrivilegedAction) 306 * @see java.security.DomainCombiner 307 */ 308 309 @CallerSensitive 310 public static <T> T doPrivileged(PrivilegedAction<T> action) 311 { 312 return executePrivileged(action, null, Reflection.getCallerClass()); 313 } 314 315 /** 316 * Performs the specified {@code PrivilegedAction} with privileges 317 * enabled. The action is performed with <i>all</i> of the permissions 318 * possessed by the caller's protection domain. 319 * 320 * <p> If the action's {@code run} method throws an (unchecked) 321 * exception, it will propagate through this method. 322 * 323 * <p> This method preserves the current AccessControlContext's 324 * DomainCombiner (which may be null) while the action is performed. 325 * 326 * @param <T> the type of the value returned by the PrivilegedAction's 327 * {@code run} method. 328 * 329 * @param action the action to be performed. 330 * 331 * @return the value returned by the action's {@code run} method. 332 * 333 * @exception NullPointerException if the action is {@code null} 334 * 335 * @see #doPrivileged(PrivilegedAction) 336 * @see java.security.DomainCombiner 337 * 338 * @since 1.6 339 */ 340 @CallerSensitive 341 public static <T> T doPrivilegedWithCombiner(PrivilegedAction<T> action) { 342 AccessControlContext acc = getStackAccessControlContext(); 343 if (acc == null) { 344 return AccessController.doPrivileged(action); 345 } 346 DomainCombiner dc = acc.getAssignedCombiner(); 347 return AccessController.doPrivileged(action, 348 preserveCombiner(dc, Reflection.getCallerClass())); 349 } 350 351 352 /** 353 * Performs the specified {@code PrivilegedAction} with privileges 354 * enabled and restricted by the specified {@code AccessControlContext}. 355 * The action is performed with the intersection of the permissions 356 * possessed by the caller's protection domain, and those possessed 357 * by the domains represented by the specified {@code AccessControlContext}. 358 * <p> 359 * If the action's {@code run} method throws an (unchecked) exception, 360 * it will propagate through this method. 361 * <p> 362 * If a security manager is installed and the specified 363 * {@code AccessControlContext} was not created by system code and the 364 * caller's {@code ProtectionDomain} has not been granted the 365 * {@literal "createAccessControlContext"} 366 * {@link java.security.SecurityPermission}, then the action is performed 367 * with no permissions. 368 * 369 * @param <T> the type of the value returned by the PrivilegedAction's 370 * {@code run} method. 371 * @param action the action to be performed. 372 * @param context an <i>access control context</i> 373 * representing the restriction to be applied to the 374 * caller's domain's privileges before performing 375 * the specified action. If the context is 376 * {@code null}, then no additional restriction is applied. 377 * 378 * @return the value returned by the action's {@code run} method. 379 * 380 * @exception NullPointerException if the action is {@code null} 381 * 382 * @see #doPrivileged(PrivilegedAction) 383 * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext) 384 */ 385 @CallerSensitive 386 public static <T> T doPrivileged(PrivilegedAction<T> action, 387 AccessControlContext context) 388 { 389 Class<?> caller = Reflection.getCallerClass(); 390 context = checkContext(context, caller); 391 return executePrivileged(action, context, caller); 392 } 393 394 395 /** 396 * Performs the specified {@code PrivilegedAction} with privileges 397 * enabled and restricted by the specified 398 * {@code AccessControlContext} and with a privilege scope limited 399 * by specified {@code Permission} arguments. 400 * 401 * The action is performed with the intersection of the permissions 402 * possessed by the caller's protection domain, and those possessed 403 * by the domains represented by the specified 404 * {@code AccessControlContext}. 405 * <p> 406 * If the action's {@code run} method throws an (unchecked) exception, 407 * it will propagate through this method. 408 * <p> 409 * If a security manager is installed and the specified 410 * {@code AccessControlContext} was not created by system code and the 411 * caller's {@code ProtectionDomain} has not been granted the 412 * {@literal "createAccessControlContext"} 413 * {@link java.security.SecurityPermission}, then the action is performed 414 * with no permissions. 415 * 416 * @param <T> the type of the value returned by the PrivilegedAction's 417 * {@code run} method. 418 * @param action the action to be performed. 419 * @param context an <i>access control context</i> 420 * representing the restriction to be applied to the 421 * caller's domain's privileges before performing 422 * the specified action. If the context is 423 * {@code null}, 424 * then no additional restriction is applied. 425 * @param perms the {@code Permission} arguments which limit the 426 * scope of the caller's privileges. The number of arguments 427 * is variable. 428 * 429 * @return the value returned by the action's {@code run} method. 430 * 431 * @throws NullPointerException if action or perms or any element of 432 * perms is {@code null} 433 * 434 * @see #doPrivileged(PrivilegedAction) 435 * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext) 436 * 437 * @since 1.8 438 */ 439 @CallerSensitive 440 public static <T> T doPrivileged(PrivilegedAction<T> action, 441 AccessControlContext context, Permission... perms) { 442 443 AccessControlContext parent = getContext(); 444 if (perms == null) { 445 throw new NullPointerException("null permissions parameter"); 446 } 447 Class<?> caller = Reflection.getCallerClass(); 448 DomainCombiner dc = (context == null) ? null : context.getCombiner(); 449 return AccessController.doPrivileged(action, createWrapper(dc, 450 caller, parent, context, perms)); 451 } 452 453 454 /** 455 * Performs the specified {@code PrivilegedAction} with privileges 456 * enabled and restricted by the specified 457 * {@code AccessControlContext} and with a privilege scope limited 458 * by specified {@code Permission} arguments. 459 * 460 * The action is performed with the intersection of the permissions 461 * possessed by the caller's protection domain, and those possessed 462 * by the domains represented by the specified 463 * {@code AccessControlContext}. 464 * <p> 465 * If the action's {@code run} method throws an (unchecked) exception, 466 * it will propagate through this method. 467 * 468 * <p> This method preserves the current AccessControlContext's 469 * DomainCombiner (which may be null) while the action is performed. 470 * <p> 471 * If a security manager is installed and the specified 472 * {@code AccessControlContext} was not created by system code and the 473 * caller's {@code ProtectionDomain} has not been granted the 474 * {@literal "createAccessControlContext"} 475 * {@link java.security.SecurityPermission}, then the action is performed 476 * with no permissions. 477 * 478 * @param <T> the type of the value returned by the PrivilegedAction's 479 * {@code run} method. 480 * @param action the action to be performed. 481 * @param context an <i>access control context</i> 482 * representing the restriction to be applied to the 483 * caller's domain's privileges before performing 484 * the specified action. If the context is 485 * {@code null}, 486 * then no additional restriction is applied. 487 * @param perms the {@code Permission} arguments which limit the 488 * scope of the caller's privileges. The number of arguments 489 * is variable. 490 * 491 * @return the value returned by the action's {@code run} method. 492 * 493 * @throws NullPointerException if action or perms or any element of 494 * perms is {@code null} 495 * 496 * @see #doPrivileged(PrivilegedAction) 497 * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext) 498 * @see java.security.DomainCombiner 499 * 500 * @since 1.8 501 */ 502 @CallerSensitive 503 public static <T> T doPrivilegedWithCombiner(PrivilegedAction<T> action, 504 AccessControlContext context, Permission... perms) { 505 506 AccessControlContext parent = getContext(); 507 DomainCombiner dc = parent.getCombiner(); 508 if (dc == null && context != null) { 509 dc = context.getCombiner(); 510 } 511 if (perms == null) { 512 throw new NullPointerException("null permissions parameter"); 513 } 514 Class<?> caller = Reflection.getCallerClass(); 515 return AccessController.doPrivileged(action, createWrapper(dc, caller, 516 parent, context, perms)); 517 } 518 519 /** 520 * Performs the specified {@code PrivilegedExceptionAction} with 521 * privileges enabled. The action is performed with <i>all</i> of the 522 * permissions possessed by the caller's protection domain. 523 * 524 * <p> If the action's {@code run} method throws an <i>unchecked</i> 525 * exception, it will propagate through this method. 526 * 527 * <p> Note that any DomainCombiner associated with the current 528 * AccessControlContext will be ignored while the action is performed. 529 * 530 * @param <T> the type of the value returned by the 531 * PrivilegedExceptionAction's {@code run} method. 532 * 533 * @param action the action to be performed 534 * 535 * @return the value returned by the action's {@code run} method 536 * 537 * @exception PrivilegedActionException if the specified action's 538 * {@code run} method threw a <i>checked</i> exception 539 * @exception NullPointerException if the action is {@code null} 540 * 541 * @see #doPrivileged(PrivilegedAction) 542 * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext) 543 * @see #doPrivilegedWithCombiner(PrivilegedExceptionAction) 544 * @see java.security.DomainCombiner 545 */ 546 @CallerSensitive 547 public static <T> T 548 doPrivileged(PrivilegedExceptionAction<T> action) 549 throws PrivilegedActionException 550 { 551 AccessControlContext context = null; 552 Class<?> caller = Reflection.getCallerClass(); 553 try { 554 return executePrivileged(action, context, caller); 555 } catch (RuntimeException e) { 556 throw e; 557 } catch (Exception e) { 558 throw wrapException(e); 559 } 560 } 561 562 /** 563 * Performs the specified {@code PrivilegedExceptionAction} with 564 * privileges enabled. The action is performed with <i>all</i> of the 565 * permissions possessed by the caller's protection domain. 566 * 567 * <p> If the action's {@code run} method throws an <i>unchecked</i> 568 * exception, it will propagate through this method. 569 * 570 * <p> This method preserves the current AccessControlContext's 571 * DomainCombiner (which may be null) while the action is performed. 572 * 573 * @param <T> the type of the value returned by the 574 * PrivilegedExceptionAction's {@code run} method. 575 * 576 * @param action the action to be performed. 577 * 578 * @return the value returned by the action's {@code run} method 579 * 580 * @exception PrivilegedActionException if the specified action's 581 * {@code run} method threw a <i>checked</i> exception 582 * @exception NullPointerException if the action is {@code null} 583 * 584 * @see #doPrivileged(PrivilegedAction) 585 * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext) 586 * @see java.security.DomainCombiner 587 * 588 * @since 1.6 589 */ 590 @CallerSensitive 591 public static <T> T doPrivilegedWithCombiner(PrivilegedExceptionAction<T> action) 592 throws PrivilegedActionException 593 { 594 AccessControlContext acc = getStackAccessControlContext(); 595 if (acc == null) { 596 return AccessController.doPrivileged(action); 597 } 598 DomainCombiner dc = acc.getAssignedCombiner(); 599 return AccessController.doPrivileged(action, 600 preserveCombiner(dc, Reflection.getCallerClass())); 601 } 602 603 /** 604 * preserve the combiner across the doPrivileged call 605 */ 606 private static AccessControlContext preserveCombiner(DomainCombiner combiner, 607 Class<?> caller) 608 { 609 return createWrapper(combiner, caller, null, null, null); 610 } 611 612 /** 613 * Create a wrapper to contain the limited privilege scope data. 614 */ 615 private static AccessControlContext 616 createWrapper(DomainCombiner combiner, Class<?> caller, 617 AccessControlContext parent, AccessControlContext context, 618 Permission[] perms) 619 { 620 ProtectionDomain callerPD = getProtectionDomain(caller); 621 // check if caller is authorized to create context 622 if (System.getSecurityManager() != null && 623 context != null && !context.isAuthorized() && 624 !callerPD.implies(SecurityConstants.CREATE_ACC_PERMISSION)) 625 { 626 return getInnocuousAcc(); 627 } else { 628 return new AccessControlContext(callerPD, combiner, parent, 629 context, perms); 630 } 631 } 632 633 private static class AccHolder { 634 // An AccessControlContext with no granted permissions. 635 // Only initialized on demand when getInnocuousAcc() is called. 636 static final AccessControlContext innocuousAcc = 637 new AccessControlContext(new ProtectionDomain[] { 638 new ProtectionDomain(null, null) }); 639 } 640 private static AccessControlContext getInnocuousAcc() { 641 return AccHolder.innocuousAcc; 642 } 643 644 private static native ProtectionDomain getProtectionDomain(final Class<?> caller); 645 646 /** 647 * Performs the specified {@code PrivilegedExceptionAction} with 648 * privileges enabled and restricted by the specified 649 * {@code AccessControlContext}. The action is performed with the 650 * intersection of the permissions possessed by the caller's 651 * protection domain, and those possessed by the domains represented by the 652 * specified {@code AccessControlContext}. 653 * <p> 654 * If the action's {@code run} method throws an <i>unchecked</i> 655 * exception, it will propagate through this method. 656 * <p> 657 * If a security manager is installed and the specified 658 * {@code AccessControlContext} was not created by system code and the 659 * caller's {@code ProtectionDomain} has not been granted the 660 * {@literal "createAccessControlContext"} 661 * {@link java.security.SecurityPermission}, then the action is performed 662 * with no permissions. 663 * 664 * @param <T> the type of the value returned by the 665 * PrivilegedExceptionAction's {@code run} method. 666 * @param action the action to be performed 667 * @param context an <i>access control context</i> 668 * representing the restriction to be applied to the 669 * caller's domain's privileges before performing 670 * the specified action. If the context is 671 * {@code null}, then no additional restriction is applied. 672 * 673 * @return the value returned by the action's {@code run} method 674 * 675 * @exception PrivilegedActionException if the specified action's 676 * {@code run} method threw a <i>checked</i> exception 677 * @exception NullPointerException if the action is {@code null} 678 * 679 * @see #doPrivileged(PrivilegedAction) 680 * @see #doPrivileged(PrivilegedAction,AccessControlContext) 681 */ 682 @CallerSensitive 683 public static <T> T 684 doPrivileged(PrivilegedExceptionAction<T> action, 685 AccessControlContext context) 686 throws PrivilegedActionException 687 { 688 Class<?> caller = Reflection.getCallerClass(); 689 context = checkContext(context, caller); 690 try { 691 return executePrivileged(action, context, caller); 692 } catch (RuntimeException e) { 693 throw e; 694 } catch (Exception e) { 695 throw wrapException(e); 696 } 697 } 698 699 private static AccessControlContext checkContext(AccessControlContext context, 700 Class<?> caller) 701 { 702 // check if caller is authorized to create context 703 if (System.getSecurityManager() != null && 704 context != null && !context.isAuthorized() && 705 context != getInnocuousAcc()) 706 { 707 ProtectionDomain callerPD = getProtectionDomain(caller); 708 if (callerPD != null && !callerPD.implies(SecurityConstants.CREATE_ACC_PERMISSION)) { 709 return getInnocuousAcc(); 710 } 711 } 712 return context; 713 } 714 715 /** 716 * The value needs to be physically located in the frame, so that it 717 * can be found by a stack walk. 718 */ 719 @Hidden 720 private static native void ensureMaterializedForStackWalk(Object o); 721 722 /** 723 * Sanity check that the caller context is indeed privileged. 724 * 725 * Used by executePrivileged to make sure the frame is properly 726 * recognized by the VM. 727 */ 728 private static boolean isPrivileged() { 729 AccessControlContext ctx = getStackAccessControlContext(); 730 return ctx == null || ctx.isPrivileged(); 731 } 732 733 /** 734 * Execute the action as privileged. 735 * 736 * The VM recognizes this method as special, so any changes to the 737 * name or signature require corresponding changes in 738 * getStackAccessControlContext(). 739 */ 740 @Hidden 741 @ForceInline 742 private static <T> T 743 executePrivileged(PrivilegedAction<T> action, 744 AccessControlContext context, 745 Class<?> caller) 746 { 747 // Ensure context has a physical value in the frame 748 if (context != null) { 749 ensureMaterializedForStackWalk(context); 750 } 751 752 assert isPrivileged(); // sanity check invariant 753 T result = action.run(); 754 assert isPrivileged(); // sanity check invariant 755 756 // Keep these alive across the run() call so they can be 757 // retrieved by getStackAccessControlContext(). 758 Reference.reachabilityFence(context); 759 Reference.reachabilityFence(caller); 760 return result; 761 } 762 763 /** 764 * Execute the action as privileged. 765 * 766 * The VM recognizes this method as special, so any changes to the 767 * name or signature require corresponding changes in 768 * getStackAccessControlContext(). 769 */ 770 @Hidden 771 @ForceInline 772 private static <T> T 773 executePrivileged(PrivilegedExceptionAction<T> action, 774 AccessControlContext context, 775 Class<?> caller) 776 throws Exception 777 { 778 // Ensure context has a physical value in the frame 779 if (context != null) { 780 ensureMaterializedForStackWalk(context); 781 } 782 783 assert isPrivileged(); // sanity check invariant 784 T result = action.run(); 785 assert isPrivileged(); // sanity check invariant 786 787 // Keep these alive across the run() call so they can be 788 // retrieved by getStackAccessControlContext(). 789 Reference.reachabilityFence(context); 790 Reference.reachabilityFence(caller); 791 return result; 792 } 793 794 795 /** 796 * Wrap an exception. The annotations are used in a best effort to 797 * avoid StackOverflowError in the caller. Inlining the callees as 798 * well and tail-call elimination could also help here, but are not 799 * needed for correctness, only quality of implementation. 800 */ 801 @Hidden 802 @ForceInline 803 @ReservedStackAccess 804 private static PrivilegedActionException wrapException(Exception e) { 805 return new PrivilegedActionException(e); 806 } 807 808 /** 809 * Performs the specified {@code PrivilegedExceptionAction} with 810 * privileges enabled and restricted by the specified 811 * {@code AccessControlContext} and with a privilege scope limited by 812 * specified {@code Permission} arguments. 813 * 814 * The action is performed with the intersection of the permissions 815 * possessed by the caller's protection domain, and those possessed 816 * by the domains represented by the specified 817 * {@code AccessControlContext}. 818 * <p> 819 * If the action's {@code run} method throws an (unchecked) exception, 820 * it will propagate through this method. 821 * <p> 822 * If a security manager is installed and the specified 823 * {@code AccessControlContext} was not created by system code and the 824 * caller's {@code ProtectionDomain} has not been granted the 825 * {@literal "createAccessControlContext"} 826 * {@link java.security.SecurityPermission}, then the action is performed 827 * with no permissions. 828 * 829 * @param <T> the type of the value returned by the 830 * PrivilegedExceptionAction's {@code run} method. 831 * @param action the action to be performed. 832 * @param context an <i>access control context</i> 833 * representing the restriction to be applied to the 834 * caller's domain's privileges before performing 835 * the specified action. If the context is 836 * {@code null}, 837 * then no additional restriction is applied. 838 * @param perms the {@code Permission} arguments which limit the 839 * scope of the caller's privileges. The number of arguments 840 * is variable. 841 * 842 * @return the value returned by the action's {@code run} method. 843 * 844 * @throws PrivilegedActionException if the specified action's 845 * {@code run} method threw a <i>checked</i> exception 846 * @throws NullPointerException if action or perms or any element of 847 * perms is {@code null} 848 * 849 * @see #doPrivileged(PrivilegedAction) 850 * @see #doPrivileged(PrivilegedAction,AccessControlContext) 851 * 852 * @since 1.8 853 */ 854 @CallerSensitive 855 public static <T> T doPrivileged(PrivilegedExceptionAction<T> action, 856 AccessControlContext context, Permission... perms) 857 throws PrivilegedActionException 858 { 859 AccessControlContext parent = getContext(); 860 if (perms == null) { 861 throw new NullPointerException("null permissions parameter"); 862 } 863 Class<?> caller = Reflection.getCallerClass(); 864 DomainCombiner dc = (context == null) ? null : context.getCombiner(); 865 return AccessController.doPrivileged(action, createWrapper(dc, caller, parent, context, perms)); 866 } 867 868 869 /** 870 * Performs the specified {@code PrivilegedExceptionAction} with 871 * privileges enabled and restricted by the specified 872 * {@code AccessControlContext} and with a privilege scope limited by 873 * specified {@code Permission} arguments. 874 * 875 * The action is performed with the intersection of the permissions 876 * possessed by the caller's protection domain, and those possessed 877 * by the domains represented by the specified 878 * {@code AccessControlContext}. 879 * <p> 880 * If the action's {@code run} method throws an (unchecked) exception, 881 * it will propagate through this method. 882 * 883 * <p> This method preserves the current AccessControlContext's 884 * DomainCombiner (which may be null) while the action is performed. 885 * <p> 886 * If a security manager is installed and the specified 887 * {@code AccessControlContext} was not created by system code and the 888 * caller's {@code ProtectionDomain} has not been granted the 889 * {@literal "createAccessControlContext"} 890 * {@link java.security.SecurityPermission}, then the action is performed 891 * with no permissions. 892 * 893 * @param <T> the type of the value returned by the 894 * PrivilegedExceptionAction's {@code run} method. 895 * @param action the action to be performed. 896 * @param context an <i>access control context</i> 897 * representing the restriction to be applied to the 898 * caller's domain's privileges before performing 899 * the specified action. If the context is 900 * {@code null}, 901 * then no additional restriction is applied. 902 * @param perms the {@code Permission} arguments which limit the 903 * scope of the caller's privileges. The number of arguments 904 * is variable. 905 * 906 * @return the value returned by the action's {@code run} method. 907 * 908 * @throws PrivilegedActionException if the specified action's 909 * {@code run} method threw a <i>checked</i> exception 910 * @throws NullPointerException if action or perms or any element of 911 * perms is {@code null} 912 * 913 * @see #doPrivileged(PrivilegedAction) 914 * @see #doPrivileged(PrivilegedAction,AccessControlContext) 915 * @see java.security.DomainCombiner 916 * 917 * @since 1.8 918 */ 919 @CallerSensitive 920 public static <T> T doPrivilegedWithCombiner(PrivilegedExceptionAction<T> action, 921 AccessControlContext context, 922 Permission... perms) 923 throws PrivilegedActionException 924 { 925 AccessControlContext parent = getContext(); 926 DomainCombiner dc = parent.getCombiner(); 927 if (dc == null && context != null) { 928 dc = context.getCombiner(); 929 } 930 if (perms == null) { 931 throw new NullPointerException("null permissions parameter"); 932 } 933 Class<?> caller = Reflection.getCallerClass(); 934 return AccessController.doPrivileged(action, createWrapper(dc, caller, 935 parent, context, perms)); 936 } 937 938 /** 939 * Returns the AccessControl context. i.e., it gets 940 * the protection domains of all the callers on the stack, 941 * starting at the first class with a non-null 942 * ProtectionDomain. 943 * 944 * @return the access control context based on the current stack or 945 * null if there was only privileged system code. 946 */ 947 948 private static native AccessControlContext getStackAccessControlContext(); 949 950 951 /** 952 * Returns the "inherited" AccessControl context. This is the context 953 * that existed when the thread was created. Package private so 954 * AccessControlContext can use it. 955 */ 956 957 static native AccessControlContext getInheritedAccessControlContext(); 958 959 /** 960 * This method takes a "snapshot" of the current calling context, which 961 * includes the current Thread's inherited AccessControlContext and any 962 * limited privilege scope, and places it in an AccessControlContext object. 963 * This context may then be checked at a later point, possibly in another thread. 964 * 965 * @see AccessControlContext 966 * 967 * @return the AccessControlContext based on the current context. 968 */ 969 970 public static AccessControlContext getContext() 971 { 972 AccessControlContext acc = getStackAccessControlContext(); 973 if (acc == null) { 974 // all we had was privileged system code. We don't want 975 // to return null though, so we construct a real ACC. 976 return new AccessControlContext(null, true); 977 } else { 978 return acc.optimize(); 979 } 980 } 981 982 /** 983 * Determines whether the access request indicated by the 984 * specified permission should be allowed or denied, based on 985 * the current AccessControlContext and security policy. 986 * This method quietly returns if the access request 987 * is permitted, or throws an AccessControlException otherwise. The 988 * getPermission method of the AccessControlException returns the 989 * {@code perm} Permission object instance. 990 * 991 * @param perm the requested permission. 992 * 993 * @exception AccessControlException if the specified permission 994 * is not permitted, based on the current security policy. 995 * @exception NullPointerException if the specified permission 996 * is {@code null} and is checked based on the 997 * security policy currently in effect. 998 */ 999 1000 public static void checkPermission(Permission perm) 1001 throws AccessControlException 1002 { 1003 //System.err.println("checkPermission "+perm); 1004 //Thread.currentThread().dumpStack(); 1005 1006 if (perm == null) { 1007 throw new NullPointerException("permission can't be null"); 1008 } 1009 1010 AccessControlContext stack = getStackAccessControlContext(); 1011 // if context is null, we had privileged system code on the stack. 1012 if (stack == null) { 1013 Debug debug = AccessControlContext.getDebug(); 1014 boolean dumpDebug = false; 1015 if (debug != null) { 1016 dumpDebug = !Debug.isOn("codebase="); 1017 dumpDebug &= !Debug.isOn("permission=") || 1018 Debug.isOn("permission=" + perm.getClass().getCanonicalName()); 1019 } 1020 1021 if (dumpDebug && Debug.isOn("stack")) { 1022 Thread.dumpStack(); 1023 } 1024 1025 if (dumpDebug && Debug.isOn("domain")) { 1026 debug.println("domain (context is null)"); 1027 } 1028 1029 if (dumpDebug) { 1030 debug.println("access allowed "+perm); 1031 } 1032 return; 1033 } 1034 1035 AccessControlContext acc = stack.optimize(); 1036 acc.checkPermission(perm); 1037 } 1038 }