tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit a8c9dab64432c0494c803ccabd7b9cacef75adae
parent 03ade94314b7318be249b7bf3e0c6d7e81c7c581
Author: Cristina Horotan <chorotan@mozilla.com>
Date:   Mon, 15 Dec 2025 13:00:32 +0200

Revert "Bug 1998650 - Only favor system DLLs if we can guarantee compatibility. r=bobowen,win-reviewers,gstoll" for causing build bustage at LauncherProcessWin.cpp

This reverts commit 1bfdebd5b9ce46f26d83b25bb3ae177573a12235.

Diffstat:
Mbrowser/app/winlauncher/LauncherProcessWin.cpp | 116+++++++++++++++++++++----------------------------------------------------------
Mbrowser/app/winlauncher/moz.build | 1-
Mmozglue/misc/WindowsProcessMitigations.cpp | 51---------------------------------------------------
Mmozglue/misc/WindowsProcessMitigations.h | 3---
Msecurity/sandbox/win/src/sandboxbroker/sandboxBroker.cpp | 35+++++++++++------------------------
5 files changed, 42 insertions(+), 164 deletions(-)

diff --git a/browser/app/winlauncher/LauncherProcessWin.cpp b/browser/app/winlauncher/LauncherProcessWin.cpp @@ -10,6 +10,7 @@ #include "mozilla/CmdLineAndEnvUtils.h" #include "mozilla/DebugOnly.h" +#include "mozilla/DynamicallyLinkedFunctionPtr.h" #include "mozilla/glue/Debug.h" #include "mozilla/GeckoArgs.h" #include "mozilla/Maybe.h" @@ -17,13 +18,12 @@ #include "mozilla/SafeMode.h" #include "mozilla/UniquePtr.h" #include "mozilla/WindowsConsole.h" -#include "mozilla/WindowsProcessMitigations.h" +#include "mozilla/WindowsVersion.h" #include "mozilla/WinHeaderOnlyUtils.h" #include "nsWindowsHelpers.h" #include <windows.h> #include <processthreadsapi.h> -#include <shlwapi.h> #include "DllBlocklistInit.h" #include "ErrorHandler.h" @@ -110,82 +110,16 @@ static nsReturnRef<HANDLE> CreateJobAndAssignProcess(HANDLE aProcess) { return job.out(); } -enum class VCRuntimeDLLDir : bool { - Application, - System, -}; -static bool GetMSVCP140VersionInfo(VCRuntimeDLLDir aDir, - uint64_t& aOutVersion) { - wchar_t dllPath[MAX_PATH]; - if (aDir == VCRuntimeDLLDir::Application) { - DWORD size = ::GetModuleFileNameW(nullptr, dllPath, MAX_PATH); - if (!size || - (size == MAX_PATH && ::GetLastError() == ERROR_INSUFFICIENT_BUFFER) || - !::PathRemoveFileSpecW(dllPath)) { - return false; - } - } else { - MOZ_ASSERT(aDir == VCRuntimeDLLDir::System); - UINT size = ::GetSystemDirectoryW(dllPath, MAX_PATH); - if (!size || size >= MAX_PATH) { - return false; - } - } - - if (!::PathAppendW(dllPath, L"msvcp140.dll")) { - return false; - } - HMODULE crt = - ::LoadLibraryExW(dllPath, nullptr, LOAD_LIBRARY_AS_IMAGE_RESOURCE); - if (!crt) { - return false; - } - - mozilla::nt::PEHeaders headers{crt}; - bool result = headers.GetVersionInfo(aOutVersion); - ::FreeLibrary(crt); - return result; -} - -/** - * Choose whether we want to favor loading DLLs from the system directory over - * the application directory. This choice automatically propagates to all child - * processes. In particular, it determines whether child processes will load - * Visual C++ runtime DLLs from the system or the application directory at - * startup. - * - * Whenever possible, we want all processes to favor loading DLLs from the - * system directory. But if old Visual C++ runtime DLLs are installed - * system-wide, then we must favor loading from the application directory - * instead to ensure compatibility, at least during startup. So in this case we - * only apply the delayed variant of the mitigation and only in sandboxed - * processes, which is the best compromise (see SandboxBroker::LaunchApp). - * - * This function is called from the launcher process *and* the browser process. - * This is because if the launcher process is disabled, we still want the - * browser process to go through this code so that it enforces the correct - * choice for itself and for child processes. - */ -static void EnablePreferLoadFromSystem32IfCompatible() { - // We may already have the mitigation if we are the browser process and we - // inherited it from the launcher process. - if (!mozilla::IsPreferLoadFromSystem32Available() || - mozilla::IsPreferLoadFromSystem32Enabled()) { - return; - } +#if !defined( \ + PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_PREFER_SYSTEM32_ALWAYS_ON) +# define PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_PREFER_SYSTEM32_ALWAYS_ON \ + (0x00000001ULL << 60) +#endif // !defined(PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_PREFER_SYSTEM32_ALWAYS_ON) - // Only bail out if (1) there is a conflict because the two DLLs exist *and* - // (2) the version of the system DLL is problematic. - uint64_t systemDirVersion = 0, appDirVersion = 0; - if (GetMSVCP140VersionInfo(VCRuntimeDLLDir::System, systemDirVersion) && - GetMSVCP140VersionInfo(VCRuntimeDLLDir::Application, appDirVersion) && - systemDirVersion < appDirVersion) { - return; - } - - mozilla::DebugOnly<bool> setOk = mozilla::EnablePreferLoadFromSystem32(); - MOZ_ASSERT(setOk); -} +#if !defined(PROCESS_CREATION_MITIGATION_POLICY_CONTROL_FLOW_GUARD_ALWAYS_OFF) +# define PROCESS_CREATION_MITIGATION_POLICY_CONTROL_FLOW_GUARD_ALWAYS_OFF \ + (0x00000002ULL << 40) +#endif // !defined(PROCESS_CREATION_MITIGATION_POLICY_CONTROL_FLOW_GUARD_ALWAYS_OFF) /** * Any mitigation policies that should be set on the browser process should go @@ -193,11 +127,10 @@ static void EnablePreferLoadFromSystem32IfCompatible() { */ static void SetMitigationPolicies(mozilla::ProcThreadAttributes& aAttrs, const bool aIsSafeMode) { - // Note: Do *not* handle IMAGE_LOAD_PREFER_SYSTEM32_ALWAYS_ON here. For this - // mitigation we rely on EnablePreferLoadFromSystem32IfCompatible(). - // The launcher process or the browser process will choose whether we - // want to apply the mitigation or not, and child processes will - // automatically inherit that choice. + if (mozilla::IsWin10AnniversaryUpdateOrLater()) { + aAttrs.AddMitigationPolicy( + PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_PREFER_SYSTEM32_ALWAYS_ON); + } #if defined(_M_ARM64) // Disable CFG on older versions of ARM64 Windows to avoid a crash in COM. @@ -344,9 +277,6 @@ Maybe<int> LauncherMain(int& argc, wchar_t* argv[]) { return Nothing(); } - // Called from the launcher process *and* the browser process. - EnablePreferLoadFromSystem32IfCompatible(); - #if defined(MOZ_LAUNCHER_PROCESS) LauncherRegistryInfo regInfo; Maybe<bool> runAsLauncher = RunAsLauncherProcess(regInfo, argc, argv); @@ -370,6 +300,22 @@ Maybe<int> LauncherMain(int& argc, wchar_t* argv[]) { return Nothing(); } + // Make sure that the launcher process itself has image load policies set + if (IsWin10AnniversaryUpdateOrLater()) { + static const StaticDynamicallyLinkedFunctionPtr< + decltype(&SetProcessMitigationPolicy)> + pSetProcessMitigationPolicy(L"kernel32.dll", + "SetProcessMitigationPolicy"); + if (pSetProcessMitigationPolicy) { + PROCESS_MITIGATION_IMAGE_LOAD_POLICY imgLoadPol = {}; + imgLoadPol.PreferSystem32Images = 1; + + DebugOnly<BOOL> setOk = pSetProcessMitigationPolicy( + ProcessImageLoadPolicy, &imgLoadPol, sizeof(imgLoadPol)); + MOZ_ASSERT(setOk); + } + } + #if defined(MOZ_SANDBOX) // Ensure the relevant mitigations are enforced. mozilla::sandboxing::ApplyParentProcessMitigations(); diff --git a/browser/app/winlauncher/moz.build b/browser/app/winlauncher/moz.build @@ -24,7 +24,6 @@ OS_LIBS += [ "oleaut32", "ole32", "rpcrt4", - "shlwapi", "version", ] diff --git a/mozglue/misc/WindowsProcessMitigations.cpp b/mozglue/misc/WindowsProcessMitigations.cpp @@ -9,7 +9,6 @@ #include <processthreadsapi.h> #include "mozilla/DynamicallyLinkedFunctionPtr.h" -#include "mozilla/WindowsVersion.h" static_assert(sizeof(PROCESS_MITIGATION_DYNAMIC_CODE_POLICY) == 4); @@ -98,54 +97,4 @@ MFBT_API bool IsUserShadowStackEnabled() { return polInfo.EnableUserShadowStack; } -MFBT_API bool IsPreferLoadFromSystem32Available() { - return mozilla::IsWin10AnniversaryUpdateOrLater(); -} - -MFBT_API bool IsPreferLoadFromSystem32Enabled() { - auto pGetProcessMitigationPolicy = FetchGetProcessMitigationPolicyFunc(); - if (!pGetProcessMitigationPolicy) { - return false; - } - - PROCESS_MITIGATION_IMAGE_LOAD_POLICY imgLoadPol{}; - if (!pGetProcessMitigationPolicy(::GetCurrentProcess(), - ProcessImageLoadPolicy, &imgLoadPol, - sizeof(imgLoadPol))) { - return false; - } - - return imgLoadPol.PreferSystem32Images; -} - -MFBT_API bool EnablePreferLoadFromSystem32() { - auto pGetProcessMitigationPolicy = FetchGetProcessMitigationPolicyFunc(); - if (!pGetProcessMitigationPolicy) { - return false; - } - - static const mozilla::StaticDynamicallyLinkedFunctionPtr< - decltype(&::SetProcessMitigationPolicy)> - pSetProcessMitigationPolicy(L"kernel32.dll", - "SetProcessMitigationPolicy"); - if (!pSetProcessMitigationPolicy) { - return false; - } - - PROCESS_MITIGATION_IMAGE_LOAD_POLICY imgLoadPol{}; - if (!pGetProcessMitigationPolicy(::GetCurrentProcess(), - ProcessImageLoadPolicy, &imgLoadPol, - sizeof(imgLoadPol))) { - return false; - } - - if (imgLoadPol.PreferSystem32Images) { - return true; - } - - imgLoadPol.PreferSystem32Images = 1; - return pSetProcessMitigationPolicy(ProcessImageLoadPolicy, &imgLoadPol, - sizeof(imgLoadPol)); -} - } // namespace mozilla diff --git a/mozglue/misc/WindowsProcessMitigations.h b/mozglue/misc/WindowsProcessMitigations.h @@ -16,9 +16,6 @@ MFBT_API void SetWin32kLockedDownInPolicy(); MFBT_API bool IsDynamicCodeDisabled(); MFBT_API bool IsEafPlusEnabled(); MFBT_API bool IsUserShadowStackEnabled(); -MFBT_API bool IsPreferLoadFromSystem32Available(); -MFBT_API bool IsPreferLoadFromSystem32Enabled(); -MFBT_API bool EnablePreferLoadFromSystem32(); } // namespace mozilla diff --git a/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp b/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp @@ -471,36 +471,19 @@ Result<Ok, mozilla::ipc::LaunchError> SandboxBroker::LaunchApp( "Setting the reduced set of flags should always succeed"); } - sandbox::MitigationFlags delayedMitigations = - config->GetDelayedProcessMitigations(); - - // Only prefer loading from the system directory as a delayed mitigation, and - // always enable this delayed mitigation. This means that: - // - if the launcher or browser process chose to apply the mitigation, child - // processes will have it enabled at startup automatically anyway; - // - even if the launcher or browser process chose not to apply the - // mitigation, at least sandboxed child processes will run with the - // mitigation once the sandbox starts (by this time, they will already - // have loaded the Visual C++ runtime DLLs, so these are no longer a - // concern; also, although some sandboxed child processes can start new - // processes, they never start new *Firefox* processes). - // Refer to EnablePreferLoadFromSystem32IfCompatible for more details. - MOZ_ASSERT(!(config->GetProcessMitigations() & - sandbox::MITIGATION_IMAGE_LOAD_PREFER_SYS32)); - delayedMitigations |= sandbox::MITIGATION_IMAGE_LOAD_PREFER_SYS32; - // Bug 1936749: MpDetours.dll injection is incompatible with ACG. constexpr sandbox::MitigationFlags kDynamicCodeFlags = sandbox::MITIGATION_DYNAMIC_CODE_DISABLE | sandbox::MITIGATION_DYNAMIC_CODE_DISABLE_WITH_OPT_OUT; + sandbox::MitigationFlags delayedMitigations = + config->GetDelayedProcessMitigations(); if ((delayedMitigations & kDynamicCodeFlags) && ::GetModuleHandleW(L"MpDetours.dll")) { delayedMitigations &= ~kDynamicCodeFlags; + SANDBOX_SUCCEED_OR_CRASH( + config->SetDelayedProcessMitigations(delayedMitigations)); } - SANDBOX_SUCCEED_OR_CRASH( - config->SetDelayedProcessMitigations(delayedMitigations)); - EnsureAppLockerAccess(config); // If logging enabled, set up the policy. @@ -1125,7 +1108,8 @@ void SandboxBroker::SetSecurityLevelForContentProcess(int32_t aSandboxLevel, sandbox::MITIGATION_DEP | sandbox::MITIGATION_EXTENSION_POINT_DISABLE | sandbox::MITIGATION_KTM_COMPONENT | sandbox::MITIGATION_FSCTL_DISABLED | sandbox::MITIGATION_IMAGE_LOAD_NO_REMOTE | - sandbox::MITIGATION_IMAGE_LOAD_NO_LOW_LABEL; + sandbox::MITIGATION_IMAGE_LOAD_NO_LOW_LABEL | + sandbox::MITIGATION_IMAGE_LOAD_PREFER_SYS32; #if defined(_M_ARM64) // Disable CFG on older versions of ARM64 Windows to avoid a crash in COM. @@ -1446,7 +1430,8 @@ bool SandboxBroker::SetSecurityLevelForRDDProcess() { sandbox::MITIGATION_NONSYSTEM_FONT_DISABLE | sandbox::MITIGATION_KTM_COMPONENT | sandbox::MITIGATION_FSCTL_DISABLED | sandbox::MITIGATION_IMAGE_LOAD_NO_REMOTE | - sandbox::MITIGATION_IMAGE_LOAD_NO_LOW_LABEL; + sandbox::MITIGATION_IMAGE_LOAD_NO_LOW_LABEL | + sandbox::MITIGATION_IMAGE_LOAD_PREFER_SYS32; if (StaticPrefs::security_sandbox_rdd_shadow_stack_enabled()) { mitigations |= sandbox::MITIGATION_CET_COMPAT_MODE; @@ -1529,7 +1514,8 @@ bool SandboxBroker::SetSecurityLevelForSocketProcess() { sandbox::MITIGATION_NONSYSTEM_FONT_DISABLE | sandbox::MITIGATION_KTM_COMPONENT | sandbox::MITIGATION_FSCTL_DISABLED | sandbox::MITIGATION_IMAGE_LOAD_NO_REMOTE | - sandbox::MITIGATION_IMAGE_LOAD_NO_LOW_LABEL; + sandbox::MITIGATION_IMAGE_LOAD_NO_LOW_LABEL | + sandbox::MITIGATION_IMAGE_LOAD_PREFER_SYS32; if (StaticPrefs::security_sandbox_socket_shadow_stack_enabled()) { mitigations |= sandbox::MITIGATION_CET_COMPAT_MODE; @@ -1601,6 +1587,7 @@ struct UtilitySandboxProps { sandbox::MITIGATION_KTM_COMPONENT | sandbox::MITIGATION_FSCTL_DISABLED | sandbox::MITIGATION_IMAGE_LOAD_NO_REMOTE | sandbox::MITIGATION_IMAGE_LOAD_NO_LOW_LABEL | + sandbox::MITIGATION_IMAGE_LOAD_PREFER_SYS32 | sandbox::MITIGATION_CET_COMPAT_MODE; sandbox::MitigationFlags mExcludedInitialMitigations = 0;