安全和争用条件
另一个值得关注的领域是争用条件利用的安全漏洞的可能性。 实现这一点有几种方法。 下面的子主题概述了开发人员必须避免的一些主要陷阱。
Dispose 方法中的争用条件
如果类的 Dispose 方法(有关更多信息,请参阅垃圾收集)未同步,则 Dispose 内的清理代码可能会运行多次,如下例所示。
Sub Dispose()
If Not (myObj Is Nothing) Then
Cleanup(myObj)
myObj = Nothing
End If
End Sub
void Dispose()
{
if (myObj != null)
{
Cleanup(myObj);
myObj = null;
}
}
由于此 Dispose 实现未同步,因此 Cleanup
可能由第一个线程调用,然后在 _myObj
设置为 null 之前的第二个线程。 这是否是安全问题取决于 Cleanup
代码运行时发生的情况。 不同步的 Dispose 实现的一个主要问题涉及到资源句柄(例如文件)的使用。 处置不当会导致使用错误的句柄,这往往会导致安全漏洞。
构造函数中的争用条件
在某些应用程序中,其他线程可能会在其类构造函数完全运行之前访问类成员。 你应该检查所有类构造函数以确保如果发生这种情况不存在安全问题,或者在必要时同步线程。
缓存对象的争用条件
如果类的其他部分未适当同步,则缓存安全信息或使用代码访问安全断言操作的代码也可能容易受到争用条件的影响,如以下示例所示。
Sub SomeSecureFunction()
If SomeDemandPasses() Then
fCallersOk = True
DoOtherWork()
fCallersOk = False
End If
End Sub
Sub DoOtherWork()
If fCallersOK Then
DoSomethingTrusted()
Else
DemandSomething()
DoSomethingTrusted()
End If
End Sub
void SomeSecureFunction()
{
if (SomeDemandPasses())
{
fCallersOk = true;
DoOtherWork();
fCallersOk = false;
}
}
void DoOtherWork()
{
if (fCallersOK)
{
DoSomethingTrusted();
}
else
{
DemandSomething();
DoSomethingTrusted();
}
}
如果 DoOtherWork
有其他路径可以从具有相同对象的另一个线程调用,则不受信任的调用者可能会跳过请求。
如果你的代码缓存了安全信息,请确保检查它是否存在此漏洞。
终结者中的争用条件
争用条件也可能发生在引用静态或非托管资源的对象中,然后在其终结器中释放这些资源。 如果多个对象共享一个在类的终结器中操作的资源,则这些对象必须同步对该资源的所有访问。