java.lang.SecurityManager中的初始化字段是做什么用的?
What is the initialized field in java.lang.SecurityManager for?
在java.lang.SecurityManager
中,有一个名为initialized的boolean字段。
public class SecurityManager {
/*
* Have we been initialized. Effective against finalizer attacks.
*/
private boolean initialized = false;
//some code
/**
* Constructs a new <code>SecurityManager</code>.
*
* <p> If there is a security manager already installed, this method first
* calls the security manager's <code>checkPermission</code> method
* with the <code>RuntimePermission("createSecurityManager")</code>
* permission to ensure the calling thread has permission to create a new
* security manager.
* This may result in throwing a <code>SecurityException</code>.
*
* @exception java.lang.SecurityException if a security manager already
* exists and its <code>checkPermission</code> method
* doesn't allow creation of a new security manager.
* @see java.lang.System#getSecurityManager()
* @see #checkPermission(java.security.Permission) checkPermission
* @see java.lang.RuntimePermission
*/
public SecurityManager() {
synchronized(SecurityManager.class) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
// ask the currently installed security manager if we
// can create a new one.
sm.checkPermission(new RuntimePermission
("createSecurityManager"));
}
initialized = true;
}
}
//some code
}
显然,初始化字段默认为false
,但如果实例化通过安全检查并成功,则初始化字段将被分配为true
。 initialized字段上面只有注释,说是对finalizer攻击有效,并没有提供更多关于该字段的描述。
我在网上搜索了一下finalizer attacks。我的理解是我们不应该依赖可以被不受信任的代码覆盖的方法。但是它与初始化字段有什么关系呢?我仍然可以继承 java.lang.SecurityManager
,如果安装了 SecurityManager 但允许通过反射访问私有字段,则应该可以编辑初始化的字段。那么它是如何有效对抗终结器攻击的呢?
这是一种较旧的保护技术:
https://www.ibm.com/developerworks/java/library/j-fv/j-fv-pdf.pdf
简而言之 - 终结器攻击是指当您重写对象的 finalize()
方法时,该方法充当 GC 将调用以释放本机资源的析构函数。但是一旦你子类化,或者用反射覆盖它 - 原始代码的不变量/"promises" 不再成立。
How to avoid the attack
Until the third edition of the Java Language Specification (JLS) was
implemented in Java SE 6, the only ways to avoid the attack — using an
initialized
flag, prohibiting subclassing, or creating a final
finalizer — were unsatisfactory solutions.
Using an initialized flag:
One way to avoid the attack is to use an initialized
flag, which is
set to true once an object has been correctly created. Every method in
the class first checks to see if initialized
is set and throws an
exception if it is not. This kind of coding is tiresome to write, is
easy to omit by accident, and does not stop an attacker from
subclassing the method.
在java.lang.SecurityManager
中,有一个名为initialized的boolean字段。
public class SecurityManager {
/*
* Have we been initialized. Effective against finalizer attacks.
*/
private boolean initialized = false;
//some code
/**
* Constructs a new <code>SecurityManager</code>.
*
* <p> If there is a security manager already installed, this method first
* calls the security manager's <code>checkPermission</code> method
* with the <code>RuntimePermission("createSecurityManager")</code>
* permission to ensure the calling thread has permission to create a new
* security manager.
* This may result in throwing a <code>SecurityException</code>.
*
* @exception java.lang.SecurityException if a security manager already
* exists and its <code>checkPermission</code> method
* doesn't allow creation of a new security manager.
* @see java.lang.System#getSecurityManager()
* @see #checkPermission(java.security.Permission) checkPermission
* @see java.lang.RuntimePermission
*/
public SecurityManager() {
synchronized(SecurityManager.class) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
// ask the currently installed security manager if we
// can create a new one.
sm.checkPermission(new RuntimePermission
("createSecurityManager"));
}
initialized = true;
}
}
//some code
}
显然,初始化字段默认为false
,但如果实例化通过安全检查并成功,则初始化字段将被分配为true
。 initialized字段上面只有注释,说是对finalizer攻击有效,并没有提供更多关于该字段的描述。
我在网上搜索了一下finalizer attacks。我的理解是我们不应该依赖可以被不受信任的代码覆盖的方法。但是它与初始化字段有什么关系呢?我仍然可以继承 java.lang.SecurityManager
,如果安装了 SecurityManager 但允许通过反射访问私有字段,则应该可以编辑初始化的字段。那么它是如何有效对抗终结器攻击的呢?
这是一种较旧的保护技术: https://www.ibm.com/developerworks/java/library/j-fv/j-fv-pdf.pdf
简而言之 - 终结器攻击是指当您重写对象的 finalize()
方法时,该方法充当 GC 将调用以释放本机资源的析构函数。但是一旦你子类化,或者用反射覆盖它 - 原始代码的不变量/"promises" 不再成立。
How to avoid the attack
Until the third edition of the Java Language Specification (JLS) was implemented in Java SE 6, the only ways to avoid the attack — using an
initialized
flag, prohibiting subclassing, or creating afinal
finalizer — were unsatisfactory solutions.Using an initialized flag:
One way to avoid the attack is to use an
initialized
flag, which is set to true once an object has been correctly created. Every method in the class first checks to see ifinitialized
is set and throws an exception if it is not. This kind of coding is tiresome to write, is easy to omit by accident, and does not stop an attacker from subclassing the method.