Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
861bd85a
D
dragonwell8_jdk
项目概览
openanolis
/
dragonwell8_jdk
通知
4
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_jdk
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
861bd85a
编写于
6月 04, 2013
作者:
J
jdn
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
8014097: add doPrivileged methods with limited privilege scope
Reviewed-by: mchung
上级
f45551af
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
901 addition
and
101 deletion
+901
-101
src/share/classes/java/security/AccessControlContext.java
src/share/classes/java/security/AccessControlContext.java
+412
-78
src/share/classes/java/security/AccessController.java
src/share/classes/java/security/AccessController.java
+274
-23
test/java/security/AccessController/LimitedDoPrivileged.java
test/java/security/AccessController/LimitedDoPrivileged.java
+215
-0
未找到文件。
src/share/classes/java/security/AccessControlContext.java
浏览文件 @
861bd85a
...
...
@@ -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"
);
}
// optimization: if neither have contexts; return acc if possible
// rather than this, because acc might have a combiner
if
(
skipAssigned
&&
skipStack
)
{
return
this
;
}
// 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
;
}
}
}
// optimization: if there is no stack context; there is no reason
// to compress the assigned context, it already is compressed
if
(
skipStack
)
{
return
acc
;
pd
=
combine
(
context
,
assigned
);
if
(
skipLimited
&&
!
skipAssigned
&&
pd
==
assigned
)
{
return
acc
;
}
else
if
(
skipAssigned
&&
pd
==
context
)
{
calculateFields
(
acc
,
parent
,
permissions
);
return
this
;
}
}
int
slen
=
context
.
length
;
// Reuse existing ACC
this
.
context
=
pd
;
this
.
combiner
=
combiner
;
this
.
isPrivileged
=
false
;
calculateFields
(
acc
,
parent
,
permissions
);
return
this
;
}
/*
* 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
(
a
cc
.
context
,
0
,
pd
,
0
,
n
);
System
.
arraycopy
(
a
ssigned
,
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
=
c
ontex
t
[
i
];
for
(
int
i
=
0
;
i
<
slen
;
i
++)
{
ProtectionDomain
sd
=
c
urren
t
[
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
==
a
cc
.
context
.
length
)
{
return
a
cc
;
if
(!
skipAssigned
&&
n
==
a
ssigned
.
length
)
{
return
a
ssigned
;
}
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
// XXX we could add optimizations to 'current' here ...
if
(
getDebug
()
!=
null
)
{
debug
.
println
(
"AccessControlContext invoking the Combiner"
);
/*
* 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
;
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
(!
equalContext
(
that
))
return
false
;
if
(!
equalLimitedContext
(
that
))
return
false
;
if
(
context
==
null
)
{
return
(
that
.
context
==
null
);
return
true
;
}
/*
* 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
(
th
at
.
context
=
=
null
)
if
(
th
is
.
permissions
==
null
&&
that
.
permissions
!
=
null
)
return
false
;
if
(!(
this
.
containsAllPDs
(
that
)
&&
that
.
containsAllPDs
(
this
)))
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
(
this
.
combiner
==
null
)
return
(
that
.
combiner
==
null
)
;
if
(
this
NextPC
!=
null
&&
!
thisNextPC
.
equalLimitedContext
(
thatNextPC
)
)
return
false
;
if
(
th
at
.
combiner
=
=
null
)
if
(
th
is
.
parent
==
null
&&
that
.
parent
!
=
null
)
return
false
;
if
(
!
this
.
combiner
.
equals
(
that
.
combiner
))
if
(
this
.
parent
!=
null
&&
!
this
.
parent
.
equals
(
that
.
parent
))
return
false
;
return
true
;
}
private
boolean
containsAllPDs
(
AccessControlContext
that
)
{
/*
* 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
<
c
ontext
.
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
thisC
ontext
.
length
;
i
++)
{
match
=
false
;
if
((
thisPd
=
c
ontext
[
i
])
==
null
)
{
for
(
int
j
=
0
;
(
j
<
that
.
c
ontext
.
length
)
&&
!
match
;
j
++)
{
match
=
(
that
.
c
ontext
[
j
]
==
null
);
if
((
thisPd
=
thisC
ontext
[
i
])
==
null
)
{
for
(
int
j
=
0
;
(
j
<
that
C
ontext
.
length
)
&&
!
match
;
j
++)
{
match
=
(
that
C
ontext
[
j
]
==
null
);
}
}
else
{
Class
<?>
thisPdClass
=
thisPd
.
getClass
();
ProtectionDomain
thatPd
;
for
(
int
j
=
0
;
(
j
<
that
.
c
ontext
.
length
)
&&
!
match
;
j
++)
{
thatPd
=
that
.
c
ontext
[
j
];
for
(
int
j
=
0
;
(
j
<
that
C
ontext
.
length
)
&&
!
match
;
j
++)
{
thatPd
=
that
C
ontext
[
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
;
}
}
src/share/classes/java/security/AccessController.java
浏览文件 @
861bd85a
...
...
@@ -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(Privileged
Exception
Action,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();
...
...
test/java/security/AccessController/LimitedDoPrivileged.java
0 → 100644
浏览文件 @
861bd85a
/*
* 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
);
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录