Bug 1518798: Treat SysWOW64 the same as the system directory in the untrusted modules ping r=aklotz
authorCarl Corcoran <ccorcoran@mozilla.com>
Mon, 14 Jan 2019 23:53:13 +0000
changeset 514082 79f7656b35eb2d612ff56302b1e299a55d885b9b
parent 514081 1b1fe5815dffcacf40731336a114a8c2fcc2adf7
child 514083 ff6b83e3521661987c7d16cdce3d81dc87496086
push id1953
push userffxbld-merge
push dateMon, 11 Mar 2019 12:10:20 +0000
treeherdermozilla-release@9c35dcbaa899 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersaklotz
bugs1518798
milestone66.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1518798: Treat SysWOW64 the same as the system directory in the untrusted modules ping r=aklotz Under WOW64, the SysWOW64 directory is the effective system directory. A flag has been added (ModuleTrustFlags::SysWOW64Directory) representing this directory, and we now grant this the same trustworthiness as ModuleTrustFlags::SystemDirectory. Depends on D16013 Differential Revision: https://phabricator.services.mozilla.com/D16160
toolkit/components/telemetry/docs/data/untrusted-modules-ping.rst
toolkit/xre/ModuleEvaluator_windows.cpp
toolkit/xre/ModuleEvaluator_windows.h
--- a/toolkit/components/telemetry/docs/data/untrusted-modules-ping.rst
+++ b/toolkit/components/telemetry/docs/data/untrusted-modules-ping.rst
@@ -88,16 +88,17 @@ This is a bitfield indicating whether va
 * ``4`` if the module's version info indicates it's a Microsoft module
 * ``8`` if the module is located in the Firefox application directory
 * ``0x10`` if the module has the same location and version information as the Firefox executable
 * ``0x20`` if the module is located in the system directory
 * ``0x40`` if the module is a known keyboard layout DLL
 * ``0x80`` if the module is an internally-recognized JIT module
 * ``0x100`` if the module is located in the Windows Side-by-side directory (introduced in Firefox 66)
 * ``0x200`` if the module is the XPCOM module, xul.dll (introduced in Firefox 66)
