8014097: add doPrivileged methods with limited privilege scope
Reviewed-by: mchung
This commit is contained in:
parent
6ffe8293b9
commit
c0c2397857
@ -85,6 +85,15 @@ public final class AccessControlContext {
|
||||
|
||||
private DomainCombiner combiner = null;
|
||||
|
||||
// limited privilege scope
|
||||
private Permission permissions[];
|
||||
private AccessControlContext parent;
|
||||
private boolean isWrapped;
|
||||
|
||||
// is constrained by limited privilege scope?
|
||||
private boolean isLimited;
|
||||
private ProtectionDomain limitedContext[];
|
||||
|
||||
private static boolean debugInit = false;
|
||||
private static Debug debug = null;
|
||||
|
||||
@ -178,14 +187,79 @@ public final class AccessControlContext {
|
||||
|
||||
/**
|
||||
* package private for AccessController
|
||||
*
|
||||
* This "argument wrapper" context will be passed as the actual context
|
||||
* parameter on an internal doPrivileged() call used in the implementation.
|
||||
*/
|
||||
AccessControlContext(ProtectionDomain context[], DomainCombiner combiner) {
|
||||
AccessControlContext(ProtectionDomain caller, DomainCombiner combiner,
|
||||
AccessControlContext parent, AccessControlContext context,
|
||||
Permission[] perms)
|
||||
{
|
||||
/*
|
||||
* Combine the domains from the doPrivileged() context into our
|
||||
* wrapper context, if necessary.
|
||||
*/
|
||||
ProtectionDomain[] callerPDs = null;
|
||||
if (caller != null) {
|
||||
callerPDs = new ProtectionDomain[] { caller };
|
||||
}
|
||||
if (context != null) {
|
||||
this.context = context.clone();
|
||||
if (combiner != null) {
|
||||
this.context = combiner.combine(callerPDs, context.context);
|
||||
} else {
|
||||
this.context = combine(callerPDs, context.context);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Call combiner even if there is seemingly nothing to combine.
|
||||
*/
|
||||
if (combiner != null) {
|
||||
this.context = combiner.combine(callerPDs, null);
|
||||
} else {
|
||||
this.context = combine(callerPDs, null);
|
||||
}
|
||||
}
|
||||
this.combiner = combiner;
|
||||
|
||||
Permission[] tmp = null;
|
||||
if (perms != null) {
|
||||
tmp = new Permission[perms.length];
|
||||
for (int i=0; i < perms.length; i++) {
|
||||
if (perms[i] == null) {
|
||||
throw new NullPointerException("permission can't be null");
|
||||
}
|
||||
|
||||
/*
|
||||
* An AllPermission argument is equivalent to calling
|
||||
* doPrivileged() without any limit permissions.
|
||||
*/
|
||||
if (perms[i].getClass() == AllPermission.class) {
|
||||
parent = null;
|
||||
}
|
||||
tmp[i] = perms[i];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* For a doPrivileged() with limited privilege scope, initialize
|
||||
* the relevant fields.
|
||||
*
|
||||
* The limitedContext field contains the union of all domains which
|
||||
* are enclosed by this limited privilege scope. In other words,
|
||||
* it contains all of the domains which could potentially be checked
|
||||
* if none of the limiting permissions implied a requested permission.
|
||||
*/
|
||||
if (parent != null) {
|
||||
this.limitedContext = combine(parent.context, parent.limitedContext);
|
||||
this.isLimited = true;
|
||||
this.isWrapped = true;
|
||||
this.permissions = tmp;
|
||||
this.parent = parent;
|
||||
this.privilegedContext = context; // used in checkPermission2()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* package private constructor for AccessController.getContext()
|
||||
*/
|
||||
@ -260,6 +334,13 @@ public final class AccessControlContext {
|
||||
if (sm != null) {
|
||||
sm.checkPermission(SecurityConstants.GET_COMBINER_PERMISSION);
|
||||
}
|
||||
return getCombiner();
|
||||
}
|
||||
|
||||
/**
|
||||
* package private for AccessController
|
||||
*/
|
||||
DomainCombiner getCombiner() {
|
||||
return combiner;
|
||||
}
|
||||
|
||||
@ -335,8 +416,10 @@ public final class AccessControlContext {
|
||||
or the first domain was a Privileged system domain. This
|
||||
is to make the common case for system code very fast */
|
||||
|
||||
if (context == null)
|
||||
if (context == null) {
|
||||
checkPermission2(perm);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i=0; i< context.length; i++) {
|
||||
if (context[i] != null && !context[i].implies(perm)) {
|
||||
@ -370,20 +453,108 @@ public final class AccessControlContext {
|
||||
debug.println("access allowed "+perm);
|
||||
}
|
||||
|
||||
return;
|
||||
checkPermission2(perm);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check the domains associated with the limited privilege scope.
|
||||
*/
|
||||
private void checkPermission2(Permission perm) {
|
||||
if (!isLimited) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check the doPrivileged() context parameter, if present.
|
||||
*/
|
||||
if (privilegedContext != null) {
|
||||
privilegedContext.checkPermission2(perm);
|
||||
}
|
||||
|
||||
/*
|
||||
* Ignore the limited permissions and parent fields of a wrapper
|
||||
* context since they were already carried down into the unwrapped
|
||||
* context.
|
||||
*/
|
||||
if (isWrapped) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to match any limited privilege scope.
|
||||
*/
|
||||
if (permissions != null) {
|
||||
Class<?> permClass = perm.getClass();
|
||||
for (int i=0; i < permissions.length; i++) {
|
||||
Permission limit = permissions[i];
|
||||
if (limit.getClass().equals(permClass) && limit.implies(perm)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check the limited privilege scope up the call stack or the inherited
|
||||
* parent thread call stack of this ACC.
|
||||
*/
|
||||
if (parent != null) {
|
||||
/*
|
||||
* As an optimization, if the parent context is the inherited call
|
||||
* stack context from a parent thread then checking the protection
|
||||
* domains of the parent context is redundant since they have
|
||||
* already been merged into the child thread's context by
|
||||
* optimize(). When parent is set to an inherited context this
|
||||
* context was not directly created by a limited scope
|
||||
* doPrivileged() and it does not have its own limited permissions.
|
||||
*/
|
||||
if (permissions == null) {
|
||||
parent.checkPermission2(perm);
|
||||
} else {
|
||||
parent.checkPermission(perm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Take the stack-based context (this) and combine it with the
|
||||
* privileged or inherited context, if need be.
|
||||
* privileged or inherited context, if need be. Any limited
|
||||
* privilege scope is flagged regardless of whether the assigned
|
||||
* context comes from an immediately enclosing limited doPrivileged().
|
||||
* The limited privilege scope can indirectly flow from the inherited
|
||||
* parent thread or an assigned context previously captured by getContext().
|
||||
*/
|
||||
AccessControlContext optimize() {
|
||||
// the assigned (privileged or inherited) context
|
||||
AccessControlContext acc;
|
||||
DomainCombiner combiner = null;
|
||||
AccessControlContext parent = null;
|
||||
Permission[] permissions = null;
|
||||
|
||||
if (isPrivileged) {
|
||||
acc = privilegedContext;
|
||||
if (acc != null) {
|
||||
/*
|
||||
* If the context is from a limited scope doPrivileged() then
|
||||
* copy the permissions and parent fields out of the wrapper
|
||||
* context that was created to hold them.
|
||||
*/
|
||||
if (acc.isWrapped) {
|
||||
permissions = acc.permissions;
|
||||
parent = acc.parent;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
acc = AccessController.getInheritedAccessControlContext();
|
||||
if (acc != null) {
|
||||
/*
|
||||
* If the inherited context is constrained by a limited scope
|
||||
* doPrivileged() then set it as our parent so we will process
|
||||
* the non-domain-related state.
|
||||
*/
|
||||
if (acc.isLimited) {
|
||||
parent = acc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// this.context could be null if only system code is on the stack;
|
||||
@ -393,53 +564,98 @@ public final class AccessControlContext {
|
||||
// acc.context could be null if only system code was involved;
|
||||
// in that case, ignore the assigned context
|
||||
boolean skipAssigned = (acc == null || acc.context == null);
|
||||
ProtectionDomain[] assigned = (skipAssigned) ? null : acc.context;
|
||||
ProtectionDomain[] pd;
|
||||
|
||||
// if there is no enclosing limited privilege scope on the stack or
|
||||
// inherited from a parent thread
|
||||
boolean skipLimited = ((acc == null || !acc.isWrapped) && parent == null);
|
||||
|
||||
if (acc != null && acc.combiner != null) {
|
||||
// let the assigned acc's combiner do its thing
|
||||
return goCombiner(context, acc);
|
||||
if (getDebug() != null) {
|
||||
debug.println("AccessControlContext invoking the Combiner");
|
||||
}
|
||||
|
||||
// No need to clone current and assigned.context
|
||||
// combine() will not update them
|
||||
combiner = acc.combiner;
|
||||
pd = combiner.combine(context, assigned);
|
||||
} else {
|
||||
if (skipStack) {
|
||||
if (skipAssigned) {
|
||||
calculateFields(acc, parent, permissions);
|
||||
return this;
|
||||
} else if (skipLimited) {
|
||||
return acc;
|
||||
}
|
||||
} else if (assigned != null) {
|
||||
if (skipLimited) {
|
||||
// optimization: if there is a single stack domain and
|
||||
// that domain is already in the assigned context; no
|
||||
// need to combine
|
||||
if (context.length == 1 && context[0] == assigned[0]) {
|
||||
return acc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pd = combine(context, assigned);
|
||||
if (skipLimited && !skipAssigned && pd == assigned) {
|
||||
return acc;
|
||||
} else if (skipAssigned && pd == context) {
|
||||
calculateFields(acc, parent, permissions);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
// optimization: if neither have contexts; return acc if possible
|
||||
// rather than this, because acc might have a combiner
|
||||
if (skipAssigned && skipStack) {
|
||||
return this;
|
||||
}
|
||||
// Reuse existing ACC
|
||||
this.context = pd;
|
||||
this.combiner = combiner;
|
||||
this.isPrivileged = false;
|
||||
|
||||
// optimization: if there is no stack context; there is no reason
|
||||
// to compress the assigned context, it already is compressed
|
||||
if (skipStack) {
|
||||
return acc;
|
||||
}
|
||||
calculateFields(acc, parent, permissions);
|
||||
return this;
|
||||
}
|
||||
|
||||
int slen = context.length;
|
||||
|
||||
/*
|
||||
* Combine the current (stack) and assigned domains.
|
||||
*/
|
||||
private static ProtectionDomain[] combine(ProtectionDomain[]current,
|
||||
ProtectionDomain[] assigned) {
|
||||
|
||||
// current could be null if only system code is on the stack;
|
||||
// in that case, ignore the stack context
|
||||
boolean skipStack = (current == null);
|
||||
|
||||
// assigned could be null if only system code was involved;
|
||||
// in that case, ignore the assigned context
|
||||
boolean skipAssigned = (assigned == null);
|
||||
|
||||
int slen = (skipStack) ? 0 : current.length;
|
||||
|
||||
// optimization: if there is no assigned context and the stack length
|
||||
// is less then or equal to two; there is no reason to compress the
|
||||
// stack context, it already is
|
||||
if (skipAssigned && slen <= 2) {
|
||||
return this;
|
||||
return current;
|
||||
}
|
||||
|
||||
// optimization: if there is a single stack domain and that domain
|
||||
// is already in the assigned context; no need to combine
|
||||
if ((slen == 1) && (context[0] == acc.context[0])) {
|
||||
return acc;
|
||||
}
|
||||
|
||||
int n = (skipAssigned) ? 0 : acc.context.length;
|
||||
int n = (skipAssigned) ? 0 : assigned.length;
|
||||
|
||||
// now we combine both of them, and create a new context
|
||||
ProtectionDomain pd[] = new ProtectionDomain[slen + n];
|
||||
|
||||
// first copy in the assigned context domains, no need to compress
|
||||
if (!skipAssigned) {
|
||||
System.arraycopy(acc.context, 0, pd, 0, n);
|
||||
System.arraycopy(assigned, 0, pd, 0, n);
|
||||
}
|
||||
|
||||
// now add the stack context domains, discarding nulls and duplicates
|
||||
outer:
|
||||
for (int i = 0; i < context.length; i++) {
|
||||
ProtectionDomain sd = context[i];
|
||||
for (int i = 0; i < slen; i++) {
|
||||
ProtectionDomain sd = current[i];
|
||||
if (sd != null) {
|
||||
for (int j = 0; j < n; j++) {
|
||||
if (sd == pd[j]) {
|
||||
@ -453,54 +669,48 @@ public final class AccessControlContext {
|
||||
// if length isn't equal, we need to shorten the array
|
||||
if (n != pd.length) {
|
||||
// optimization: if we didn't really combine anything
|
||||
if (!skipAssigned && n == acc.context.length) {
|
||||
return acc;
|
||||
if (!skipAssigned && n == assigned.length) {
|
||||
return assigned;
|
||||
} else if (skipAssigned && n == slen) {
|
||||
return this;
|
||||
return current;
|
||||
}
|
||||
ProtectionDomain tmp[] = new ProtectionDomain[n];
|
||||
System.arraycopy(pd, 0, tmp, 0, n);
|
||||
pd = tmp;
|
||||
}
|
||||
|
||||
// return new AccessControlContext(pd, false);
|
||||
|
||||
// Reuse existing ACC
|
||||
|
||||
this.context = pd;
|
||||
this.combiner = null;
|
||||
this.isPrivileged = false;
|
||||
|
||||
return this;
|
||||
return pd;
|
||||
}
|
||||
|
||||
private AccessControlContext goCombiner(ProtectionDomain[] current,
|
||||
AccessControlContext assigned) {
|
||||
|
||||
// the assigned ACC's combiner is not null --
|
||||
// let the combiner do its thing
|
||||
/*
|
||||
* Calculate the additional domains that could potentially be reached via
|
||||
* limited privilege scope. Mark the context as being subject to limited
|
||||
* privilege scope unless the reachable domains (if any) are already
|
||||
* contained in this domain context (in which case any limited
|
||||
* privilege scope checking would be redundant).
|
||||
*/
|
||||
private void calculateFields(AccessControlContext assigned,
|
||||
AccessControlContext parent, Permission[] permissions)
|
||||
{
|
||||
ProtectionDomain[] parentLimit = null;
|
||||
ProtectionDomain[] assignedLimit = null;
|
||||
ProtectionDomain[] newLimit;
|
||||
|
||||
// XXX we could add optimizations to 'current' here ...
|
||||
|
||||
if (getDebug() != null) {
|
||||
debug.println("AccessControlContext invoking the Combiner");
|
||||
parentLimit = (parent != null)? parent.limitedContext: null;
|
||||
assignedLimit = (assigned != null)? assigned.limitedContext: null;
|
||||
newLimit = combine(parentLimit, assignedLimit);
|
||||
if (newLimit != null) {
|
||||
if (context == null || !containsAllPDs(newLimit, context)) {
|
||||
this.limitedContext = newLimit;
|
||||
this.permissions = permissions;
|
||||
this.parent = parent;
|
||||
this.isLimited = true;
|
||||
}
|
||||
}
|
||||
|
||||
// No need to clone current and assigned.context
|
||||
// combine() will not update them
|
||||
ProtectionDomain[] combinedPds = assigned.combiner.combine(
|
||||
current, assigned.context);
|
||||
|
||||
// return new AccessControlContext(combinedPds, assigned.combiner);
|
||||
|
||||
// Reuse existing ACC
|
||||
this.context = combinedPds;
|
||||
this.combiner = assigned.combiner;
|
||||
this.isPrivileged = false;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks two AccessControlContext objects for equality.
|
||||
* Checks that <i>obj</i> is
|
||||
@ -520,31 +730,131 @@ public final class AccessControlContext {
|
||||
|
||||
AccessControlContext that = (AccessControlContext) obj;
|
||||
|
||||
|
||||
if (context == null) {
|
||||
return (that.context == null);
|
||||
}
|
||||
|
||||
if (that.context == null)
|
||||
if (!equalContext(that))
|
||||
return false;
|
||||
|
||||
if (!(this.containsAllPDs(that) && that.containsAllPDs(this)))
|
||||
return false;
|
||||
|
||||
if (this.combiner == null)
|
||||
return (that.combiner == null);
|
||||
|
||||
if (that.combiner == null)
|
||||
return false;
|
||||
|
||||
if (!this.combiner.equals(that.combiner))
|
||||
if (!equalLimitedContext(that))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean containsAllPDs(AccessControlContext that) {
|
||||
/*
|
||||
* Compare for equality based on state that is free of limited
|
||||
* privilege complications.
|
||||
*/
|
||||
private boolean equalContext(AccessControlContext that) {
|
||||
if (!equalPDs(this.context, that.context))
|
||||
return false;
|
||||
|
||||
if (this.combiner == null && that.combiner != null)
|
||||
return false;
|
||||
|
||||
if (this.combiner != null && !this.combiner.equals(that.combiner))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean equalPDs(ProtectionDomain[] a, ProtectionDomain[] b) {
|
||||
if (a == null) {
|
||||
return (b == null);
|
||||
}
|
||||
|
||||
if (b == null)
|
||||
return false;
|
||||
|
||||
if (!(containsAllPDs(a, b) && containsAllPDs(b, a)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare for equality based on state that is captured during a
|
||||
* call to AccessController.getContext() when a limited privilege
|
||||
* scope is in effect.
|
||||
*/
|
||||
private boolean equalLimitedContext(AccessControlContext that) {
|
||||
if (that == null)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* If neither instance has limited privilege scope then we're done.
|
||||
*/
|
||||
if (!this.isLimited && !that.isLimited)
|
||||
return true;
|
||||
|
||||
/*
|
||||
* If only one instance has limited privilege scope then we're done.
|
||||
*/
|
||||
if (!(this.isLimited && that.isLimited))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Wrapped instances should never escape outside the implementation
|
||||
* this class and AccessController so this will probably never happen
|
||||
* but it only makes any sense to compare if they both have the same
|
||||
* isWrapped state.
|
||||
*/
|
||||
if ((this.isWrapped && !that.isWrapped) ||
|
||||
(!this.isWrapped && that.isWrapped)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.permissions == null && that.permissions != null)
|
||||
return false;
|
||||
|
||||
if (this.permissions != null && that.permissions == null)
|
||||
return false;
|
||||
|
||||
if (!(this.containsAllLimits(that) && that.containsAllLimits(this)))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Skip through any wrapped contexts.
|
||||
*/
|
||||
AccessControlContext thisNextPC = getNextPC(this);
|
||||
AccessControlContext thatNextPC = getNextPC(that);
|
||||
|
||||
/*
|
||||
* The protection domains and combiner of a privilegedContext are
|
||||
* not relevant because they have already been included in the context
|
||||
* of this instance by optimize() so we only care about any limited
|
||||
* privilege state they may have.
|
||||
*/
|
||||
if (thisNextPC == null && thatNextPC != null && thatNextPC.isLimited)
|
||||
return false;
|
||||
|
||||
if (thisNextPC != null && !thisNextPC.equalLimitedContext(thatNextPC))
|
||||
return false;
|
||||
|
||||
if (this.parent == null && that.parent != null)
|
||||
return false;
|
||||
|
||||
if (this.parent != null && !this.parent.equals(that.parent))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Follow the privilegedContext link making our best effort to skip
|
||||
* through any wrapper contexts.
|
||||
*/
|
||||
private static AccessControlContext getNextPC(AccessControlContext acc) {
|
||||
while (acc != null && acc.privilegedContext != null) {
|
||||
acc = acc.privilegedContext;
|
||||
if (!acc.isWrapped)
|
||||
return acc;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean containsAllPDs(ProtectionDomain[] thisContext,
|
||||
ProtectionDomain[] thatContext) {
|
||||
boolean match = false;
|
||||
|
||||
//
|
||||
// ProtectionDomains within an ACC currently cannot be null
|
||||
// and this is enforced by the constructor and the various
|
||||
@ -552,17 +862,17 @@ public final class AccessControlContext {
|
||||
// to support the notion of a null PD and therefore this logic continues
|
||||
// to support that notion.
|
||||
ProtectionDomain thisPd;
|
||||
for (int i = 0; i < context.length; i++) {
|
||||
for (int i = 0; i < thisContext.length; i++) {
|
||||
match = false;
|
||||
if ((thisPd = context[i]) == null) {
|
||||
for (int j = 0; (j < that.context.length) && !match; j++) {
|
||||
match = (that.context[j] == null);
|
||||
if ((thisPd = thisContext[i]) == null) {
|
||||
for (int j = 0; (j < thatContext.length) && !match; j++) {
|
||||
match = (thatContext[j] == null);
|
||||
}
|
||||
} else {
|
||||
Class<?> thisPdClass = thisPd.getClass();
|
||||
ProtectionDomain thatPd;
|
||||
for (int j = 0; (j < that.context.length) && !match; j++) {
|
||||
thatPd = that.context[j];
|
||||
for (int j = 0; (j < thatContext.length) && !match; j++) {
|
||||
thatPd = thatContext[j];
|
||||
|
||||
// Class check required to avoid PD exposure (4285406)
|
||||
match = (thatPd != null &&
|
||||
@ -573,6 +883,29 @@ public final class AccessControlContext {
|
||||
}
|
||||
return match;
|
||||
}
|
||||
|
||||
private boolean containsAllLimits(AccessControlContext that) {
|
||||
boolean match = false;
|
||||
Permission thisPerm;
|
||||
|
||||
if (this.permissions == null && that.permissions == null)
|
||||
return true;
|
||||
|
||||
for (int i = 0; i < this.permissions.length; i++) {
|
||||
Permission limit = this.permissions[i];
|
||||
Class <?> limitClass = limit.getClass();
|
||||
match = false;
|
||||
for (int j = 0; (j < that.permissions.length) && !match; j++) {
|
||||
Permission perm = that.permissions[j];
|
||||
match = (limitClass.equals(perm.getClass()) &&
|
||||
limit.equals(perm));
|
||||
}
|
||||
if (!match) return false;
|
||||
}
|
||||
return match;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the hash code value for this context. The hash code
|
||||
* is computed by exclusive or-ing the hash code of all the protection
|
||||
@ -591,6 +924,7 @@ public final class AccessControlContext {
|
||||
if (context[i] != null)
|
||||
hashCode ^= context[i].hashCode();
|
||||
}
|
||||
|
||||
return hashCode;
|
||||
}
|
||||
}
|
||||
|
@ -82,9 +82,15 @@ import sun.reflect.Reflection;
|
||||
* else if (caller i is marked as privileged) {
|
||||
* if (a context was specified in the call to doPrivileged)
|
||||
* context.checkPermission(permission)
|
||||
* return;
|
||||
* if (limited permissions were specified in the call to doPrivileged) {
|
||||
* for (each limited permission) {
|
||||
* if (the limited permission implies the requested permission)
|
||||
* return;
|
||||
* }
|
||||
* } else
|
||||
* return;
|
||||
* }
|
||||
* };
|
||||
* }
|
||||
*
|
||||
* // Next, check the context inherited when the thread was created.
|
||||
* // Whenever a new thread is created, the AccessControlContext at
|
||||
@ -101,11 +107,16 @@ import sun.reflect.Reflection;
|
||||
* was marked as "privileged" via a <code>doPrivileged</code>
|
||||
* call without a context argument (see below for information about a
|
||||
* context argument). If that caller's domain has the
|
||||
* specified permission, no further checking is done and
|
||||
* specified permission and at least one limiting permission argument (if any)
|
||||
* implies the requested permission, no further checking is done and
|
||||
* <code>checkPermission</code>
|
||||
* returns quietly, indicating that the requested access is allowed.
|
||||
* If that domain does not have the specified permission, an exception
|
||||
* is thrown, as usual.
|
||||
* is thrown, as usual. If the caller's domain had the specified permission
|
||||
* but it was not implied by any limiting permission arguments given in the call
|
||||
* to <code>doPrivileged</code> then the permission checking continues
|
||||
* until there are no more callers or another <code>doPrivileged</code>
|
||||
* call matches the requested permission and returns normally.
|
||||
*
|
||||
* <p> The normal use of the "privileged" feature is as follows. If you
|
||||
* don't need to return a value from within the "privileged" block, do
|
||||
@ -180,6 +191,9 @@ import sun.reflect.Reflection;
|
||||
*
|
||||
* <p> Be *very* careful in your use of the "privileged" construct, and
|
||||
* always remember to make the privileged code section as small as possible.
|
||||
* You can pass <code>Permission</code> arguments to further limit the
|
||||
* scope of the "privilege" (see below).
|
||||
*
|
||||
*
|
||||
* <p> Note that <code>checkPermission</code> always performs security checks
|
||||
* within the context of the currently executing thread.
|
||||
@ -215,7 +229,9 @@ import sun.reflect.Reflection;
|
||||
*
|
||||
* <p> There are also times where you don't know a priori which permissions
|
||||
* to check the context against. In these cases you can use the
|
||||
* doPrivileged method that takes a context:
|
||||
* doPrivileged method that takes a context. You can also limit the scope
|
||||
* of the privileged code by passing additional <code>Permission</code>
|
||||
* parameters.
|
||||
*
|
||||
* <pre> {@code
|
||||
* somemethod() {
|
||||
@ -223,12 +239,21 @@ import sun.reflect.Reflection;
|
||||
* public Object run() {
|
||||
* // Code goes here. Any permission checks within this
|
||||
* // run method will require that the intersection of the
|
||||
* // callers protection domain and the snapshot's
|
||||
* // context have the desired permission.
|
||||
* // caller's protection domain and the snapshot's
|
||||
* // context have the desired permission. If a requested
|
||||
* // permission is not implied by the limiting FilePermission
|
||||
* // argument then checking of the thread continues beyond the
|
||||
* // caller of doPrivileged.
|
||||
* }
|
||||
* }, acc);
|
||||
* }, acc, new FilePermission("/temp/*", read));
|
||||
* ...normal code here...
|
||||
* }}</pre>
|
||||
* <p> Passing a limiting <code>Permission</code> argument of an instance of
|
||||
* <code>AllPermission</code> is equivalent to calling the equivalent
|
||||
* <code>doPrivileged</code> method without limiting <code>Permission</code>
|
||||
* arguments. Passing a zero length array of <code>Permission</code> disables
|
||||
* the code privileges so that checking always continues beyond the caller of
|
||||
* that <code>doPrivileged</code> method.
|
||||
*
|
||||
* @see AccessControlContext
|
||||
*
|
||||
@ -334,6 +359,112 @@ public final class AccessController {
|
||||
public static native <T> T doPrivileged(PrivilegedAction<T> action,
|
||||
AccessControlContext context);
|
||||
|
||||
|
||||
/**
|
||||
* Performs the specified <code>PrivilegedAction</code> with privileges
|
||||
* enabled and restricted by the specified
|
||||
* <code>AccessControlContext</code> and with a privilege scope limited
|
||||
* by specified <code>Permission</code> arguments.
|
||||
*
|
||||
* The action is performed with the intersection of the permissions
|
||||
* possessed by the caller's protection domain, and those possessed
|
||||
* by the domains represented by the specified
|
||||
* <code>AccessControlContext</code>.
|
||||
* <p>
|
||||
* If the action's <code>run</code> method throws an (unchecked) exception,
|
||||
* it will propagate through this method.
|
||||
*
|
||||
* @param action the action to be performed.
|
||||
* @param context an <i>access control context</i>
|
||||
* representing the restriction to be applied to the
|
||||
* caller's domain's privileges before performing
|
||||
* the specified action. If the context is
|
||||
* <code>null</code>,
|
||||
* then no additional restriction is applied.
|
||||
* @param perms the <code>Permission</code> arguments which limit the
|
||||
* scope of the caller's privileges. The number of arguments
|
||||
* is variable.
|
||||
*
|
||||
* @return the value returned by the action's <code>run</code> method.
|
||||
*
|
||||
* @throws NullPointerException if action or perms or any element of
|
||||
* perms is <code>null</code>
|
||||
*
|
||||
* @see #doPrivileged(PrivilegedAction)
|
||||
* @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
@CallerSensitive
|
||||
public static <T> T doPrivileged(PrivilegedAction<T> action,
|
||||
AccessControlContext context, Permission... perms) {
|
||||
|
||||
AccessControlContext parent = getContext();
|
||||
if (perms == null) {
|
||||
throw new NullPointerException("null permissions parameter");
|
||||
}
|
||||
Class <?> caller = Reflection.getCallerClass();
|
||||
return AccessController.doPrivileged(action, createWrapper(null,
|
||||
caller, parent, context, perms));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Performs the specified <code>PrivilegedAction</code> with privileges
|
||||
* enabled and restricted by the specified
|
||||
* <code>AccessControlContext</code> and with a privilege scope limited
|
||||
* by specified <code>Permission</code> arguments.
|
||||
*
|
||||
* The action is performed with the intersection of the permissions
|
||||
* possessed by the caller's protection domain, and those possessed
|
||||
* by the domains represented by the specified
|
||||
* <code>AccessControlContext</code>.
|
||||
* <p>
|
||||
* If the action's <code>run</code> method throws an (unchecked) exception,
|
||||
* it will propagate through this method.
|
||||
*
|
||||
* <p> This method preserves the current AccessControlContext's
|
||||
* DomainCombiner (which may be null) while the action is performed.
|
||||
*
|
||||
* @param action the action to be performed.
|
||||
* @param context an <i>access control context</i>
|
||||
* representing the restriction to be applied to the
|
||||
* caller's domain's privileges before performing
|
||||
* the specified action. If the context is
|
||||
* <code>null</code>,
|
||||
* then no additional restriction is applied.
|
||||
* @param perms the <code>Permission</code> arguments which limit the
|
||||
* scope of the caller's privileges. The number of arguments
|
||||
* is variable.
|
||||
*
|
||||
* @return the value returned by the action's <code>run</code> method.
|
||||
*
|
||||
* @throws NullPointerException if action or perms or any element of
|
||||
* perms is <code>null</code>
|
||||
*
|
||||
* @see #doPrivileged(PrivilegedAction)
|
||||
* @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
|
||||
* @see java.security.DomainCombiner
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
@CallerSensitive
|
||||
public static <T> T doPrivilegedWithCombiner(PrivilegedAction<T> action,
|
||||
AccessControlContext context, Permission... perms) {
|
||||
|
||||
AccessControlContext parent = getContext();
|
||||
DomainCombiner dc = parent.getCombiner();
|
||||
if (dc == null && context != null) {
|
||||
dc = context.getCombiner();
|
||||
}
|
||||
if (perms == null) {
|
||||
throw new NullPointerException("null permissions parameter");
|
||||
}
|
||||
Class <?> caller = Reflection.getCallerClass();
|
||||
return AccessController.doPrivileged(action, createWrapper(dc, caller,
|
||||
parent, context, perms));
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the specified <code>PrivilegedExceptionAction</code> with
|
||||
* privileges enabled. The action is performed with <i>all</i> of the
|
||||
@ -408,6 +539,22 @@ public final class AccessController {
|
||||
private static AccessControlContext preserveCombiner(DomainCombiner combiner,
|
||||
Class<?> caller)
|
||||
{
|
||||
return createWrapper(combiner, caller, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a wrapper to contain the limited privilege scope data.
|
||||
*/
|
||||
private static AccessControlContext
|
||||
createWrapper(DomainCombiner combiner, Class<?> caller,
|
||||
AccessControlContext parent, AccessControlContext context,
|
||||
Permission[] perms)
|
||||
{
|
||||
return new AccessControlContext(getCallerPD(caller), combiner, parent,
|
||||
context, perms);
|
||||
}
|
||||
|
||||
private static ProtectionDomain getCallerPD(final Class <?> caller) {
|
||||
ProtectionDomain callerPd = doPrivileged
|
||||
(new PrivilegedAction<ProtectionDomain>() {
|
||||
public ProtectionDomain run() {
|
||||
@ -415,18 +562,9 @@ public final class AccessController {
|
||||
}
|
||||
});
|
||||
|
||||
// perform 'combine' on the caller of doPrivileged,
|
||||
// even if the caller is from the bootclasspath
|
||||
ProtectionDomain[] pds = new ProtectionDomain[] {callerPd};
|
||||
if (combiner == null) {
|
||||
return new AccessControlContext(pds);
|
||||
} else {
|
||||
return new AccessControlContext(combiner.combine(pds, null),
|
||||
combiner);
|
||||
}
|
||||
return callerPd;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Performs the specified <code>PrivilegedExceptionAction</code> with
|
||||
* privileges enabled and restricted by the specified
|
||||
@ -454,7 +592,7 @@ public final class AccessController {
|
||||
* @exception NullPointerException if the action is <code>null</code>
|
||||
*
|
||||
* @see #doPrivileged(PrivilegedAction)
|
||||
* @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
|
||||
* @see #doPrivileged(PrivilegedAction,AccessControlContext)
|
||||
*/
|
||||
@CallerSensitive
|
||||
public static native <T> T
|
||||
@ -462,6 +600,118 @@ public final class AccessController {
|
||||
AccessControlContext context)
|
||||
throws PrivilegedActionException;
|
||||
|
||||
|
||||
/**
|
||||
* Performs the specified <code>PrivilegedExceptionAction</code> with
|
||||
* privileges enabled and restricted by the specified
|
||||
* <code>AccessControlContext</code> and with a privilege scope limited by
|
||||
* specified <code>Permission</code> arguments.
|
||||
*
|
||||
* The action is performed with the intersection of the permissions
|
||||
* possessed by the caller's protection domain, and those possessed
|
||||
* by the domains represented by the specified
|
||||
* <code>AccessControlContext</code>.
|
||||
* <p>
|
||||
* If the action's <code>run</code> method throws an (unchecked) exception,
|
||||
* it will propagate through this method.
|
||||
*
|
||||
* @param action the action to be performed.
|
||||
* @param context an <i>access control context</i>
|
||||
* representing the restriction to be applied to the
|
||||
* caller's domain's privileges before performing
|
||||
* the specified action. If the context is
|
||||
* <code>null</code>,
|
||||
* then no additional restriction is applied.
|
||||
* @param perms the <code>Permission</code> arguments which limit the
|
||||
* scope of the caller's privileges. The number of arguments
|
||||
* is variable.
|
||||
*
|
||||
* @return the value returned by the action's <code>run</code> method.
|
||||
*
|
||||
* @throws PrivilegedActionException if the specified action's
|
||||
* <code>run</code> method threw a <i>checked</i> exception
|
||||
* @throws NullPointerException if action or perms or any element of
|
||||
* perms is <code>null</code>
|
||||
*
|
||||
* @see #doPrivileged(PrivilegedAction)
|
||||
* @see #doPrivileged(PrivilegedAction,AccessControlContext)
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
@CallerSensitive
|
||||
public static <T> T doPrivileged(PrivilegedExceptionAction<T> action,
|
||||
AccessControlContext context, Permission... perms)
|
||||
throws PrivilegedActionException
|
||||
{
|
||||
AccessControlContext parent = getContext();
|
||||
if (perms == null) {
|
||||
throw new NullPointerException("null permissions parameter");
|
||||
}
|
||||
Class <?> caller = Reflection.getCallerClass();
|
||||
return AccessController.doPrivileged(action, createWrapper(null, caller, parent, context, perms));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Performs the specified <code>PrivilegedExceptionAction</code> with
|
||||
* privileges enabled and restricted by the specified
|
||||
* <code>AccessControlContext</code> and with a privilege scope limited by
|
||||
* specified <code>Permission</code> arguments.
|
||||
*
|
||||
* The action is performed with the intersection of the permissions
|
||||
* possessed by the caller's protection domain, and those possessed
|
||||
* by the domains represented by the specified
|
||||
* <code>AccessControlContext</code>.
|
||||
* <p>
|
||||
* If the action's <code>run</code> method throws an (unchecked) exception,
|
||||
* it will propagate through this method.
|
||||
*
|
||||
* <p> This method preserves the current AccessControlContext's
|
||||
* DomainCombiner (which may be null) while the action is performed.
|
||||
*
|
||||
* @param action the action to be performed.
|
||||
* @param context an <i>access control context</i>
|
||||
* representing the restriction to be applied to the
|
||||
* caller's domain's privileges before performing
|
||||
* the specified action. If the context is
|
||||
* <code>null</code>,
|
||||
* then no additional restriction is applied.
|
||||
* @param perms the <code>Permission</code> arguments which limit the
|
||||
* scope of the caller's privileges. The number of arguments
|
||||
* is variable.
|
||||
*
|
||||
* @return the value returned by the action's <code>run</code> method.
|
||||
*
|
||||
* @throws PrivilegedActionException if the specified action's
|
||||
* <code>run</code> method threw a <i>checked</i> exception
|
||||
* @throws NullPointerException if action or perms or any element of
|
||||
* perms is <code>null</code>
|
||||
*
|
||||
* @see #doPrivileged(PrivilegedAction)
|
||||
* @see #doPrivileged(PrivilegedAction,AccessControlContext)
|
||||
* @see java.security.DomainCombiner
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
@CallerSensitive
|
||||
public static <T> T doPrivilegedWithCombiner(PrivilegedExceptionAction<T> action,
|
||||
AccessControlContext context,
|
||||
Permission... perms)
|
||||
throws PrivilegedActionException
|
||||
{
|
||||
AccessControlContext parent = getContext();
|
||||
DomainCombiner dc = parent.getCombiner();
|
||||
if (dc == null && context != null) {
|
||||
dc = context.getCombiner();
|
||||
}
|
||||
if (perms == null) {
|
||||
throw new NullPointerException("null permissions parameter");
|
||||
}
|
||||
Class <?> caller = Reflection.getCallerClass();
|
||||
return AccessController.doPrivileged(action, createWrapper(dc, caller,
|
||||
parent, context, perms));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the AccessControl context. i.e., it gets
|
||||
* the protection domains of all the callers on the stack,
|
||||
@ -474,6 +724,7 @@ public final class AccessController {
|
||||
|
||||
private static native AccessControlContext getStackAccessControlContext();
|
||||
|
||||
|
||||
/**
|
||||
* Returns the "inherited" AccessControl context. This is the context
|
||||
* that existed when the thread was created. Package private so
|
||||
@ -484,9 +735,9 @@ public final class AccessController {
|
||||
|
||||
/**
|
||||
* This method takes a "snapshot" of the current calling context, which
|
||||
* includes the current Thread's inherited AccessControlContext,
|
||||
* and places it in an AccessControlContext object. This context may then
|
||||
* be checked at a later point, possibly in another thread.
|
||||
* includes the current Thread's inherited AccessControlContext and any
|
||||
* limited privilege scope, and places it in an AccessControlContext object.
|
||||
* This context may then be checked at a later point, possibly in another thread.
|
||||
*
|
||||
* @see AccessControlContext
|
||||
*
|
||||
@ -524,7 +775,7 @@ public final class AccessController {
|
||||
*/
|
||||
|
||||
public static void checkPermission(Permission perm)
|
||||
throws AccessControlException
|
||||
throws AccessControlException
|
||||
{
|
||||
//System.err.println("checkPermission "+perm);
|
||||
//Thread.currentThread().dumpStack();
|
||||
|
215
jdk/test/java/security/AccessController/LimitedDoPrivileged.java
Normal file
215
jdk/test/java/security/AccessController/LimitedDoPrivileged.java
Normal file
@ -0,0 +1,215 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8014097
|
||||
* @summary Test the limited privilege scope version of doPrivileged
|
||||
*/
|
||||
|
||||
import java.security.*;
|
||||
import java.util.*;
|
||||
|
||||
public class LimitedDoPrivileged {
|
||||
/*
|
||||
* Test variations of doPrivileged() and doPrivileged() with a limited privilege scope
|
||||
* in a sandbox with the usual default permission to read the system properties for the
|
||||
* file and path separators.
|
||||
*
|
||||
* By passing in an "assigned" AccessControlContext that has
|
||||
* no default permissions we can test how code privileges are being scoped.
|
||||
*/
|
||||
|
||||
private static final ProtectionDomain domain =
|
||||
new ProtectionDomain(null, null, null, null);
|
||||
private static final AccessControlContext acc =
|
||||
new AccessControlContext(new ProtectionDomain[] { domain });
|
||||
private static final PropertyPermission pathPerm =
|
||||
new PropertyPermission("path.separator", "read");
|
||||
private static final PropertyPermission filePerm =
|
||||
new PropertyPermission("file.separator", "read");
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
/*
|
||||
* Verify that we have the usual default property read permission.
|
||||
*/
|
||||
AccessController.getContext().checkPermission(filePerm);
|
||||
AccessController.getContext().checkPermission(pathPerm);
|
||||
System.out.println("test 1 passed");
|
||||
|
||||
/*
|
||||
* Inject the "no permission" AccessControlContext.
|
||||
*/
|
||||
AccessController.doPrivileged(new PrivilegedAction() {
|
||||
public Object run() {
|
||||
|
||||
/*
|
||||
* Verify that we no longer have the "file.separator" permission.
|
||||
*/
|
||||
try {
|
||||
AccessController.getContext().checkPermission(pathPerm);
|
||||
} catch (AccessControlException ace) {
|
||||
System.out.println("test 2 passed");
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that we can give ourselves limited privilege to read
|
||||
* any system property starting with "path.".
|
||||
*/
|
||||
AccessController.doPrivileged
|
||||
(new PrivilegedAction() {
|
||||
public Object run() {
|
||||
AccessController.getContext().checkPermission(pathPerm);
|
||||
return null;
|
||||
}
|
||||
}, null, new PropertyPermission("path.*", "read"));
|
||||
System.out.println("test 3 passed");
|
||||
|
||||
/*
|
||||
* Verify that if we give ourselves limited privilege to read
|
||||
* any system property starting with "path." it won't give us the
|
||||
* the ability to read "file.separator".
|
||||
*/
|
||||
try {
|
||||
AccessController.doPrivileged
|
||||
(new PrivilegedAction() {
|
||||
public Object run() {
|
||||
AccessController.getContext().checkPermission(filePerm);
|
||||
return null;
|
||||
}
|
||||
}, null, new PropertyPermission("path.*", "read"));
|
||||
} catch (AccessControlException ace) {
|
||||
System.out.println("test 4 passed");
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that capturing and passing in the context with no default
|
||||
* system property permission grants will prevent access that succeeded
|
||||
* earlier without the context assignment.
|
||||
*/
|
||||
final AccessControlContext context = AccessController.getContext();
|
||||
try {
|
||||
AccessController.doPrivileged
|
||||
(new PrivilegedAction() {
|
||||
public Object run() {
|
||||
AccessController.getContext().checkPermission(pathPerm);
|
||||
return null;
|
||||
}
|
||||
}, context, new PropertyPermission("path.*", "read"));
|
||||
} catch (AccessControlException ace) {
|
||||
System.out.println("test 5 passed");
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that we can give ourselves full privilege to read
|
||||
* any system property starting with "path.".
|
||||
*/
|
||||
AccessController.doPrivileged
|
||||
(new PrivilegedAction() {
|
||||
public Object run() {
|
||||
AccessController.getContext().checkPermission(pathPerm);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
System.out.println("test 6 passed");
|
||||
|
||||
/*
|
||||
* Verify that capturing and passing in the context with no default
|
||||
* system property permission grants will prevent access that succeeded
|
||||
* earlier without the context assignment.
|
||||
*/
|
||||
try {
|
||||
AccessController.doPrivileged
|
||||
(new PrivilegedAction() {
|
||||
public Object run() {
|
||||
AccessController.getContext().checkPermission(pathPerm);
|
||||
return null;
|
||||
}
|
||||
}, context);
|
||||
} catch (AccessControlException ace) {
|
||||
System.out.println("test 7 passed");
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that we can give ourselves limited privilege to read
|
||||
* any system property starting with "path." when a limited
|
||||
* privilege scope context is captured and passed to a regular
|
||||
* doPrivileged() as an assigned context.
|
||||
*/
|
||||
AccessController.doPrivileged
|
||||
(new PrivilegedAction() {
|
||||
public Object run() {
|
||||
|
||||
/*
|
||||
* Capture the limited privilege scope and inject it into the
|
||||
* regular doPrivileged().
|
||||
*/
|
||||
final AccessControlContext limitedContext = AccessController.getContext();
|
||||
AccessController.doPrivileged
|
||||
(new PrivilegedAction() {
|
||||
public Object run() {
|
||||
AccessController.getContext().checkPermission(pathPerm);
|
||||
return null;
|
||||
}
|
||||
}, limitedContext);
|
||||
return null;
|
||||
}
|
||||
}, null, new PropertyPermission("path.*", "read"));
|
||||
System.out.println("test 8 passed");
|
||||
|
||||
/*
|
||||
* Verify that we can give ourselves limited privilege to read
|
||||
* any system property starting with "path." it won't give us the
|
||||
* the ability to read "file.separator" when a limited
|
||||
* privilege scope context is captured and passed to a regular
|
||||
* doPrivileged() as an assigned context.
|
||||
*/
|
||||
AccessController.doPrivileged
|
||||
(new PrivilegedAction() {
|
||||
public Object run() {
|
||||
|
||||
/*
|
||||
* Capture the limited privilege scope and inject it into the
|
||||
* regular doPrivileged().
|
||||
*/
|
||||
final AccessControlContext limitedContext = AccessController.getContext();
|
||||
try {
|
||||
AccessController.doPrivileged
|
||||
(new PrivilegedAction() {
|
||||
public Object run() {
|
||||
AccessController.getContext().checkPermission(filePerm);
|
||||
return null;
|
||||
}
|
||||
}, limitedContext);
|
||||
} catch (AccessControlException ace) {
|
||||
System.out.println("test 9 passed");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}, null, new PropertyPermission("path.*", "read"));
|
||||
|
||||
return null;
|
||||
}
|
||||
}, acc);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user