Bug 1950112: Use win32k lockdown and ACG for GMP process for non-widevine CDMs. r=yjuglaret,win-reviewers
Differential Revision: https://phabricator.services.mozilla.com/D239356
This commit is contained in:
@@ -1526,11 +1526,6 @@ Result<Ok, LaunchError> WindowsProcessLauncher::DoSetup() {
|
||||
FilePath exePath;
|
||||
BinPathType pathType = GetPathToBinary(exePath, mProcessType);
|
||||
|
||||
# if defined(MOZ_SANDBOX) || defined(_ARM64_)
|
||||
const bool isGMP = mProcessType == GeckoProcessType_GMPlugin;
|
||||
const bool isWidevine = isGMP && Contains(mChildArgs, "gmp-widevinecdm");
|
||||
# endif // defined(MOZ_SANDBOX) || defined(_ARM64_)
|
||||
|
||||
mCmdLine.emplace(exePath.ToWStringHack());
|
||||
|
||||
if (pathType == BinPathType::Self) {
|
||||
@@ -1574,14 +1569,15 @@ Result<Ok, LaunchError> WindowsProcessLauncher::DoSetup() {
|
||||
break;
|
||||
case GeckoProcessType_GMPlugin:
|
||||
if (!PR_GetEnv("MOZ_DISABLE_GMP_SANDBOX")) {
|
||||
// The Widevine CDM on Windows can only load at USER_RESTRICTED,
|
||||
// not at USER_LOCKDOWN. So look in the command line arguments
|
||||
// to see if we're loading the path to the Widevine CDM, and if
|
||||
// so use sandbox level USER_RESTRICTED instead of USER_LOCKDOWN.
|
||||
auto level =
|
||||
isWidevine ? SandboxBroker::Restricted : SandboxBroker::LockDown;
|
||||
if (NS_WARN_IF(
|
||||
!mResults.mSandboxBroker->SetSecurityLevelForGMPlugin(level))) {
|
||||
auto gmpSandboxKind = GMPSandboxKind::Default;
|
||||
if (Contains(mChildArgs, "gmp-widevinecdm")) {
|
||||
gmpSandboxKind = GMPSandboxKind::Widevine;
|
||||
} else if (Contains(mChildArgs, "gmp-clearkey")) {
|
||||
gmpSandboxKind = GMPSandboxKind::Clearkey;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!mResults.mSandboxBroker->SetSecurityLevelForGMPlugin(
|
||||
gmpSandboxKind))) {
|
||||
return Err(LaunchError("SetSecurityLevelForGMPlugin"));
|
||||
}
|
||||
mUseSandbox = true;
|
||||
|
||||
@@ -16104,14 +16104,19 @@
|
||||
# true means win32k system calls are not permitted.
|
||||
- name: security.sandbox.content.win32k-disable
|
||||
type: RelaxedAtomicBool
|
||||
value: true
|
||||
value: @IS_NIGHTLY_BUILD@
|
||||
mirror: always
|
||||
|
||||
# Note: win32k is currently _not_ disabled for GMP due to intermittent test
|
||||
# failures, where the GMP process fails very early. See bug 1449348.
|
||||
# Whether win32k is disabled for compatible plugins.
|
||||
- name: security.sandbox.gmp.win32k-disable
|
||||
type: RelaxedAtomicBool
|
||||
value: false
|
||||
value: @IS_NIGHTLY_BUILD@
|
||||
mirror: always
|
||||
|
||||
# Whether ACG is enabled (dynamic code blocked) for compatible plugins.
|
||||
- name: security.sandbox.gmp.acg.enabled
|
||||
type: RelaxedAtomicBool
|
||||
value: true
|
||||
mirror: always
|
||||
|
||||
# Whether win32k is disabled for socket processes.
|
||||
|
||||
@@ -1750,8 +1750,8 @@ bool SandboxBroker::SetSecurityLevelForUtilityProcess(
|
||||
}
|
||||
}
|
||||
|
||||
bool SandboxBroker::SetSecurityLevelForGMPlugin(SandboxLevel aLevel,
|
||||
bool aIsRemoteLaunch) {
|
||||
bool SandboxBroker::SetSecurityLevelForGMPlugin(
|
||||
GMPSandboxKind aGMPSandboxKind) {
|
||||
if (!mPolicy) {
|
||||
return false;
|
||||
}
|
||||
@@ -1761,8 +1761,10 @@ bool SandboxBroker::SetSecurityLevelForGMPlugin(SandboxLevel aLevel,
|
||||
SANDBOX_ENSURE_SUCCESS(
|
||||
result,
|
||||
"SetJobLevel should never fail with these arguments, what happened?");
|
||||
auto level = (aLevel == Restricted) ? sandbox::USER_RESTRICTED
|
||||
: sandbox::USER_LOCKDOWN;
|
||||
|
||||
// The Widevine CDM on Windows can only load at USER_RESTRICTED
|
||||
auto level = (aGMPSandboxKind == Widevine) ? sandbox::USER_RESTRICTED
|
||||
: sandbox::USER_LOCKDOWN;
|
||||
result = mPolicy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS, level);
|
||||
SANDBOX_ENSURE_SUCCESS(
|
||||
result,
|
||||
@@ -1803,13 +1805,28 @@ bool SandboxBroker::SetSecurityLevelForGMPlugin(SandboxLevel aLevel,
|
||||
result = mPolicy->SetProcessMitigations(mitigations);
|
||||
SANDBOX_ENSURE_SUCCESS(result, "Invalid flags for SetProcessMitigations.");
|
||||
|
||||
if (StaticPrefs::security_sandbox_gmp_win32k_disable()) {
|
||||
// win32k is currently not disabled for clearkey due to WMF decoding or
|
||||
// widevine due to intermittent test failures, where the GMP process fails
|
||||
// very early. See bug 1449348.
|
||||
if (StaticPrefs::security_sandbox_gmp_win32k_disable() &&
|
||||
aGMPSandboxKind != Widevine && aGMPSandboxKind != Clearkey) {
|
||||
result = AddWin32kLockdownPolicy(mPolicy, true);
|
||||
SANDBOX_ENSURE_SUCCESS(result, "Failed to add the win32k lockdown policy");
|
||||
}
|
||||
|
||||
mitigations = sandbox::MITIGATION_STRICT_HANDLE_CHECKS |
|
||||
sandbox::MITIGATION_DLL_SEARCH_ORDER;
|
||||
if (StaticPrefs::security_sandbox_gmp_acg_enabled()) {
|
||||
auto acgMitigation = sandbox::MITIGATION_DYNAMIC_CODE_DISABLE;
|
||||
if (aGMPSandboxKind == Widevine) {
|
||||
// We can't guarantee that widevine won't use dynamic code.
|
||||
acgMitigation = 0;
|
||||
} else if (aGMPSandboxKind == Clearkey) {
|
||||
// Clearkey uses system decoding libraries.
|
||||
acgMitigation = DynamicCodeFlagForSystemMediaLibraries();
|
||||
}
|
||||
mitigations |= acgMitigation;
|
||||
}
|
||||
|
||||
result = mPolicy->SetDelayedProcessMitigations(mitigations);
|
||||
SANDBOX_ENSURE_SUCCESS(result,
|
||||
|
||||
@@ -26,6 +26,8 @@ class TargetPolicy;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
enum GMPSandboxKind { Default, Widevine, Clearkey };
|
||||
|
||||
class SandboxBroker {
|
||||
public:
|
||||
SandboxBroker();
|
||||
@@ -56,9 +58,7 @@ class SandboxBroker {
|
||||
bool SetSecurityLevelForRDDProcess();
|
||||
bool SetSecurityLevelForSocketProcess();
|
||||
|
||||
enum SandboxLevel { LockDown, Restricted };
|
||||
bool SetSecurityLevelForGMPlugin(SandboxLevel aLevel,
|
||||
bool aIsRemoteLaunch = false);
|
||||
bool SetSecurityLevelForGMPlugin(GMPSandboxKind aGMPSandboxKind);
|
||||
bool SetSecurityLevelForUtilityProcess(mozilla::ipc::SandboxingKind aSandbox);
|
||||
|
||||
// File system permissions
|
||||
|
||||
@@ -6272,6 +6272,13 @@ bool XRE_IsE10sParentProcess() {
|
||||
#undef GECKO_PROCESS_TYPE
|
||||
|
||||
bool XRE_UseNativeEventProcessing() {
|
||||
#if defined(XP_WIN)
|
||||
// If win32k is locked down we can't use native event processing.
|
||||
if (IsWin32kLockedDown()) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (XRE_GetProcessType()) {
|
||||
#if defined(XP_MACOSX) || defined(XP_WIN)
|
||||
case GeckoProcessType_RDD:
|
||||
|
||||
@@ -619,17 +619,23 @@ nsresult nsAppShell::Init() {
|
||||
if (nsresult rv = this->InitEventWindow(); NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
} else if (XRE_IsContentProcess() && !IsWin32kLockedDown()) {
|
||||
// We're not generally processing native events, but still using GDI and we
|
||||
// still have some internal windows, e.g. from calling CoInitializeEx.
|
||||
// So we use a class that will do a single event pump where previously we
|
||||
// might have processed multiple events to make sure any occasional messages
|
||||
// to these windows are processed. This also allows any internal Windows
|
||||
// messages to be processed to ensure the GDI data remains fresh.
|
||||
nsCOMPtr<nsIThreadInternal> threadInt =
|
||||
do_QueryInterface(NS_GetCurrentThread());
|
||||
if (threadInt) {
|
||||
threadInt->SetObserver(new SingleNativeEventPump());
|
||||
} else {
|
||||
// Load winmm.dll because it is still needed by our event loop and might not
|
||||
// get loaded before we lower the sandbox.
|
||||
::LoadLibraryW(L"winmm.dll");
|
||||
|
||||
if (XRE_IsContentProcess() && !IsWin32kLockedDown()) {
|
||||
// We're not generally processing native events, but still using GDI and
|
||||
// we still have some internal windows, e.g. from calling CoInitializeEx.
|
||||
// So we use a class that will do a single event pump where previously we
|
||||
// might have processed multiple events to make sure any occasional
|
||||
// messages to these windows are processed. This also allows any internal
|
||||
// Windows messages to be processed to ensure the GDI data remains fresh.
|
||||
nsCOMPtr<nsIThreadInternal> threadInt =
|
||||
do_QueryInterface(NS_GetCurrentThread());
|
||||
if (threadInt) {
|
||||
threadInt->SetObserver(new SingleNativeEventPump());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user