+* ``0x400`` if the module is located in the SysWOW64 directory (introduced in Firefox 66)
 
 payload.combinedStacks
 ----------------------
 This object holds stack traces that correspond to events in ``payload.events``.
 
 .. code-block:: js
 
     "combinedStacks": {
@@ -132,8 +133,9 @@ Notes
 
 Version History
 ~~~~~~~~~~~~~~~
 - Firefox 65: Initial support (`bug 1435827 <https://bugzilla.mozilla.org/show_bug.cgi?id=1435827>`_).
 - Firefox 66:
 
    - Added Windows Side-by-side directory trust flag (`bug 1514694 <https://bugzilla.mozilla.org/show_bug.cgi?id=1514694>`_).
    - Added module load times (``xulLoadDurationMS``, ``loadDurationMS``) and xul.dll trust flag (`bug 1518490 <https://bugzilla.mozilla.org/show_bug.cgi?id=1518490>`_).
+   - Added SysWOW64 trust flag (`bug 1518798 <https://bugzilla.mozilla.org/show_bug.cgi?id=1518798>`_).
--- a/toolkit/xre/ModuleEvaluator_windows.cpp
+++ b/toolkit/xre/ModuleEvaluator_windows.cpp
@@ -126,16 +126,36 @@ ModuleEvaluator::ModuleEvaluator() {
   nsCOMPtr<nsIFile> winSxSDir;
   if (NS_SUCCEEDED(NS_GetSpecialDirectory(NS_WIN_WINDOWS_DIR,
                                           getter_AddRefs(winSxSDir)))) {
     if (NS_SUCCEEDED(winSxSDir->Append(NS_LITERAL_STRING("WinSxS")))) {
       winSxSDir->GetPath(mWinSxSDirectory);
     }
   }
 
+#ifdef _M_IX86
+  mSysWOW64Directory.SetLength(MAX_PATH);
+  UINT sysWOWlen =
+      ::GetSystemWow64DirectoryW((char16ptr_t)mSysWOW64Directory.BeginWriting(),
+                                 mSysWOW64Directory.Length());
+  if (!sysWOWlen || (sysWOWlen > mSysWOW64Directory.Length())) {
+    // This could be the following cases:
+    // - Genuine error
+    // - GetLastError == ERROR_CALL_NOT_IMPLEMENTED (32-bit Windows)
+    // - Buffer too small. The buffer being MAX_PATH, this should be so rare we
+    //   don't bother with this case.
+    // In all these cases, consider this directory unavailable.
+    mSysWOW64Directory.Truncate();
+  } else {
+    // In this case, GetSystemWow64DirectoryW returns the length of the string,
+    // not including the null-terminator.
+    mSysWOW64Directory.SetLength(sysWOWlen);
+  }
+#endif  // _M_IX86
+
   nsCOMPtr<nsIFile> exeDir;
   if (NS_SUCCEEDED(
           NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(exeDir)))) {
     exeDir->GetPath(mExeDirectory);
   }
 
   nsCOMPtr<nsIFile> exeFile;
   if (NS_SUCCEEDED(XRE_GetBinaryPath(getter_AddRefs(exeFile)))) {
@@ -224,16 +244,27 @@ Maybe<bool> ModuleEvaluator::IsModuleTru
   // Is the DLL in the system directory?
   if (!mSysDirectory.IsEmpty() &&
       StringBeginsWith(dllFullPath, mSysDirectory,
                        nsCaseInsensitiveStringComparator())) {
     aDllInfo.mTrustFlags |= ModuleTrustFlags::SystemDirectory;
     score += 50;
   }
 
+#ifdef _M_IX86
+  // Under WOW64, SysWOW64 is the effective system directory. Give SysWOW64 the
+  // same trustworthiness as ModuleTrustFlags::SystemDirectory.
+  if (!mSysWOW64Directory.IsEmpty() &&
+      StringBeginsWith(dllFullPath, mSysWOW64Directory,
+                       nsCaseInsensitiveStringComparator())) {
+    aDllInfo.mTrustFlags |= ModuleTrustFlags::SysWOW64Directory;
+    score += 50;
+  }
+#endif  // _M_IX86
+
   // Is the DLL in the WinSxS directory? Some Microsoft DLLs (e.g. comctl32) are
   // loaded from here and don't have digital signatures. So while this is not a
   // guarantee of trustworthiness, but is at least as valid as system32.
   if (!mWinSxSDirectory.IsEmpty() &&
       StringBeginsWith(dllFullPath, mWinSxSDirectory,
                        nsCaseInsensitiveStringComparator())) {
     aDllInfo.mTrustFlags |= ModuleTrustFlags::WinSxSDirectory;
     score += 50;
--- a/toolkit/xre/ModuleEvaluator_windows.h
+++ b/toolkit/xre/ModuleEvaluator_windows.h
@@ -26,16 +26,17 @@ enum class ModuleTrustFlags : uint32_t {
   MicrosoftVersion = 4,
   FirefoxDirectory = 8,
   FirefoxDirectoryAndVersion = 0x10,
   SystemDirectory = 0x20,
   KeyboardLayout = 0x40,
   JitPI = 0x80,
   WinSxSDirectory = 0x100,
   Xul = 0x200,
+  SysWOW64Directory = 0x400,
 };
 
 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(ModuleTrustFlags);
 
 // This class is very similar to mozilla::glue::ModuleLoadEvent, except this is
 // more Gecko-friendly, and has a few more fields that enable us to evaluate
 // trustworthiness.
 class ModuleLoadEvent {
@@ -93,16 +94,19 @@ class ModuleLoadEvent {
 };
 
 // This class performs trustworthiness evaluation for incoming DLLs.
 class ModuleEvaluator {
   Maybe<uint64_t> mExeVersion;  // Version number of the running EXE image
   nsString mExeDirectory;
   nsString mSysDirectory;
   nsString mWinSxSDirectory;
+#ifdef _M_IX86
+  nsString mSysWOW64Directory;
+#endif  // _M_IX86
   Vector<nsString, 0, InfallibleAllocPolicy> mKeyboardLayoutDlls;
 
  public:
   ModuleEvaluator();
 
   /**
    * Evaluates the trustworthiness of the given module and fills in remaining
    * fields in ModuleInfo.