另一个关注领域是种族条件利用的安全漏洞的可能性。 有多种方法可能会发生这种情况。 后面的子主题概述了开发人员必须避免的一些主要陷阱。
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
有其他路径可以从具有相同对象的另一个线程调用,则不受信任的调用者可能会跳过请求。
如果代码缓存安全信息,请确保查看此漏洞。
终结者中的争用条件
争用条件也可能发生在引用静态或非托管资源的对象中,然后在其终结器中释放这些资源。 如果多个对象共享在类的终结器中操作的资源,这些对象必须同步所有对该资源的访问。