diff --git a/dom/media/gmp/GMPLoader.cpp b/dom/media/gmp/GMPLoader.cpp index 75630c5fdd3..4f3c467fb03 100644 --- a/dom/media/gmp/GMPLoader.cpp +++ b/dom/media/gmp/GMPLoader.cpp @@ -15,6 +15,9 @@ #if defined(XP_WIN) && defined(MOZ_SANDBOX) #include "mozilla/sandboxTarget.h" +#include "windows.h" +#include +#include #endif #if defined(HASH_NODE_ID_WITH_DEVICE_ID) @@ -69,6 +72,43 @@ GMPLoader* CreateGMPLoader(SandboxStarter* aStarter) { return static_cast(new GMPLoaderImpl(aStarter)); } +#if defined(XP_WIN) +MOZ_NEVER_INLINE +static bool +GetStackAfterCurrentFrame(uint8_t** aOutTop, uint8_t** aOutBottom) +{ + // "Top" of the free space on the stack is directly after the memory + // holding our return address. + uint8_t* top = (uint8_t*)_AddressOfReturnAddress(); + + // Look down the stack until we find the guard page... + MEMORY_BASIC_INFORMATION memInfo = {0}; + uint8_t* bottom = top; + while (1) { + if (!VirtualQuery(bottom, &memInfo, sizeof(memInfo))) { + return false; + } + if ((memInfo.Protect & PAGE_GUARD) == PAGE_GUARD) { + bottom = (uint8_t*)memInfo.BaseAddress + memInfo.RegionSize; +#ifdef DEBUG + if (!VirtualQuery(bottom, &memInfo, sizeof(memInfo))) { + return false; + } + assert(!(memInfo.Protect & PAGE_GUARD)); // Should have found boundary. +#endif + break; + } else if (memInfo.State != MEM_COMMIT || + (memInfo.AllocationProtect & PAGE_READWRITE) != PAGE_READWRITE) { + return false; + } + bottom = (uint8_t*)memInfo.BaseAddress - 1; + } + *aOutTop = top; + *aOutBottom = bottom; + return true; +} +#endif + bool GMPLoaderImpl::Load(const char* aLibPath, uint32_t aLibPathLen, @@ -106,6 +146,17 @@ GMPLoaderImpl::Load(const char* aLibPath, if (!rlz_lib::BytesToString(digest, SHA256_LENGTH, &nodeId)) { return false; } + // We've successfully bound the origin salt to node id. + // rlz_lib::GetRawMachineId and/or the system functions it + // called could have left user identifiable data on the stack, + // so carefully zero the stack down to the guard page. + uint8_t* top; + uint8_t* bottom; + if (!GetStackAfterCurrentFrame(&top, &bottom)) { + return false; + } + assert(top >= bottom); + SecureZeroMemory(bottom, (top - bottom)); } else #endif {