Zabezpečení a konflikty časování
Další oblastí zájmu je potenciál bezpečnostních otvorů využívaných podmínkami závodu. Existuje několik způsobů, jak k tomu může dojít. Dílčí dílčí oblasti, které následují, popisují některé hlavní nástrahy, kterým se vývojář musí vyhnout.
Podmínky časování v metodě Dispose
Pokud metoda Dispose třídy (další informace, viz uvolňování paměti) není synchronizována, je možné, že kód čištění uvnitř Dispose lze spustit více než jednou, jak je znázorněno v následujícím příkladu.
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;
}
}
Vzhledem k tomu, že tato implementace Dispose není synchronizována, je možné Cleanup
ji volat prvním jedním vláknem a potom druhé vlákno před _myObj
nastavením na hodnotu null. To, jestli se jedná o bezpečnostní problém, závisí na tom, co se stane, když Cleanup
se kód spustí. Hlavním problémem s nesynchronizovanými implementacemi Dispose je použití popisovačů prostředků, jako jsou soubory. Nesprávné odstranění může způsobit použití nesprávného popisovače, což často vede k ohrožením zabezpečení.
Podmínky časování v konstruktorech
V některých aplikacích může být možné, aby ostatní vlákna přistupovala ke členům třídy před tím, než se jejich konstruktory třídy úplně spustily. Měli byste zkontrolovat všechny konstruktory tříd, abyste měli jistotu, že neexistují žádné problémy se zabezpečením, pokud k tomu dojde, nebo v případě potřeby synchronizujte vlákna.
Podmínky časování s objekty uloženými v mezipaměti
Kód, který ukládá informace o zabezpečení do mezipaměti nebo používá operaci Assert zabezpečení přístupu kódu, může být také zranitelný vůči časovacím podmínkám, pokud ostatní části třídy nejsou správně synchronizovány, jak je znázorněno v následujícím příkladu.
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();
}
}
Pokud existují další cesty, DoOtherWork
které lze volat z jiného vlákna se stejným objektem, může nedůvěryhodný volající vyklouznout po poptávce.
Pokud váš kód ukládá informace o zabezpečení do mezipaměti, ujistěte se, že je zkontrolujete pro tuto chybu zabezpečení.
Podmínky závodu v finalizátorech
K podmínkám časování může dojít také v objektu, který odkazuje na statický nebo nespravovaný prostředek, který pak uvolní v finalizátoru. Pokud více objektů sdílí prostředek, který je manipulován s finalizátorem třídy, musí objekty synchronizovat veškerý přístup k danému prostředku.