У меня есть следующий класс, который компилируется в Visual Studio 2015:
class MitigationPolicyChecker
{
public:
static auto& getInstance()
{
static MitigationPolicyChecker instance;
return instance;
}
MitigationPolicyChecker(MitigationPolicyChecker const&) = delete;
MitigationPolicyChecker(MitigationPolicyChecker&&) = delete;
MitigationPolicyChecker& operator=(MitigationPolicyChecker const&) = delete;
MitigationPolicyChecker& operator=(MitigationPolicyChecker&&) = delete;
bool IsDynamicCodeProhibited();
private:
MitigationPolicyChecker() = default;
~MitigationPolicyChecker() = default;
void GetDynamicCodePolicy();
bool m_bDynamicCodeProhibited = false;
};
Этот класс предназначен для запуска из DllMain и проверяет структуру в загруженном образе NtDll, чтобы проверить наличие определенной политики смягчения
В редких случаях (<0,0001% случаев загрузки DLL) этот синглтон вызывает сбой приложения. Однако сбой не связан с тем, что пытается сделать класс, или с хорошо известным списком вещей, которые не разрешены в DllMain (насколько я могу судить). Это связано с созданием самого синглтона. </p>
Стек вызовов в WinDbg выглядит следующим образом:
00 OurDll!MitigationPolicyChecker::getInstance+0x1a
02 OurDll!Initialize+0x79
03 OurDll!DllMain+0x1c9
04 OurDll!dllmain_dispatch+0x74
05 ntdll!LdrpRunInitializeRoutines+0x1fe
06 ntdll!LdrGetProcedureAddressEx+0x2aa
07 ntdll!LdrpCorInitialize+0x1a1
08 ntdll!LdrpInitializeProcess+0x1816
09 ntdll! ?? ::FNODOBFM::`string'+0x22790
0a ntdll!LdrInitializeThunk+0xe
На линии static MitigationPolicyChecker instance
* 1013 происходит нарушение доступа* И аварийная сборочная линия - последняя строка здесь, по-видимому rdx и rcx были равны нулю в соответствии с записью исключения (возможно, сбой локального хранилища потока ??):
0:000> uf OurDll!MitigationPolicyChecker::getInstance
OurDll!MitigationPolicyChecker::getInstance:
8 000007fe`fbc38ed0 4883ec28 sub rsp,28h
9 000007fe`fbc38ed4 b804000000 mov eax,4
9 000007fe`fbc38ed9 8bc0 mov eax,eax
9 000007fe`fbc38edb 8b0dcf850b00 mov ecx,dword ptr [OurDll!_tls_index (000007fe`fbcf14b0)]
9 000007fe`fbc38ee1 65488b142558000000 mov rdx,qword ptr gs:[58h]
9 000007fe`fbc38eea 488b0cca mov rcx,qword ptr [rdx+rcx*8]
Так что здесь происходит? У процесса есть только один активный поток во время сбоя, поэтому я не думаю, что это проблема параллелизма. Насколько я знаю:
- Статический объект должен быть создан при первом доступе.
- Статика обычно инициализируется непосредственно перед DllMain, но в этом случае, поскольку это функцияна уровне статики он будет создан при вызове, а поскольку он VS2015, он будет создан как «магическая статика».
Есть ли что-то, чего мне не хватает, что делает это небезопасным?