mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 14:54:52 +02:00
8212605: Pure-Java implementation of AccessController.doPrivileged
Reviewed-by: dholmes, mullan, vlivanov, mchung, alanb, rriggs
This commit is contained in:
parent
c8c41d1444
commit
a9ae141836
24 changed files with 213 additions and 450 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -25,9 +25,18 @@
|
|||
|
||||
package java.security;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.ref.Reference;
|
||||
import sun.security.util.Debug;
|
||||
import sun.security.util.SecurityConstants;
|
||||
import jdk.internal.reflect.CallerSensitive;
|
||||
import jdk.internal.reflect.Reflection;
|
||||
import jdk.internal.vm.annotation.DontInline;
|
||||
import jdk.internal.vm.annotation.ForceInline;
|
||||
import jdk.internal.vm.annotation.ReservedStackAccess;
|
||||
|
||||
/**
|
||||
* <p> The AccessController class is used for access control operations
|
||||
|
@ -296,7 +305,10 @@ public final class AccessController {
|
|||
*/
|
||||
|
||||
@CallerSensitive
|
||||
public static native <T> T doPrivileged(PrivilegedAction<T> action);
|
||||
public static <T> T doPrivileged(PrivilegedAction<T> action)
|
||||
{
|
||||
return executePrivileged(action, null, Reflection.getCallerClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the specified {@code PrivilegedAction} with privileges
|
||||
|
@ -369,8 +381,13 @@ public final class AccessController {
|
|||
* @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
|
||||
*/
|
||||
@CallerSensitive
|
||||
public static native <T> T doPrivileged(PrivilegedAction<T> action,
|
||||
AccessControlContext context);
|
||||
public static <T> T doPrivileged(PrivilegedAction<T> action,
|
||||
AccessControlContext context)
|
||||
{
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
context = checkContext(context, caller);
|
||||
return executePrivileged(action, context, caller);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
@ -425,7 +442,7 @@ public final class AccessController {
|
|||
if (perms == null) {
|
||||
throw new NullPointerException("null permissions parameter");
|
||||
}
|
||||
Class <?> caller = Reflection.getCallerClass();
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
return AccessController.doPrivileged(action, createWrapper(null,
|
||||
caller, parent, context, perms));
|
||||
}
|
||||
|
@ -491,7 +508,7 @@ public final class AccessController {
|
|||
if (perms == null) {
|
||||
throw new NullPointerException("null permissions parameter");
|
||||
}
|
||||
Class <?> caller = Reflection.getCallerClass();
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
return AccessController.doPrivileged(action, createWrapper(dc, caller,
|
||||
parent, context, perms));
|
||||
}
|
||||
|
@ -524,10 +541,20 @@ public final class AccessController {
|
|||
* @see java.security.DomainCombiner
|
||||
*/
|
||||
@CallerSensitive
|
||||
public static native <T> T
|
||||
public static <T> T
|
||||
doPrivileged(PrivilegedExceptionAction<T> action)
|
||||
throws PrivilegedActionException;
|
||||
|
||||
throws PrivilegedActionException
|
||||
{
|
||||
AccessControlContext context = null;
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
try {
|
||||
return executePrivileged(action, context, caller);
|
||||
} catch (RuntimeException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw wrapException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the specified {@code PrivilegedExceptionAction} with
|
||||
|
@ -587,11 +614,11 @@ public final class AccessController {
|
|||
AccessControlContext parent, AccessControlContext context,
|
||||
Permission[] perms)
|
||||
{
|
||||
ProtectionDomain callerPD = getCallerPD(caller);
|
||||
ProtectionDomain callerPD = getProtectionDomain(caller);
|
||||
// check if caller is authorized to create context
|
||||
if (context != null && !context.isAuthorized() &&
|
||||
System.getSecurityManager() != null &&
|
||||
!callerPD.impliesCreateAccessControlContext())
|
||||
if (System.getSecurityManager() != null &&
|
||||
context != null && !context.isAuthorized() &&
|
||||
!callerPD.implies(SecurityConstants.CREATE_ACC_PERMISSION))
|
||||
{
|
||||
return getInnocuousAcc();
|
||||
} else {
|
||||
|
@ -611,16 +638,7 @@ public final class AccessController {
|
|||
return AccHolder.innocuousAcc;
|
||||
}
|
||||
|
||||
private static ProtectionDomain getCallerPD(final Class <?> caller) {
|
||||
ProtectionDomain callerPd = doPrivileged
|
||||
(new PrivilegedAction<>() {
|
||||
public ProtectionDomain run() {
|
||||
return caller.getProtectionDomain();
|
||||
}
|
||||
});
|
||||
|
||||
return callerPd;
|
||||
}
|
||||
private static native ProtectionDomain getProtectionDomain(final Class<?> caller);
|
||||
|
||||
/**
|
||||
* Performs the specified {@code PrivilegedExceptionAction} with
|
||||
|
@ -659,11 +677,125 @@ public final class AccessController {
|
|||
* @see #doPrivileged(PrivilegedAction,AccessControlContext)
|
||||
*/
|
||||
@CallerSensitive
|
||||
public static native <T> T
|
||||
public static <T> T
|
||||
doPrivileged(PrivilegedExceptionAction<T> action,
|
||||
AccessControlContext context)
|
||||
throws PrivilegedActionException;
|
||||
throws PrivilegedActionException
|
||||
{
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
context = checkContext(context, caller);
|
||||
try {
|
||||
return executePrivileged(action, context, caller);
|
||||
} catch (RuntimeException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw wrapException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static AccessControlContext checkContext(AccessControlContext context,
|
||||
Class<?> caller)
|
||||
{
|
||||
// check if caller is authorized to create context
|
||||
if (System.getSecurityManager() != null &&
|
||||
context != null && !context.isAuthorized() &&
|
||||
context != getInnocuousAcc())
|
||||
{
|
||||
ProtectionDomain callerPD = getProtectionDomain(caller);
|
||||
if (callerPD != null && !callerPD.implies(SecurityConstants.CREATE_ACC_PERMISSION)) {
|
||||
return getInnocuousAcc();
|
||||
}
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanity check that the caller context is indeed privileged.
|
||||
*
|
||||
* Used by executePrivileged to make sure the frame is properly
|
||||
* recognized by the VM.
|
||||
*/
|
||||
private static boolean isPrivileged() {
|
||||
AccessControlContext ctx = getStackAccessControlContext();
|
||||
return ctx == null || ctx.isPrivileged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the action as privileged.
|
||||
*
|
||||
* The VM recognizes this method as special, so any changes to the
|
||||
* name or signature require corresponding changes in
|
||||
* getStackAccessControlContext().
|
||||
*/
|
||||
@Hidden
|
||||
@ForceInline
|
||||
private static <T> T
|
||||
executePrivileged(PrivilegedAction<T> action,
|
||||
AccessControlContext context,
|
||||
Class<?> caller)
|
||||
{
|
||||
assert isPrivileged(); // sanity check invariant
|
||||
T result = action.run();
|
||||
assert isPrivileged(); // sanity check invariant
|
||||
|
||||
// Keep these alive across the run() call so they can be
|
||||
// retrieved by getStackAccessControlContext().
|
||||
Reference.reachabilityFence(context);
|
||||
Reference.reachabilityFence(caller);
|
||||
Reference.reachabilityFence(action);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the action as privileged.
|
||||
*
|
||||
* The VM recognizes this method as special, so any changes to the
|
||||
* name or signature require corresponding changes in
|
||||
* getStackAccessControlContext().
|
||||
*/
|
||||
@Hidden
|
||||
@ForceInline
|
||||
private static <T> T
|
||||
executePrivileged(PrivilegedExceptionAction<T> action,
|
||||
AccessControlContext context,
|
||||
Class<?> caller)
|
||||
throws Exception
|
||||
{
|
||||
assert isPrivileged(); // sanity check invariant
|
||||
T result = action.run();
|
||||
assert isPrivileged(); // sanity check invariant
|
||||
|
||||
// Keep these alive across the run() call so they can be
|
||||
// retrieved by getStackAccessControlContext().
|
||||
Reference.reachabilityFence(context);
|
||||
Reference.reachabilityFence(caller);
|
||||
Reference.reachabilityFence(action);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Internal marker for hidden implementation frames.
|
||||
*/
|
||||
/*non-public*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface Hidden {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Wrap an exception. The annotations are used in a best effort to
|
||||
* avoid StackOverflowError in the caller. Inlining the callees as
|
||||
* well and tail-call elimination could also help here, but are not
|
||||
* needed for correctness, only quality of implementation.
|
||||
*/
|
||||
@Hidden
|
||||
@ForceInline
|
||||
@ReservedStackAccess
|
||||
private static PrivilegedActionException wrapException(Exception e) {
|
||||
return new PrivilegedActionException(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the specified {@code PrivilegedExceptionAction} with
|
||||
|
@ -720,7 +852,7 @@ public final class AccessController {
|
|||
if (perms == null) {
|
||||
throw new NullPointerException("null permissions parameter");
|
||||
}
|
||||
Class <?> caller = Reflection.getCallerClass();
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
return AccessController.doPrivileged(action, createWrapper(null, caller, parent, context, perms));
|
||||
}
|
||||
|
||||
|
@ -789,7 +921,7 @@ public final class AccessController {
|
|||
if (perms == null) {
|
||||
throw new NullPointerException("null permissions parameter");
|
||||
}
|
||||
Class <?> caller = Reflection.getCallerClass();
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
return AccessController.doPrivileged(action, createWrapper(dc, caller,
|
||||
parent, context, perms));
|
||||
}
|
||||
|
|
|
@ -394,11 +394,6 @@ public class ProtectionDomain {
|
|||
return false;
|
||||
}
|
||||
|
||||
// called by the VM -- do not remove
|
||||
boolean impliesCreateAccessControlContext() {
|
||||
return implies(SecurityConstants.CREATE_ACC_PERMISSION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a ProtectionDomain to a String.
|
||||
*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue