Backed out changeset 6bd7baadb78c (bug 1702086) for causing Bug 1607574.

CLOSED TREE
This commit is contained in:
Alexandru Michis 2021-04-28 23:23:01 +03:00
parent 336af263f9
commit 335b6f5f96
2 changed files with 42 additions and 44 deletions

View File

@ -19,8 +19,6 @@
#define CV_SIGNATURE 0x53445352 // 'SDSR' #define CV_SIGNATURE 0x53445352 // 'SDSR'
namespace {
struct CodeViewRecord70 { struct CodeViewRecord70 {
uint32_t signature; uint32_t signature;
GUID pdbSignature; GUID pdbSignature;
@ -30,13 +28,6 @@ struct CodeViewRecord70 {
char pdbFileName[1]; char pdbFileName[1];
}; };
struct HModuleFreer {
using pointer = HMODULE;
void operator()(pointer aModule) { ::FreeLibrary(aModule); }
};
} // anonymous namespace
static constexpr char digits[16] = {'0', '1', '2', '3', '4', '5', '6', '7', static constexpr char digits[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
@ -179,19 +170,6 @@ SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf() {
std::size(modulePath))) { std::size(modulePath))) {
continue; continue;
} }
// Load the module again to make sure that its handle will remain valid
// as we attempt to read the PDB information from it. We load the DLL as
// a datafile so that if the module actually gets unloaded between the call
// to EnumProcessModules and the following LoadLibraryEx, we don't end up
// running the now newly loaded module's DllMain function. If the module
// is already loaded, LoadLibraryEx just increments its refcount.
mozilla::UniquePtr<HMODULE, HModuleFreer> handleLock(
LoadLibraryExW(modulePath, NULL, LOAD_LIBRARY_AS_DATAFILE));
if (!handleLock) {
continue;
}
mozilla::UniquePtr<char[]> utf8ModulePath( mozilla::UniquePtr<char[]> utf8ModulePath(
mozilla::glue::WideToUTF8(modulePath)); mozilla::glue::WideToUTF8(modulePath));
if (!utf8ModulePath) { if (!utf8ModulePath) {
@ -201,10 +179,6 @@ SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf() {
MODULEINFO module = {0}; MODULEINFO module = {0};
if (!GetModuleInformation(hProcess, hMods[i], &module, if (!GetModuleInformation(hProcess, hMods[i], &module,
sizeof(MODULEINFO))) { sizeof(MODULEINFO))) {
// If the module was unloaded before LoadLibraryEx, LoadLibraryEx
// loads the module onto an address different from hMods[i] and
// thus GetModuleInformation fails with ERROR_INVALID_HANDLE.
// We skip that case.
continue; continue;
} }
@ -251,12 +225,31 @@ SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf() {
#endif // !defined(_M_ARM64) #endif // !defined(_M_ARM64)
std::string breakpadId; std::string breakpadId;
// Load the module again to make sure that its handle will remain
// valid as we attempt to read the PDB information from it. We load the
// DLL as a datafile so that if the module actually gets unloaded between
// the call to EnumProcessModules and the following LoadLibraryEx, we
// don't end up running the now newly loaded module's DllMain function. If
// the module is already loaded, LoadLibraryEx just increments its
// refcount.
//
// Note that because of the race condition above, merely loading the DLL
// again is not safe enough, therefore we also need to make sure that we
// can read the memory mapped at the base address before we can safely
// proceed to actually access those pages.
HMODULE handleLock =
LoadLibraryExW(modulePath, NULL, LOAD_LIBRARY_AS_DATAFILE);
MEMORY_BASIC_INFORMATION vmemInfo = {0};
std::string pdbSig; std::string pdbSig;
uint32_t pdbAge; uint32_t pdbAge;
std::string pdbPathStr; std::string pdbPathStr;
std::string pdbNameStr; std::string pdbNameStr;
char* pdbName = nullptr; char* pdbName = nullptr;
if (GetPdbInfo((uintptr_t)module.lpBaseOfDll, pdbSig, pdbAge, &pdbName)) { if (handleLock &&
sizeof(vmemInfo) ==
VirtualQuery(module.lpBaseOfDll, &vmemInfo, sizeof(vmemInfo)) &&
vmemInfo.State == MEM_COMMIT &&
GetPdbInfo((uintptr_t)module.lpBaseOfDll, pdbSig, pdbAge, &pdbName)) {
MOZ_ASSERT(breakpadId.empty()); MOZ_ASSERT(breakpadId.empty());
breakpadId += pdbSig; breakpadId += pdbSig;
AppendHex(pdbAge, breakpadId, WITHOUT_PADDING); AppendHex(pdbAge, breakpadId, WITHOUT_PADDING);
@ -273,6 +266,8 @@ SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf() {
breakpadId, moduleNameStr, modulePathStr, pdbNameStr, breakpadId, moduleNameStr, modulePathStr, pdbNameStr,
pdbPathStr, GetVersion(modulePath), ""); pdbPathStr, GetVersion(modulePath), "");
sharedLibraryInfo.AddSharedLibrary(shlib); sharedLibraryInfo.AddSharedLibrary(shlib);
FreeLibrary(handleLock); // ok to free null handles
} }
return sharedLibraryInfo; return sharedLibraryInfo;

View File

@ -137,25 +137,9 @@ SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf() {
continue; continue;
} }
// Load the module again to make sure that its handle will remain valid
// as we attempt to read the PDB information from it. We load the DLL as
// a datafile so that if the module actually gets unloaded between the call
// to EnumProcessModules and the following LoadLibraryEx, we don't end up
// running the now newly loaded module's DllMain function. If the module
// is already loaded, LoadLibraryEx just increments its refcount.
nsModuleHandle handleLock(
LoadLibraryEx(modulePath, NULL, LOAD_LIBRARY_AS_DATAFILE));
if (!handleLock) {
continue;
}
MODULEINFO module = {0}; MODULEINFO module = {0};
if (!GetModuleInformation(hProcess, hMods[i], &module, if (!GetModuleInformation(hProcess, hMods[i], &module,
sizeof(MODULEINFO))) { sizeof(MODULEINFO))) {
// If the module was unloaded before LoadLibraryEx, LoadLibraryEx
// loads the module onto an address different from hMods[i] and
// thus GetModuleInformation fails with ERROR_INVALID_HANDLE.
// We skip that case.
continue; continue;
} }
@ -203,12 +187,29 @@ SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf() {
!moduleNameStr.LowerCaseEqualsLiteral("ntdll.dll")); !moduleNameStr.LowerCaseEqualsLiteral("ntdll.dll"));
nsCString breakpadId; nsCString breakpadId;
// Load the module again to make sure that its handle will remain
// valid as we attempt to read the PDB information from it. We load the
// DLL as a datafile so that if the module actually gets unloaded between
// the call to EnumProcessModules and the following LoadLibraryEx, we don't
// end up running the now newly loaded module's DllMain function. If the
// module is already loaded, LoadLibraryEx just increments its refcount.
//
// Note that because of the race condition above, merely loading the DLL
// again is not safe enough, therefore we also need to make sure that we
// can read the memory mapped at the base address before we can safely
// proceed to actually access those pages.
HMODULE handleLock =
LoadLibraryEx(modulePath, NULL, LOAD_LIBRARY_AS_DATAFILE);
MEMORY_BASIC_INFORMATION vmemInfo = {0};
nsID pdbSig; nsID pdbSig;
uint32_t pdbAge; uint32_t pdbAge;
nsAutoString pdbPathStr; nsAutoString pdbPathStr;
nsAutoString pdbNameStr; nsAutoString pdbNameStr;
char* pdbName = nullptr; char* pdbName = nullptr;
if (canGetPdbInfo && if (handleLock &&
sizeof(vmemInfo) ==
VirtualQuery(module.lpBaseOfDll, &vmemInfo, sizeof(vmemInfo)) &&
vmemInfo.State == MEM_COMMIT && canGetPdbInfo &&
GetPdbInfo((uintptr_t)module.lpBaseOfDll, pdbSig, pdbAge, &pdbName)) { GetPdbInfo((uintptr_t)module.lpBaseOfDll, pdbSig, pdbAge, &pdbName)) {
MOZ_ASSERT(breakpadId.IsEmpty()); MOZ_ASSERT(breakpadId.IsEmpty());
breakpadId.AppendPrintf( breakpadId.AppendPrintf(
@ -234,6 +235,8 @@ SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf() {
breakpadId, moduleNameStr, modulePathStr, pdbNameStr, breakpadId, moduleNameStr, modulePathStr, pdbNameStr,
pdbPathStr, GetVersion(modulePath), ""); pdbPathStr, GetVersion(modulePath), "");
sharedLibraryInfo.AddSharedLibrary(shlib); sharedLibraryInfo.AddSharedLibrary(shlib);
FreeLibrary(handleLock); // ok to free null handles
} }
return sharedLibraryInfo; return sharedLibraryInfo;