Bug 1483687: Part 6 - Update a11y DLL blocking to use the new unified DLL blocklist; r=Jamie

Even though a11y DLLs are not strictly "DLL blocking," I felt that it would
make sense to include them in our unified DLL blocklist. This patch delegates
much of that functionality to the unified blocklist code. Going forward, any
further blocklist entries for in-proc a11y DLLs should be added to
mozglue/build/WindowsDllBlocklistDefs.in via the A11yBlocklistEntry type.

Differential Revision: https://phabricator.services.mozilla.com/D37001

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Aaron Klotz 2019-07-16 18:03:54 +00:00
parent 8f1d66c29a
commit 088309ee7c
3 changed files with 17 additions and 95 deletions

View File

@ -7,6 +7,7 @@
#include "Compatibility.h"
#include "mozilla/WindowsVersion.h"
#include "mozilla/WinHeaderOnlyUtils.h"
#include "nsExceptionHandler.h"
#include "nsPrintfCString.h"
#include "nsUnicharUtils.h"
@ -31,48 +32,12 @@ static const wchar_t* ConsumerStringMap[CONSUMERS_ENUM_LEN + 1] = {
bool Compatibility::IsModuleVersionLessThan(HMODULE aModuleHandle,
unsigned long long aVersion) {
// Get the full path to the dll.
// We start with MAX_PATH, but the path can actually be longer.
DWORD fnSize = MAX_PATH;
UniquePtr<wchar_t[]> fileName;
while (true) {
fileName = MakeUnique<wchar_t[]>(fnSize);
DWORD retLen = ::GetModuleFileNameW(aModuleHandle, fileName.get(), fnSize);
MOZ_ASSERT(retLen != 0);
if (retLen == 0) {
return true;
}
if (retLen == fnSize && ::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
// The buffer was too short. Increase the size and try again.
fnSize *= 2;
}
break; // Success!
}
// Get the version info from the file.
DWORD length = ::GetFileVersionInfoSizeW(fileName.get(), nullptr);
if (length == 0) {
WindowsErrorResult<ModuleVersion> version = GetModuleVersion(aModuleHandle);
if (version.isErr()) {
return true;
}
auto versionInfo = MakeUnique<unsigned char[]>(length);
if (!::GetFileVersionInfoW(fileName.get(), 0, length, versionInfo.get())) {
return true;
}
UINT uLen;
VS_FIXEDFILEINFO* fixedFileInfo = nullptr;
if (!::VerQueryValueW(versionInfo.get(), L"\\", (LPVOID*)&fixedFileInfo,
&uLen)) {
return true;
}
// Combine into a 64 bit value for comparison.
unsigned long long version =
((unsigned long long)fixedFileInfo->dwFileVersionMS) << 32 |
((unsigned long long)fixedFileInfo->dwFileVersionLS);
return version < aVersion;
return version.unwrap() < aVersion;
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -14,6 +14,7 @@
#include "mozilla/mscom/ProcessRuntime.h"
#include "mozilla/mscom/Registration.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/WinHeaderOnlyUtils.h"
#include "nsAccessibilityService.h"
#include "nsWindowsHelpers.h"
#include "nsCOMPtr.h"
@ -28,6 +29,10 @@
# define STATE_SYSTEM_NORMAL (0)
#endif // !defined(STATE_SYSTEM_NORMAL)
#define DLL_BLOCKLIST_ENTRY(name, ...) {L##name, __VA_ARGS__},
#define DLL_BLOCKLIST_STRING_TYPE const wchar_t*
#include "mozilla/WindowsDllBlocklistA11yDefs.h"
namespace mozilla {
namespace a11y {
@ -156,31 +161,6 @@ LazyInstantiator::GetClientPid(const DWORD aClientTid) {
return ::GetProcessIdOfThread(callingThread);
}
#define ALL_VERSIONS ((unsigned long long)-1LL)
struct DllBlockInfo {
// The name of the DLL.
const wchar_t* mName;
// If mUntilVersion is ALL_VERSIONS, we'll block all versions of this dll.
// Otherwise, we'll block all versions less than the given version, as queried
// by GetFileVersionInfo and VS_FIXEDFILEINFO's dwFileVersionMS and
// dwFileVersionLS fields.
//
// Note that the version is usually 4 components, which is A.B.C.D
// encoded as 0x AAAA BBBB CCCC DDDD ULL (spaces added for clarity).
unsigned long long mUntilVersion;
};
/**
* This is the blocklist for known "bad" DLLs that instantiate a11y.
*/
static const DllBlockInfo gBlockedInprocDlls[] = {
// RealPlayer, bug 1418535, bug 1437417
// Versions before 18.1.11.0 cause severe performance problems.
{L"dtvhooks.dll", MAKE_FILE_VERSION(18, 1, 11, 0)},
{L"dtvhooks64.dll", MAKE_FILE_VERSION(18, 1, 11, 0)}};
/**
* This is the blocklist for known "bad" remote clients that instantiate a11y.
*/
@ -213,11 +193,9 @@ bool LazyInstantiator::IsBlockedInjection() {
// This dll isn't loaded.
continue;
}
if (blockedDll.mUntilVersion == ALL_VERSIONS) {
return true;
}
return Compatibility::IsModuleVersionLessThan(module,
blockedDll.mUntilVersion);
WindowsErrorResult<ModuleVersion> version = GetModuleVersion(module);
return version.isOk() && blockedDll.IsVersionBlocked(version.unwrap());
}
return false;

View File

@ -20,6 +20,7 @@
#include "mozilla/mscom/Utils.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/WindowsVersion.h"
#include "mozilla/WinHeaderOnlyUtils.h"
#include "nsDirectoryServiceDefs.h"
#include "nsDirectoryServiceUtils.h"
#include "ProxyWrappers.h"
@ -275,35 +276,13 @@ static bool GetInstantiatorExecutable(const DWORD aPid,
static void AppendVersionInfo(nsIFile* aClientExe, nsAString& aStrToAppend) {
MOZ_ASSERT(!NS_IsMainThread());
nsAutoString fullPath;
nsresult rv = aClientExe->GetPath(fullPath);
if (NS_FAILED(rv)) {
WindowsErrorResult<ModuleVersion> version = GetModuleVersion(aClientExe);
if (version.isErr()) {
return;
}
DWORD verInfoSize = ::GetFileVersionInfoSize(fullPath.get(), nullptr);
if (!verInfoSize) {
return;
}
auto verInfoBuf = MakeUnique<BYTE[]>(verInfoSize);
if (!::GetFileVersionInfo(fullPath.get(), 0, verInfoSize, verInfoBuf.get())) {
return;
}
VS_FIXEDFILEINFO* fixedInfo = nullptr;
UINT fixedInfoLen = 0;
if (!::VerQueryValue(verInfoBuf.get(), L"\\", (LPVOID*)&fixedInfo,
&fixedInfoLen)) {
return;
}
uint32_t major = HIWORD(fixedInfo->dwFileVersionMS);
uint32_t minor = LOWORD(fixedInfo->dwFileVersionMS);
uint32_t patch = HIWORD(fixedInfo->dwFileVersionLS);
uint32_t build = LOWORD(fixedInfo->dwFileVersionLS);
uint16_t major, minor, patch, build;
Tie(major, minor, patch, build) = version.unwrap().AsTuple();
aStrToAppend.AppendLiteral(u"|");