Sdílet prostřednictvím


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.

Viz také