diff options
author | liamjm <liamjm@chromium.org> | 2015-12-03 14:38:16 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-12-03 22:39:21 +0000 |
commit | 39fb5127a8a3a3f6216e48fd97ce9388c1e92c61 (patch) | |
tree | e6229a2f6816ab413573376ea760af775c804649 /sandbox | |
parent | aecbe2b387324d6a633ee732f7eb3ee2ff0cfea8 (diff) | |
download | chromium_src-39fb5127a8a3a3f6216e48fd97ce9388c1e92c61.zip chromium_src-39fb5127a8a3a3f6216e48fd97ce9388c1e92c61.tar.gz chromium_src-39fb5127a8a3a3f6216e48fd97ce9388c1e92c61.tar.bz2 |
Fixes for 1324523008 which was reverted. (Due to GetUserDefaultLocaleName being available on Vista and later)
Original description:
Add sbox tests related to warming up of locales.
Warm up locales in LowerToken() after RevertToSelf() as existing warmup was not working on Win 8.1 x64.
Remove existing warmup which was done outside of LowerToken().
BUG=464430
Review URL: https://codereview.chromium.org/1419483002
Cr-Commit-Position: refs/heads/master@{#363076}
Diffstat (limited to 'sandbox')
-rw-r--r-- | sandbox/win/BUILD.gn | 1 | ||||
-rw-r--r-- | sandbox/win/sandbox_win.gypi | 1 | ||||
-rw-r--r-- | sandbox/win/src/lpc_policy_test.cc | 156 | ||||
-rw-r--r-- | sandbox/win/src/sandbox_policy.h | 2 | ||||
-rw-r--r-- | sandbox/win/src/sandbox_types.h | 15 | ||||
-rw-r--r-- | sandbox/win/src/target_services.cc | 40 |
6 files changed, 207 insertions, 8 deletions
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); |