summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/nacl/loader/nacl_main_platform_delegate_win.cc3
-rw-r--r--content/renderer/renderer_main_platform_delegate_win.cc3
-rw-r--r--sandbox/win/BUILD.gn1
-rw-r--r--sandbox/win/sandbox_win.gypi1
-rw-r--r--sandbox/win/src/lpc_policy_test.cc156
-rw-r--r--sandbox/win/src/sandbox_policy.h2
-rw-r--r--sandbox/win/src/sandbox_types.h15
-rw-r--r--sandbox/win/src/target_services.cc40
-rw-r--r--tools/metrics/histograms/histograms.xml1
9 files changed, 208 insertions, 14 deletions
diff --git a/components/nacl/loader/nacl_main_platform_delegate_win.cc b/components/nacl/loader/nacl_main_platform_delegate_win.cc
index e4d0ad5..c0caa5e 100644
--- a/components/nacl/loader/nacl_main_platform_delegate_win.cc
+++ b/components/nacl/loader/nacl_main_platform_delegate_win.cc
@@ -17,9 +17,6 @@ void NaClMainPlatformDelegate::EnableSandbox(
// Cause advapi32 to load before the sandbox is turned on.
unsigned int dummy_rand;
rand_s(&dummy_rand);
- // Warm up language subsystems before the sandbox is turned on.
- ::GetUserDefaultLangID();
- ::GetUserDefaultLCID();
// Turn the sandbox on.
target_services->LowerToken();
diff --git a/content/renderer/renderer_main_platform_delegate_win.cc b/content/renderer/renderer_main_platform_delegate_win.cc
index aae8ea1..675961d 100644
--- a/content/renderer/renderer_main_platform_delegate_win.cc
+++ b/content/renderer/renderer_main_platform_delegate_win.cc
@@ -87,9 +87,6 @@ bool RendererMainPlatformDelegate::EnableSandbox() {
// Cause advapi32 to load before the sandbox is turned on.
unsigned int dummy_rand;
rand_s(&dummy_rand);
- // Warm up language subsystems before the sandbox is turned on.
- ::GetUserDefaultLangID();
- ::GetUserDefaultLCID();
target_services->LowerToken();
return true;
diff --git a/sandbox/win/BUILD.gn b/sandbox/win/BUILD.gn
index 129f065..2250869 100644
--- a/sandbox/win/BUILD.gn
+++ b/sandbox/win/BUILD.gn
@@ -196,6 +196,7 @@ test("sbox_integration_tests") {
"src/handle_policy_test.cc",
"src/integrity_level_test.cc",
"src/ipc_ping_test.cc",
+ "src/lpc_policy_test.cc",
"src/named_pipe_policy_test.cc",
"src/policy_target_test.cc",
"src/process_mitigations_test.cc",
diff --git a/sandbox/win/sandbox_win.gypi b/sandbox/win/sandbox_win.gypi
index 08d512a..ae8b51c 100644
--- a/sandbox/win/sandbox_win.gypi
+++ b/sandbox/win/sandbox_win.gypi
@@ -219,6 +219,7 @@
'src/handle_closer_test.cc',
'src/integrity_level_test.cc',
'src/ipc_ping_test.cc',
+ 'src/lpc_policy_test.cc',
'src/named_pipe_policy_test.cc',
'src/policy_target_test.cc',
'src/process_mitigations_test.cc',
diff --git a/sandbox/win/src/lpc_policy_test.cc b/sandbox/win/src/lpc_policy_test.cc
new file mode 100644
index 0000000..ac7b39f
--- /dev/null
+++ b/sandbox/win/src/lpc_policy_test.cc
@@ -0,0 +1,156 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// These tests have been added to specifically tests issues arising from (A)LPC
+// lock down.
+
+#include <algorithm>
+#include <cctype>
+
+#include <windows.h>
+#include <winioctl.h>
+
+#include "base/win/windows_version.h"
+#include "sandbox/win/src/sandbox.h"
+#include "sandbox/win/src/sandbox_factory.h"
+#include "sandbox/win/src/sandbox_policy.h"
+#include "sandbox/win/tests/common/controller.h"
+#include "sandbox/win/tests/common/test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace sandbox {
+
+// Converts LCID to std::wstring for passing to sbox tests.
+std::wstring LcidToWString(LCID lcid) {
+ wchar_t buff[10] = {0};
+ int res = swprintf_s(buff, sizeof(buff) / sizeof(buff[0]), L"%08x", lcid);
+ if (-1 != res) {
+ return std::wstring(buff);
+ }
+ return std::wstring();
+}
+
+// Converts LANGID to std::wstring for passing to sbox tests.
+std::wstring LangidToWString(LANGID langid) {
+ wchar_t buff[10] = {0};
+ int res = swprintf_s(buff, sizeof(buff) / sizeof(buff[0]), L"%04x", langid);
+ if (-1 != res) {
+ return std::wstring(buff);
+ }
+ return std::wstring();
+}
+
+SBOX_TESTS_COMMAND int Lpc_GetUserDefaultLangID(int argc, wchar_t** argv) {
+ if (argc != 1)
+ return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
+ std::wstring expected_langid_string(argv[0]);
+
+ // This will cause an exception if not warmed up suitably.
+ LANGID langid = ::GetUserDefaultLangID();
+
+ std::wstring langid_string = LangidToWString(langid);
+ if (0 == wcsncmp(langid_string.c_str(), expected_langid_string.c_str(), 4)) {
+ return SBOX_TEST_SUCCEEDED;
+ }
+ return SBOX_TEST_FAILED;
+}
+
+TEST(LpcPolicyTest, GetUserDefaultLangID) {
+ LANGID langid = ::GetUserDefaultLangID();
+ std::wstring cmd = L"Lpc_GetUserDefaultLangID " + LangidToWString(langid);
+ TestRunner runner;
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(cmd.c_str()));
+}
+
+SBOX_TESTS_COMMAND int Lpc_GetUserDefaultLCID(int argc, wchar_t** argv) {
+ if (argc != 1)
+ return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
+ std::wstring expected_lcid_string(argv[0]);
+
+ // This will cause an exception if not warmed up suitably.
+ LCID lcid = ::GetUserDefaultLCID();
+
+ std::wstring lcid_string = LcidToWString(lcid);
+ if (0 == wcsncmp(lcid_string.c_str(), expected_lcid_string.c_str(), 8)) {
+ return SBOX_TEST_SUCCEEDED;
+ }
+ return SBOX_TEST_FAILED;
+}
+
+TEST(LpcPolicyTest, GetUserDefaultLCID) {
+ LCID lcid = ::GetUserDefaultLCID();
+ std::wstring cmd = L"Lpc_GetUserDefaultLCID " + LcidToWString(lcid);
+ TestRunner runner;
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(cmd.c_str()));
+}
+
+// GetUserDefaultLocaleName is not available on WIN XP. So we'll
+// load it on-the-fly.
+const wchar_t kKernel32DllName[] = L"kernel32.dll";
+typedef int(WINAPI* GetUserDefaultLocaleNameFunction)(LPWSTR lpLocaleName,
+ int cchLocaleName);
+
+SBOX_TESTS_COMMAND int Lpc_GetUserDefaultLocaleName(int argc, wchar_t** argv) {
+ if (argc != 1)
+ return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
+ std::wstring expected_locale_name(argv[0]);
+ static GetUserDefaultLocaleNameFunction GetUserDefaultLocaleName_func = NULL;
+ if (!GetUserDefaultLocaleName_func) {
+ // GetUserDefaultLocaleName is not available on WIN XP. So we'll
+ // load it on-the-fly.
+ HMODULE kernel32_dll = ::GetModuleHandle(kKernel32DllName);
+ if (!kernel32_dll) {
+ return SBOX_TEST_FAILED;
+ }
+ GetUserDefaultLocaleName_func =
+ reinterpret_cast<GetUserDefaultLocaleNameFunction>(
+ GetProcAddress(kernel32_dll, "GetUserDefaultLocaleName"));
+ if (!GetUserDefaultLocaleName_func) {
+ return SBOX_TEST_FAILED;
+ }
+ }
+ wchar_t locale_name[LOCALE_NAME_MAX_LENGTH] = {0};
+ // This will cause an exception if not warmed up suitably.
+ int ret = GetUserDefaultLocaleName_func(
+ locale_name, LOCALE_NAME_MAX_LENGTH * sizeof(wchar_t));
+ if (!ret) {
+ return SBOX_TEST_FAILED;
+ }
+ if (!wcsnlen(locale_name, LOCALE_NAME_MAX_LENGTH)) {
+ return SBOX_TEST_FAILED;
+ }
+ if (0 == wcsncmp(locale_name, expected_locale_name.c_str(),
+ LOCALE_NAME_MAX_LENGTH)) {
+ return SBOX_TEST_SUCCEEDED;
+ }
+ return SBOX_TEST_FAILED;
+}
+
+TEST(LpcPolicyTest, GetUserDefaultLocaleName) {
+ // GetUserDefaultLocaleName is not available before Vista.
+ if (base::win::GetVersion() < base::win::VERSION_VISTA) {
+ return;
+ }
+ static GetUserDefaultLocaleNameFunction GetUserDefaultLocaleName_func = NULL;
+ if (!GetUserDefaultLocaleName_func) {
+ // GetUserDefaultLocaleName is not available on WIN XP. So we'll
+ // load it on-the-fly.
+ HMODULE kernel32_dll = ::GetModuleHandle(kKernel32DllName);
+ EXPECT_NE(NULL, int(kernel32_dll));
+ GetUserDefaultLocaleName_func =
+ reinterpret_cast<GetUserDefaultLocaleNameFunction>(
+ GetProcAddress(kernel32_dll, "GetUserDefaultLocaleName"));
+ EXPECT_NE(NULL, int(GetUserDefaultLocaleName_func));
+ }
+ wchar_t locale_name[LOCALE_NAME_MAX_LENGTH] = {0};
+ EXPECT_NE(0, GetUserDefaultLocaleName_func(
+ locale_name, LOCALE_NAME_MAX_LENGTH * sizeof(wchar_t)));
+ EXPECT_NE(0U, wcsnlen(locale_name, LOCALE_NAME_MAX_LENGTH));
+ std::wstring cmd =
+ L"Lpc_GetUserDefaultLocaleName " + std::wstring(locale_name);
+ TestRunner runner;
+ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(cmd.c_str()));
+}
+
+} // namespace sandbox
diff --git a/sandbox/win/src/sandbox_policy.h b/sandbox/win/src/sandbox_policy.h
index c1af857..0c3e847 100644
--- a/sandbox/win/src/sandbox_policy.h
+++ b/sandbox/win/src/sandbox_policy.h
@@ -80,7 +80,7 @@ class TargetPolicy {
// not compatible with AppContainer, see SetAppContainer.
// lockdown: the security level for the token that comes into force after the
// process calls TargetServices::LowerToken() or the process calls
- // ReverToSelf(). See the explanation of each level in the TokenLevel
+ // RevertToSelf(). See the explanation of each level in the TokenLevel
// definition.
// Return value: SBOX_ALL_OK if the setting succeeds and false otherwise.
// Returns false if the lockdown value is more permissive than the initial
diff --git a/sandbox/win/src/sandbox_types.h b/sandbox/win/src/sandbox_types.h
index 3e531be..b749b9c 100644
--- a/sandbox/win/src/sandbox_types.h
+++ b/sandbox/win/src/sandbox_types.h
@@ -54,13 +54,14 @@ enum ResultCode {
// If the sandbox cannot create a secure environment for the target, the
// target will be forcibly terminated. These are the process exit codes.
enum TerminationCodes {
- SBOX_FATAL_INTEGRITY = 7006, // Could not set the integrity level.
- SBOX_FATAL_DROPTOKEN = 7007, // Could not lower the token.
- SBOX_FATAL_FLUSHANDLES = 7008, // Failed to flush registry handles.
- SBOX_FATAL_CACHEDISABLE = 7009, // Failed to forbid HCKU caching.
- SBOX_FATAL_CLOSEHANDLES = 7010, // Failed to close pending handles.
- SBOX_FATAL_MITIGATION = 7011, // Could not set the mitigation policy.
- SBOX_FATAL_MEMORY_EXCEEDED = 7012, // Exceeded the job memory limit.
+ SBOX_FATAL_INTEGRITY = 7006, // Could not set the integrity level.
+ SBOX_FATAL_DROPTOKEN = 7007, // Could not lower the token.
+ SBOX_FATAL_FLUSHANDLES = 7008, // Failed to flush registry handles.
+ SBOX_FATAL_CACHEDISABLE = 7009, // Failed to forbid HCKU caching.
+ SBOX_FATAL_CLOSEHANDLES = 7010, // Failed to close pending handles.
+ SBOX_FATAL_MITIGATION = 7011, // Could not set the mitigation policy.
+ SBOX_FATAL_MEMORY_EXCEEDED = 7012, // Exceeded the job memory limit.
+ SBOX_FATAL_WARMUP = 7013, // Failed to warmup.
SBOX_FATAL_LAST
};
diff --git a/sandbox/win/src/target_services.cc b/sandbox/win/src/target_services.cc
index 116f0c9..e10f7ca 100644
--- a/sandbox/win/src/target_services.cc
+++ b/sandbox/win/src/target_services.cc
@@ -59,6 +59,44 @@ bool CloseOpenHandles(bool* is_csrss_connected) {
return true;
}
+// GetUserDefaultLocaleName is not available on WIN XP. So we'll
+// load it on-the-fly.
+const wchar_t kKernel32DllName[] = L"kernel32.dll";
+typedef decltype(GetUserDefaultLocaleName)* GetUserDefaultLocaleNameFunction;
+
+// Warm up language subsystems before the sandbox is turned on.
+// Tested on Win8.1 x64:
+// This needs to happen after RevertToSelf() is called, because (at least) in
+// the case of GetUserDefaultLCID() it checks the TEB to see if the process is
+// impersonating (TEB!IsImpersonating). If it is, the cached locale information
+// is not used, nor is it set. Therefore, calls after RevertToSelf() will not
+// have warmed-up values to use.
+bool WarmupWindowsLocales() {
+ // NOTE(liamjm): When last checked (Win 8.1 x64) it wasn't necessary to
+ // warmup all of these functions, but let's not assume that.
+ ::GetUserDefaultLangID();
+ ::GetUserDefaultLCID();
+ if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
+ static GetUserDefaultLocaleNameFunction GetUserDefaultLocaleName_func =
+ NULL;
+ if (!GetUserDefaultLocaleName_func) {
+ HMODULE kernel32_dll = ::GetModuleHandle(kKernel32DllName);
+ if (!kernel32_dll) {
+ return false;
+ }
+ GetUserDefaultLocaleName_func =
+ reinterpret_cast<GetUserDefaultLocaleNameFunction>(
+ GetProcAddress(kernel32_dll, "GetUserDefaultLocaleName"));
+ if (!GetUserDefaultLocaleName_func) {
+ return false;
+ }
+ }
+ wchar_t localeName[LOCALE_NAME_MAX_LENGTH] = {0};
+ return (0 != GetUserDefaultLocaleName_func(
+ localeName, LOCALE_NAME_MAX_LENGTH * sizeof(wchar_t)));
+ }
+ return true;
+}
// Used as storage for g_target_services, because other allocation facilities
// are not available early. We can't use a regular function static because on
@@ -97,6 +135,8 @@ void TargetServicesBase::LowerToken() {
::TerminateProcess(::GetCurrentProcess(), SBOX_FATAL_FLUSHANDLES);
if (ERROR_SUCCESS != ::RegDisablePredefinedCache())
::TerminateProcess(::GetCurrentProcess(), SBOX_FATAL_CACHEDISABLE);
+ if (!WarmupWindowsLocales())
+ ::TerminateProcess(::GetCurrentProcess(), SBOX_FATAL_WARMUP);
bool is_csrss_connected = true;
if (!CloseOpenHandles(&is_csrss_connected))
::TerminateProcess(::GetCurrentProcess(), SBOX_FATAL_CLOSEHANDLES);
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 470e428..f5d580a 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -57891,6 +57891,7 @@ http://cs/file:chrome/histograms.xml - but prefer this file for new entries.
<int value="7010" label="SBOX_FATAL_CLOSEHANDLES"/>
<int value="7011" label="SBOX_FATAL_MITIGATION"/>
<int value="7012" label="SBOX_FATAL_MEMORY_EXCEEDED"/>
+ <int value="7013" label="SBOX_FATAL_WARMUP"/>
<int value="529697949" label="CPP_EH_EXCEPTION"/>
<int value="533692099" label="STATUS_GUARD_PAGE_VIOLATION"/>
<int value="1073740791" label="STATUS_STACK_BUFFER_OVERRUN"/>