Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/share/classes/java/security/AccessController.java
41152 views
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
*/
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
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
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
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
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
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
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
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")
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
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")
661
private static AccessControlContext getInnocuousAcc() {
662
return AccHolder.innocuousAcc;
663
}
664
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
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")
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
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
*/
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
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
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
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
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
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")
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")
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")
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")
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
1072