Commit 60930b78 authored by Penny MacNeil's avatar Penny MacNeil Committed by Commit Bot

[Windows Sandbox] Add restrict_indirect_branch_prediction support.

-Add sandbox support for new process mitigation RESTRICT_INDIRECT_BRANCH_PREDICTION_ALWAYS_ON.
-Supported on >= Win10 RS3/1709/16299, with Jan 2018 security updates, and based on
 underlying device hardware/OEM support.  E.g. Intel STIBP
-This CL also (finally) includes an update to the ConvertProcessMitigationsToPolicy() API.
 MS ran out of bits in the DWORD64 for process mitigation flags, so related APIs can now
 take in a two-element array of DWORD64s.  The second element is for "*POLICY2*" mitigation
 flags (defined in WinBase.h).

**Any downstream users of this sandbox API will need to update their code to always
pass in a two-element array now.  |size| returned will be adjusted appropriately to be
directly passed into UpdateProcThreadAttribute(), for PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY.

Bug=808526
Test=sbox_integration_tests.exe

Change-Id: I9c5a0350d9b77f56a4a18be49d68fff039b11e54
Reviewed-on: https://chromium-review.googlesource.com/922797
Commit-Queue: Penny MacNeil <pennymac@chromium.org>
Reviewed-by: default avatarWill Harris <wfh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#540380}
parent 61967f2c
...@@ -323,7 +323,7 @@ ResultCode BrokerServicesBase::SpawnTarget(const wchar_t* exe_path, ...@@ -323,7 +323,7 @@ ResultCode BrokerServicesBase::SpawnTarget(const wchar_t* exe_path,
// |startup_info| because |UpdateProcThreadAttribute| requires that // |startup_info| because |UpdateProcThreadAttribute| requires that
// its |lpValue| parameter persist until |DeleteProcThreadAttributeList| is // its |lpValue| parameter persist until |DeleteProcThreadAttributeList| is
// called; StartupInformation's destructor makes such a call. // called; StartupInformation's destructor makes such a call.
DWORD64 mitigations; DWORD64 mitigations[2];
std::vector<HANDLE> inherited_handle_list; std::vector<HANDLE> inherited_handle_list;
DWORD child_process_creation = PROCESS_CREATION_CHILD_PROCESS_RESTRICTED; DWORD child_process_creation = PROCESS_CREATION_CHILD_PROCESS_RESTRICTED;
...@@ -339,8 +339,8 @@ ResultCode BrokerServicesBase::SpawnTarget(const wchar_t* exe_path, ...@@ -339,8 +339,8 @@ ResultCode BrokerServicesBase::SpawnTarget(const wchar_t* exe_path,
size_t mitigations_size; size_t mitigations_size;
ConvertProcessMitigationsToPolicy(policy_base->GetProcessMitigations(), ConvertProcessMitigationsToPolicy(policy_base->GetProcessMitigations(),
&mitigations, &mitigations_size); &mitigations[0], &mitigations_size);
if (mitigations) if (mitigations[0] || mitigations[1])
++attribute_count; ++attribute_count;
bool restrict_child_process_creation = false; bool restrict_child_process_creation = false;
...@@ -385,9 +385,9 @@ ResultCode BrokerServicesBase::SpawnTarget(const wchar_t* exe_path, ...@@ -385,9 +385,9 @@ ResultCode BrokerServicesBase::SpawnTarget(const wchar_t* exe_path,
if (!startup_info.InitializeProcThreadAttributeList(attribute_count)) if (!startup_info.InitializeProcThreadAttributeList(attribute_count))
return SBOX_ERROR_PROC_THREAD_ATTRIBUTES; return SBOX_ERROR_PROC_THREAD_ATTRIBUTES;
if (mitigations) { if (mitigations[0] || mitigations[1]) {
if (!startup_info.UpdateProcThreadAttribute( if (!startup_info.UpdateProcThreadAttribute(
PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY, &mitigations, PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY, &mitigations[0],
mitigations_size)) { mitigations_size)) {
return SBOX_ERROR_PROC_THREAD_ATTRIBUTES; return SBOX_ERROR_PROC_THREAD_ATTRIBUTES;
} }
......
This diff is collapsed.
...@@ -26,9 +26,10 @@ bool ApplyMitigationsToCurrentThread(MitigationFlags flags); ...@@ -26,9 +26,10 @@ bool ApplyMitigationsToCurrentThread(MitigationFlags flags);
MitigationFlags FilterPostStartupProcessMitigations(MitigationFlags flags); MitigationFlags FilterPostStartupProcessMitigations(MitigationFlags flags);
// Converts sandbox flags to the PROC_THREAD_ATTRIBUTE_SECURITY_CAPABILITIES // Converts sandbox flags to the PROC_THREAD_ATTRIBUTE_SECURITY_CAPABILITIES
// policy flags used by UpdateProcThreadAttribute(). The size field varies // policy flags used by UpdateProcThreadAttribute().
// between a 32-bit and a 64-bit type based on the exact build and version of // - |policy_flags| must be a two-element DWORD64 array.
// Windows, so the returned size must be passed to UpdateProcThreadAttribute(). // - |size| is a size_t so that it can be passed directly into
// UpdateProcThreadAttribute().
void ConvertProcessMitigationsToPolicy(MitigationFlags flags, void ConvertProcessMitigationsToPolicy(MitigationFlags flags,
DWORD64* policy_flags, DWORD64* policy_flags,
size_t* size); size_t* size);
......
...@@ -330,6 +330,16 @@ SBOX_TESTS_COMMAND int CheckPolicy(int argc, wchar_t** argv) { ...@@ -330,6 +330,16 @@ SBOX_TESTS_COMMAND int CheckPolicy(int argc, wchar_t** argv) {
break; break;
} }
//--------------------------------------------------
// MITIGATION_RESTRICT_INDIRECT_BRANCH_PREDICTION
//--------------------------------------------------
case (TESTPOLICY_RESTRICTINDIRECTBRANCHPREDICTION): {
// TODO(pennymac): No Policy defines available yet!
// Can't use GetProcessMitigationPolicy() API to check if enabled at this
// time. If the creation of THIS process succeeded, then the call to
// UpdateProcThreadAttribute() with this mitigation succeeded.
break;
}
default: default:
return SBOX_TEST_INVALID_PARAMETER; return SBOX_TEST_INVALID_PARAMETER;
} }
...@@ -896,4 +906,38 @@ TEST(ProcessMitigationsTest, CheckChildProcessAbnormalExit) { ...@@ -896,4 +906,38 @@ TEST(ProcessMitigationsTest, CheckChildProcessAbnormalExit) {
EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(test_command.c_str())); EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(test_command.c_str()));
} }
//------------------------------------------------------------------------------
// Restrict indirect branch prediction
// (MITIGATION_RESTRICT_INDIRECT_BRANCH_PREDICTION)
// >= Win10 RS3
//------------------------------------------------------------------------------
// This test validates that setting the
// MITIGATION_RESTRICT_INDIRECT_BRANCH_PREDICTION mitigation enables the setting
// on a process.
TEST(ProcessMitigationsTest,
CheckWin10RestrictIndirectBranchPredictionPolicySuccess) {
if (base::win::GetVersion() < base::win::VERSION_WIN10_RS3)
return;
base::string16 test_command = L"CheckPolicy ";
test_command += std::to_wstring(TESTPOLICY_RESTRICTINDIRECTBRANCHPREDICTION);
//---------------------------------
// 1) Test setting pre-startup.
//---------------------------------
TestRunner runner;
sandbox::TargetPolicy* policy = runner.GetPolicy();
EXPECT_EQ(policy->SetProcessMitigations(
MITIGATION_RESTRICT_INDIRECT_BRANCH_PREDICTION),
SBOX_ALL_OK);
EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(test_command.c_str()));
//---------------------------------
// 2) Test setting post-startup.
// ** Post-startup not supported. Must be enabled on creation.
//---------------------------------
}
} // namespace sandbox } // namespace sandbox
...@@ -255,6 +255,12 @@ const MitigationFlags MITIGATION_IMAGE_LOAD_NO_LOW_LABEL = 0x00080000; ...@@ -255,6 +255,12 @@ const MitigationFlags MITIGATION_IMAGE_LOAD_NO_LOW_LABEL = 0x00080000;
// PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_PREFER_SYSTEM32_ALWAYS_ON. // PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_PREFER_SYSTEM32_ALWAYS_ON.
const MitigationFlags MITIGATION_IMAGE_LOAD_PREFER_SYS32 = 0x00100000; const MitigationFlags MITIGATION_IMAGE_LOAD_PREFER_SYS32 = 0x00100000;
// Prevents hyperthreads from interfering with indirect branch predictions.
// (SPECTRE Variant 2 mitigation.) Corresponds to
// PROCESS_CREATION_MITIGATION_POLICY2_RESTRICT_INDIRECT_BRANCH_PREDICTION_ALWAYS_ON.
const MitigationFlags MITIGATION_RESTRICT_INDIRECT_BRANCH_PREDICTION =
0x00200000;
} // namespace sandbox } // namespace sandbox
#endif // SANDBOX_SRC_SECURITY_LEVEL_H_ #endif // SANDBOX_SRC_SECURITY_LEVEL_H_
...@@ -25,7 +25,8 @@ enum TestPolicy { ...@@ -25,7 +25,8 @@ enum TestPolicy {
TESTPOLICY_LOADNOREMOTE, TESTPOLICY_LOADNOREMOTE,
TESTPOLICY_LOADNOLOW, TESTPOLICY_LOADNOLOW,
TESTPOLICY_DYNAMICCODEOPTOUT, TESTPOLICY_DYNAMICCODEOPTOUT,
TESTPOLICY_LOADPREFERSYS32 TESTPOLICY_LOADPREFERSYS32,
TESTPOLICY_RESTRICTINDIRECTBRANCHPREDICTION
}; };
// Timeout for ::WaitForSingleObject synchronization. // Timeout for ::WaitForSingleObject synchronization.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment