Commit 84fd669f authored by pennymac's avatar pennymac Committed by Commit bot

[Chrome ELF] New NT registry API.

This CL is part of a chain of CLs:
1) "MITIGATION_EXTENSION_POINT_DISABLE support for children" (https://codereview.chromium.org/1835003003)
2) "MITIGATION_EXTENSION_POINT_DISABLE emergency off finch" (https://codereview.chromium.org/1836523004/)
-> THIS
4) "Early browser security support" (https://codereview.chromium.org/1656453002)
5) "Turn on MITIGATION_EXTENSION_POINT_DISABLE" (https://codereview.chromium.org/1854323002)

Added new chrome_elf_reg utility for a registry API that doesn't touch advapi32 (useful from DllMain).
Direct calls to ntdll.  Updated Chrome ELF to always use this new registry API.

Adjusted the existing DLL blacklist to use a REG_MULTI_SZ comma-separated list instead of lots of individual reg values.

Small changes to organize file structure and functional components under chrome_elf.  Old common code now sits under "hook_util", "nt_registry", "breakpad", "dll_hash", and "blacklist".

Fairly big changes to the chrome_elf tests (blacklist_test.cc, blacklist_test_main_dll.cc and
chrome_elf_util_unittest.cc) were needed.  Since ntdll bypasses any registry redirection
(that tests use to keep the hive safe and isolated), I added in a way for the tests to access
the redirection path (and pass that information on to the test DLL).  This way the NT reg
API can work with redirection during tests.

Tests:
1) chrome_elf_unittests, chrome_elf_util_unittest.cc: ChromeElfUtilTest.NTRegistry is new
(...but run all tests to exercise the new API being used by blacklist and utils).
2) unit_tests, chrome_elf_init_unittest_win.cc: ChromeBlacklistTrialTest*

BUG=557798
CQ_INCLUDE_TRYBOTS=tryserver.chromium.win:win10_chromium_x64_rel_ng

Review-Url: https://codereview.chromium.org/1841573002
Cr-Commit-Position: refs/heads/master@{#405307}
parent b78a6a6c
......@@ -513,7 +513,9 @@ def _CheckNoNewWStrings(input_api, output_api):
for f in input_api.AffectedFiles():
if (not f.LocalPath().endswith(('.cc', '.h')) or
f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
'/win/' in f.LocalPath()):
'/win/' in f.LocalPath() or
'chrome_elf' in f.LocalPath() or
'install_static' in f.LocalPath()):
continue
allowWString = False
......
......@@ -99,9 +99,16 @@ RegistryOverrideManager::RegistryOverrideManager(
RegistryOverrideManager::~RegistryOverrideManager() {}
void RegistryOverrideManager::OverrideRegistry(HKEY override) {
OverrideRegistry(override, nullptr);
}
void RegistryOverrideManager::OverrideRegistry(HKEY override,
base::string16* override_path) {
base::string16 key_path = GenerateTempKeyPath(test_key_root_, timestamp_);
overrides_.push_back(
base::WrapUnique(new ScopedRegistryKeyOverride(override, key_path)));
if (override_path)
override_path->assign(key_path);
}
base::string16 GenerateTempKeyPath() {
......
......@@ -38,7 +38,9 @@ class RegistryOverrideManager {
// Override the given registry hive using a randomly generated temporary key.
// Multiple overrides to the same hive are not supported and lead to undefined
// behavior.
// Optional return of the registry override path.
void OverrideRegistry(HKEY override);
void OverrideRegistry(HKEY override, base::string16* override_path);
private:
friend class RegistryOverrideManagerTest;
......
......@@ -130,16 +130,22 @@ void AddFinchBlacklistToRegistry() {
HKEY_CURRENT_USER, blacklist::kRegistryFinchListPath, KEY_SET_VALUE);
std::map<std::string, std::string> params;
variations::GetVariationParams(kBrowserBlacklistTrialName, &params);
for (std::map<std::string, std::string>::iterator it = params.begin();
it != params.end();
++it) {
std::wstring name = base::UTF8ToWide(it->first);
std::wstring val = base::UTF8ToWide(it->second);
finch_blacklist_registry_key.WriteValue(name.c_str(), val.c_str());
}
std::string value = variations::GetVariationParamValue(
kBrowserBlacklistTrialName, blacklist::kRegistryFinchListValueNameStr);
if (value.empty())
return;
base::string16 value_wcs = base::UTF8ToWide(value);
// The dll names are comma-separated in this param value. We need to turn
// this into REG_MULTI_SZ format (double-null terminates).
// Note that the strings are wide character in registry.
value_wcs.push_back(L'\0');
value_wcs.push_back(L'\0');
std::replace(value_wcs.begin(), value_wcs.end(), L',', L'\0');
finch_blacklist_registry_key.WriteValue(
blacklist::kRegistryFinchListValueName, value_wcs.data(),
(value_wcs.size() * sizeof(wchar_t)), REG_MULTI_SZ);
}
void BrowserBlacklistBeaconSetup() {
......
......@@ -166,8 +166,9 @@ TEST_F(ChromeBlacklistTrialTest, AddFinchBlacklistToRegistry) {
// Set up the trial with the desired parameters.
std::map<std::string, std::string> desired_params;
desired_params["TestDllName1"] = "TestDll1.dll";
desired_params["TestDllName2"] = "TestDll2.dll";
desired_params[blacklist::kRegistryFinchListValueNameStr] =
"TestDll1.dll,TestDll2.dll";
variations::AssociateVariationParams(
kBrowserBlacklistTrialName,
......@@ -177,21 +178,23 @@ TEST_F(ChromeBlacklistTrialTest, AddFinchBlacklistToRegistry) {
// This should add the dlls in those parameters to the registry.
AddFinchBlacklistToRegistry();
// Check that all the values in desired_params were added to the registry.
// Check that all the dll names in desired_params were added to the registry.
std::vector<std::wstring> dlls;
base::win::RegKey finch_blacklist_registry_key(
HKEY_CURRENT_USER,
blacklist::kRegistryFinchListPath,
KEY_QUERY_VALUE | KEY_SET_VALUE);
ASSERT_EQ(desired_params.size(),
finch_blacklist_registry_key.GetValueCount());
ASSERT_TRUE(finch_blacklist_registry_key.HasValue(
blacklist::kRegistryFinchListValueName));
ASSERT_EQ(ERROR_SUCCESS, finch_blacklist_registry_key.ReadValues(
blacklist::kRegistryFinchListValueName, &dlls));
for (std::map<std::string, std::string>::iterator it = desired_params.begin();
it != desired_params.end();
++it) {
std::wstring name = base::UTF8ToWide(it->first);
ASSERT_TRUE(finch_blacklist_registry_key.HasValue(name.c_str()));
}
ASSERT_EQ((size_t)2,
/* Number of dll names passed in this test. */ dlls.size());
EXPECT_STREQ(L"TestDll1.dll", dlls[0].c_str());
EXPECT_STREQ(L"TestDll2.dll", dlls[1].c_str());
}
} // namespace
......@@ -2,8 +2,8 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# The install_static_util target should only depend on functions in kernel32
# and advapi32. Please don't add dependencies on other system libraries.
# The install_static_util target should only depend on functions in kernel32.
# Please don't add dependencies on other system libraries.
{
'target_defaults': {
'variables': {
......@@ -33,15 +33,13 @@
'installer_static_target': 1,
},
'dependencies': [
'installer_util_strings',
'<(DEPTH)/base/base.gyp:base',
'../chrome_elf/nt_registry/nt_registry.gyp:chrome_elf_nt_registry',
],
'msvs_settings': {
'VCLinkerTool': {
# Please don't add dependencies on other system libraries.
'AdditionalDependencies': [
'kernel32.lib',
'advapi32.lib',
],
},
},
......@@ -91,7 +89,7 @@
'installer_static_target': 1,
},
'dependencies': [
'installer_util_strings',
'../chrome_elf/nt_registry/nt_registry.gyp:chrome_elf_nt_registry_nacl_win64',
],
'include_dirs': [
'<(SHARED_INTERMEDIATE_DIR)',
......@@ -106,7 +104,6 @@
# Please don't add dependencies on other system libraries.
'AdditionalDependencies': [
'kernel32.lib',
'advapi32.lib',
],
},
},
......
......@@ -7,22 +7,19 @@ import("//testing/test.gni")
assert(is_win)
# This file only contains utility functions which must only depend on kernel32
# and advapi32. Please don't add dependencies on other system libraries.
# This file only contains utility functions which must only depend on kernel32.
# Please don't add dependencies on other system libraries.
static_library("install_static_util") {
public_deps = [
"//chrome_elf/nt_registry:nt_registry",
]
sources = [
"install_util.cc",
"install_util.h",
]
deps = [
"//base",
]
libs = [
"kernel32.lib",
"advapi32.lib",
]
libs = [ "kernel32.lib" ]
configs += [
# TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
......
include_rules = [
# Nothing from base except the includes listed below.
# Nothing from base.
"-base",
"+base/macros.h",
"+base/strings/string16.h",
"+build/build_config.h",
# Nothing from chrome.
"-chrome",
"+chrome/install_static/install_util.h",
# All registry access should go through nt_registry.
"+chrome_elf/nt_registry/nt_registry.h",
]
This diff is collapsed.
......@@ -12,8 +12,6 @@
#include <string>
#include <vector>
#include "base/strings/string16.h"
namespace install_static {
enum class ProcessType {
......@@ -78,7 +76,7 @@ bool GetCollectStatsConsent();
// Returns true if usage stats collecting is enabled for this user for the
// executable passed in as |exe_path|.
// Only used by tests.
bool GetCollectStatsConsentForTesting(const base::string16& exe_path);
bool GetCollectStatsConsentForTesting(const std::wstring& exe_path);
// Returns true if if usage stats reporting is controlled by a mandatory
// policy. |metrics_is_enforced_by_policy| will be set to true accordingly.
......@@ -100,32 +98,32 @@ bool IsNonBrowserProcess();
// TODO(ananta)
// http://crbug.com/604923
// Unify this with the Browser Distribution code.
bool GetDefaultUserDataDirectory(base::string16* result);
bool GetDefaultUserDataDirectory(std::wstring* result);
// Populates |crash_dir| with the default crash dump location regardless of
// whether DIR_USER_DATA or DIR_CRASH_DUMPS has been overridden.
// TODO(ananta)
// http://crbug.com/604923
// Unify this with the Browser Distribution code.
bool GetDefaultCrashDumpLocation(base::string16* crash_dir);
bool GetDefaultCrashDumpLocation(std::wstring* crash_dir);
// Returns the contents of the specified |variable_name| from the environment
// block of the calling process. Returns an empty string if the variable does
// not exist.
std::string GetEnvironmentString(const std::string& variable_name);
base::string16 GetEnvironmentString16(const base::string16& variable_name);
std::wstring GetEnvironmentString16(const std::wstring& variable_name);
// Sets the environment variable identified by |variable_name| to the value
// identified by |new_value|.
bool SetEnvironmentString(const std::string& variable_name,
const std::string& new_value);
bool SetEnvironmentString16(const base::string16& variable_name,
const base::string16& new_value);
bool SetEnvironmentString16(const std::wstring& variable_name,
const std::wstring& new_value);
// Returns true if the environment variable identified by |variable_name|
// exists.
bool HasEnvironmentVariable(const std::string& variable_name);
bool HasEnvironmentVariable16(const base::string16& variable_name);
bool HasEnvironmentVariable16(const std::wstring& variable_name);
// Gets the exe version details like the |product_name|, |version|,
// |special_build|, |channel_name|, etc. Most of this information is read
......@@ -133,11 +131,11 @@ bool HasEnvironmentVariable16(const base::string16& variable_name);
// TODO(ananta)
// http://crbug.com/604923
// Unify this with the Browser Distribution code.
bool GetExecutableVersionDetails(const base::string16& exe_path,
base::string16* product_name,
base::string16* version,
base::string16* special_build,
base::string16* channel_name);
bool GetExecutableVersionDetails(const std::wstring& exe_path,
std::wstring* product_name,
std::wstring* version,
std::wstring* special_build,
std::wstring* channel_name);
// Gets the channel name for the current Chrome process.
// If |add_modifier| is true the channel name is returned with the modifier
......@@ -148,8 +146,7 @@ bool GetExecutableVersionDetails(const base::string16& exe_path,
// Unify this with the Browser Distribution code.
void GetChromeChannelName(bool is_per_user_install,
bool add_modifier,
base::string16* channel_name);
std::wstring* channel_name);
// Returns the version of Google Update that is installed.
// TODO(ananta)
......@@ -162,7 +159,7 @@ std::string GetGoogleUpdateVersion();
// TODO(ananta)
// http://crbug.com/604923
// Unify this with the Browser Distribution code.
base::string16 GetChromeInstallSubDirectory();
std::wstring GetChromeInstallSubDirectory();
// Returns the registry path where the browser crash dumps metrics need to be
// written to.
......@@ -170,7 +167,7 @@ base::string16 GetChromeInstallSubDirectory();
// http://crbug.com/604923
// Unify this with the version in
// chrome\common\metrics_constants_util_win.cc
base::string16 GetBrowserCrashDumpAttemptsRegistryPath();
std::wstring GetBrowserCrashDumpAttemptsRegistryPath();
// Returns true if the |source| string matches the |pattern|. The pattern
// may contain wildcards like '?', which matches one character or a '*'
......@@ -178,12 +175,12 @@ base::string16 GetBrowserCrashDumpAttemptsRegistryPath();
// Please note that pattern matches the whole string. If you want to find
// something in the middle of the string then you need to specify the pattern
// as '*xyz*'.
bool MatchPattern(const base::string16& source, const base::string16& pattern);
bool MatchPattern(const std::wstring& source, const std::wstring& pattern);
// UTF8 to UTF16 and vice versa conversion helpers.
base::string16 UTF8ToUTF16(const std::string& source);
std::wstring UTF8ToUTF16(const std::string& source);
std::string UTF16ToUTF8(const base::string16& source);
std::string UTF16ToUTF8(const std::wstring& source);
// Tokenizes a string |str| based on single character delimiter.
// The tokens are returned in a vector. The |trim_spaces| parameter indicates
......@@ -191,8 +188,8 @@ std::string UTF16ToUTF8(const base::string16& source);
std::vector<std::string> TokenizeString(const std::string& str,
char delimiter,
bool trim_spaces);
std::vector<base::string16> TokenizeString16(const base::string16& str,
base::char16 delimiter,
std::vector<std::wstring> TokenizeString16(const std::wstring& str,
wchar_t delimiter,
bool trim_spaces);
// Compares version strings of the form "X.X.X.X" and returns the result of the
......
......@@ -70,7 +70,7 @@ TEST(InstallStaticTest, TokenizeString) {
// TokenizeString16 tests.
// Test if the string is tokenized correctly with all tokens stripped of
// leading and trailing spaces.
std::vector<base::string16> results16 =
std::vector<std::wstring> results16 =
TokenizeString16(L"un |deux\t|trois\n|quatre", L'|', true);
ASSERT_EQ(4u, results16.size());
EXPECT_THAT(results16, ElementsAre(L"un", L"deux", L"trois", L"quatre"));
......
......@@ -2,10 +2,17 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# Chrome elf targets (excepting tests) should only link in kernel32.
# Please don't add dependencies on any other system libraries.
import("//build/config/win/manifest.gni")
import("//chrome/version.gni")
import("//testing/test.gni")
##------------------------------------------------------------------------------
## chrome_elf
##------------------------------------------------------------------------------
process_version("chrome_elf_resources") {
template_file = chrome_version_rc_template
sources = [
......@@ -38,10 +45,11 @@ shared_library("chrome_elf") {
":breakpad",
":chrome_elf_manifest",
":chrome_elf_resources",
":common",
":hook_util",
"//base",
"//build/config/sanitizers:deps",
"//chrome/install_static:install_static_util",
"//chrome_elf/nt_registry:nt_registry",
"//components/crash/content/app",
"//components/crash/core/common",
"//content/public/common:result_codes",
......@@ -66,6 +74,10 @@ shared_library("chrome_elf") {
}
}
##------------------------------------------------------------------------------
## source sets
##------------------------------------------------------------------------------
source_set("constants") {
sources = [
"chrome_elf_constants.cc",
......@@ -73,35 +85,6 @@ source_set("constants") {
]
}
source_set("common") {
public_deps = [
":constants",
]
deps = [
"//base",
"//sandbox",
]
sources = [
"thunk_getter.cc",
"thunk_getter.h",
]
}
source_set("breakpad") {
include_dirs = [ "$target_gen_dir" ]
sources = [
"breakpad.cc",
"breakpad.h",
]
deps = [
":common",
"//base",
"//breakpad:breakpad_handler",
"//chrome/common:version_header",
"//chrome/install_static:install_static_util",
]
}
source_set("dll_hash") {
deps = [
"//base",
......@@ -112,6 +95,10 @@ source_set("dll_hash") {
]
}
##------------------------------------------------------------------------------
## chrome_elf sub targets
##------------------------------------------------------------------------------
executable("dll_hash_main") {
sources = [
"dll_hash/dll_hash_main.cc",
......@@ -135,13 +122,44 @@ static_library("blacklist") {
]
deps = [
":breakpad",
":common",
":constants",
":hook_util",
"//chrome/install_static:install_static_util",
"//chrome_elf/nt_registry:nt_registry",
# Still uses base/win/pe_image.h
"//base",
]
}
static_library("breakpad") {
include_dirs = [ "$target_gen_dir" ]
sources = [
"breakpad/breakpad.cc",
"breakpad/breakpad.h",
]
deps = [
"//breakpad:breakpad_handler",
"//chrome/common:version_header",
"//chrome/install_static:install_static_util",
"//chrome_elf/nt_registry:nt_registry",
]
}
static_library("hook_util") {
sources = [
"hook_util/thunk_getter.cc",
"hook_util/thunk_getter.h",
]
deps = [
"//sandbox",
]
}
##------------------------------------------------------------------------------
## tests
##------------------------------------------------------------------------------
test("chrome_elf_unittests") {
output_name = "chrome_elf_unittests"
sources = [
......@@ -154,12 +172,14 @@ test("chrome_elf_unittests") {
deps = [
":blacklist",
":blacklist_test_main_dll",
":common",
":constants",
":hook_util",
"//base",
"//base/test:test_support",
"//chrome",
"//chrome/common:version_header",
"//chrome/install_static:install_static_util",
"//chrome_elf/nt_registry:nt_registry",
"//sandbox",
"//testing/gtest",
]
......@@ -198,10 +218,10 @@ shared_library("blacklist_test_main_dll") {
]
deps = [
":blacklist",
":common",
"//base",
"//build/config/sanitizers:deps",
"//chrome/install_static:install_static_util",
"//chrome_elf/nt_registry:nt_registry",
]
}
......
caitkp@chromium.org
robertshield@chromium.org
# For early browser process security and nt_registry:
pennymac@chromium.org
......@@ -18,8 +18,11 @@
],
'dependencies': [
'../base/base.gyp:base',
'../chrome/chrome.gyp:install_static_util',
'../chrome_elf/chrome_elf.gyp:chrome_elf_breakpad',
'../chrome_elf/chrome_elf.gyp:chrome_elf_constants',
'../chrome_elf/chrome_elf.gyp:chrome_elf_hook_util',
'../chrome_elf/nt_registry/nt_registry.gyp:chrome_elf_nt_registry',
'../sandbox/sandbox.gyp:sandbox',
],
},
......@@ -32,6 +35,8 @@
],
'dependencies': [
'../base/base.gyp:base',
'../chrome/chrome.gyp:install_static_util',
'../chrome_elf/nt_registry/nt_registry.gyp:chrome_elf_nt_registry',
'blacklist',
],
},
......
This diff is collapsed.
......@@ -16,10 +16,9 @@
// Note that only #includes from base that are either header-only or built into
// base_static (see base/base.gyp) are allowed here.
#include "base/strings/string16.h"
#include "base/win/pe_image.h"
#include "chrome_elf/blacklist/blacklist.h"
#include "chrome_elf/breakpad.h"
#include "chrome_elf/breakpad/breakpad.h"
#include "sandbox/win/src/internal_types.h"
#include "sandbox/win/src/nt_internals.h"
#include "sandbox/win/src/sandbox_nt_util.h"
......@@ -37,7 +36,7 @@ FARPROC GetNtDllExportByName(const char* export_name) {
return ::GetProcAddress(ntdll, export_name);
}
int DllMatch(const base::string16& module_name) {
int DllMatch(const std::wstring& module_name) {
if (module_name.empty())
return -1;
......@@ -52,7 +51,7 @@ int DllMatch(const base::string16& module_name) {
// code in sandbox_nt_util.cc. See if they can be unified.
// Native reimplementation of PSAPIs GetMappedFileName.
base::string16 GetBackingModuleFilePath(PVOID address) {
std::wstring GetBackingModuleFilePath(PVOID address) {
DCHECK_NT(g_nt_query_virtual_memory_func);
// We'll start with something close to max_path characters for the name.
......@@ -83,11 +82,11 @@ base::string16 GetBackingModuleFilePath(PVOID address) {
UNICODE_STRING* section_string =
reinterpret_cast<UNICODE_STRING*>(section_name);
return base::string16(section_string->Buffer,
return std::wstring(section_string->Buffer,
section_string->Length / sizeof(wchar_t));
}
return base::string16();
return std::wstring();
}
bool IsModuleValidImageSection(HANDLE section,
......@@ -114,12 +113,12 @@ bool IsModuleValidImageSection(HANDLE section,
return true;
}
base::string16 ExtractLoadedModuleName(const base::string16& module_path) {
std::wstring ExtractLoadedModuleName(const std::wstring& module_path) {
if (module_path.empty() || module_path.back() == L'\\')
return base::string16();
return std::wstring();
size_t sep = module_path.find_last_of(L'\\');
if (sep == base::string16::npos)
if (sep == std::wstring::npos)
return module_path;
return module_path.substr(sep + 1);
}
......@@ -161,11 +160,11 @@ void SafeGetImageInfo(const base::win::PEImage& pe,
}
}
base::string16 GetImageInfoFromLoadedModule(HMODULE module, uint32_t* flags) {
std::wstring GetImageInfoFromLoadedModule(HMODULE module, uint32_t* flags) {
std::string out_name;
base::win::PEImage pe(module);
SafeGetImageInfo(pe, &out_name, flags);
return base::string16(out_name.begin(), out_name.end());
return std::wstring(out_name.begin(), out_name.end());
}
bool IsSameAsCurrentProcess(HANDLE process) {
......@@ -198,7 +197,7 @@ NTSTATUS BlNtMapViewOfSectionImpl(
if (module) {
UINT image_flags;
base::string16 module_name_from_image(GetImageInfoFromLoadedModule(
std::wstring module_name_from_image(GetImageInfoFromLoadedModule(
reinterpret_cast<HMODULE>(*base), &image_flags));
int blocked_index = DllMatch(module_name_from_image);
......@@ -206,8 +205,8 @@ NTSTATUS BlNtMapViewOfSectionImpl(
// If the module name isn't blacklisted, see if the file name is different
// and blacklisted.
if (blocked_index == -1) {
base::string16 file_name(GetBackingModuleFilePath(*base));
base::string16 module_name_from_file = ExtractLoadedModuleName(file_name);
std::wstring file_name(GetBackingModuleFilePath(*base));
std::wstring module_name_from_file = ExtractLoadedModuleName(file_name);
if (module_name_from_image != module_name_from_file)
blocked_index = DllMatch(module_name_from_file);
......
......@@ -7,6 +7,7 @@
#include <memory>
#include "base/environment.h"
#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/files/scoped_temp_dir.h"
#include "base/i18n/case_conversion.h"
......@@ -20,8 +21,8 @@
#include "base/win/registry.h"
#include "chrome/common/chrome_version.h"
#include "chrome_elf/blacklist/blacklist.h"
#include "chrome_elf/blacklist/test/blacklist_test_main_dll.h"
#include "chrome_elf/chrome_elf_constants.h"
#include "chrome_elf/nt_registry/nt_registry.h"
#include "testing/gtest/include/gtest/gtest.h"
const wchar_t kTestDllName1[] = L"blacklist_test_dll_1.dll";
......@@ -33,24 +34,31 @@ const wchar_t kDll3Beacon[] = L"{9E056AEC-169E-400c-B2D0-5A07E3ACE2EB}";
extern const wchar_t* kEnvVars[];
extern "C" {
// When modifying the blacklist in the test process, use the exported test dll
// functions on the test blacklist dll, not the ones linked into the test
// executable itself.
__declspec(dllimport) void TestDll_AddDllsFromRegistryToBlacklist();
__declspec(dllimport) bool TestDll_AddDllToBlacklist(const wchar_t* dll_name);
__declspec(dllimport) int TestDll_BlacklistSize();
__declspec(dllimport) void TestDll_BlockedDll(size_t blocked_index);
__declspec(dllimport) int TestDll_GetBlacklistIndex(const wchar_t* dll_name);
__declspec(dllimport) bool TestDll_IsBlacklistInitialized();
__declspec(dllimport) bool TestDll_RemoveDllFromBlacklist(
const wchar_t* dll_name);
__declspec(dllimport) bool TestDll_SuccessfullyBlocked(
namespace {
// Functions we need from blacklist_test_main_dll.dll
typedef void (*TestDll_AddDllsFromRegistryToBlacklistFunction)();
typedef bool (*TestDll_AddDllToBlacklistFunction)(const wchar_t* dll_name);
typedef int (*TestDll_BlacklistSizeFunction)();
typedef void (*TestDll_BlockedDllFunction)(size_t blocked_index);
typedef int (*TestDll_GetBlacklistIndexFunction)(const wchar_t* dll_name);
typedef bool (*TestDll_IsBlacklistInitializedFunction)();
typedef bool (*TestDll_RemoveDllFromBlacklistFunction)(const wchar_t* dll_name);
typedef bool (*TestDll_SuccessfullyBlockedFunction)(
const wchar_t** blocked_dlls,
int* size);
}
namespace {
typedef void (*InitTestDllFunction)();
TestDll_AddDllsFromRegistryToBlacklistFunction
TestDll_AddDllsFromRegistryToBlacklist = nullptr;
TestDll_AddDllToBlacklistFunction TestDll_AddDllToBlacklist = nullptr;
TestDll_BlacklistSizeFunction TestDll_BlacklistSize = nullptr;
TestDll_BlockedDllFunction TestDll_BlockedDll = nullptr;
TestDll_GetBlacklistIndexFunction TestDll_GetBlacklistIndex = nullptr;
TestDll_IsBlacklistInitializedFunction TestDll_IsBlacklistInitialized = nullptr;
TestDll_RemoveDllFromBlacklistFunction TestDll_RemoveDllFromBlacklist = nullptr;
TestDll_SuccessfullyBlockedFunction TestDll_SuccessfullyBlocked = nullptr;
InitTestDllFunction InitTestDll = nullptr;
struct TestData {
const wchar_t* dll_name;
......@@ -63,7 +71,6 @@ struct TestData {
class BlacklistTest : public testing::Test {
protected:
BlacklistTest() : override_manager_(), num_initially_blocked_(0) {
override_manager_.OverrideRegistry(HKEY_CURRENT_USER);
}
void CheckBlacklistedDllsNotLoaded() {
......@@ -125,9 +132,71 @@ class BlacklistTest : public testing::Test {
int num_initially_blocked_;
private:
// This function puts registry-key redirection paths into
// process-specific environment variables, for our test DLLs to access.
// This will only work as long as the IPC is within the same process.
void IpcOverrides() {
if (::wcslen(nt::HKCU_override) != 0) {
ASSERT_TRUE(
::SetEnvironmentVariableW(L"hkcu_override", nt::HKCU_override));
}
if (::wcslen(nt::HKLM_override) != 0) {
ASSERT_TRUE(
::SetEnvironmentVariableW(L"hklm_override", nt::HKLM_override));
}
}
void SetUp() override {
// Force an import from blacklist_test_main_dll.
InitBlacklistTestDll();
base::string16 temp;
override_manager_.OverrideRegistry(HKEY_CURRENT_USER, &temp);
::wcsncpy(nt::HKCU_override, temp.c_str(), nt::g_kRegMaxPathLen - 1);
// Make the override path available to our test DLL.
IpcOverrides();
// Load the main test Dll now.
// Note: this has to happen after we set up the registry overrides.
HMODULE dll = nullptr;
dll = ::LoadLibraryW(L"blacklist_test_main_dll.dll");
if (!dll)
return;
TestDll_AddDllsFromRegistryToBlacklist =
reinterpret_cast<TestDll_AddDllsFromRegistryToBlacklistFunction>(
::GetProcAddress(dll, "TestDll_AddDllsFromRegistryToBlacklist"));
TestDll_AddDllToBlacklist =
reinterpret_cast<TestDll_AddDllToBlacklistFunction>(
::GetProcAddress(dll, "TestDll_AddDllToBlacklist"));
TestDll_BlacklistSize = reinterpret_cast<TestDll_BlacklistSizeFunction>(
::GetProcAddress(dll, "TestDll_BlacklistSize"));
TestDll_BlockedDll = reinterpret_cast<TestDll_BlockedDllFunction>(
::GetProcAddress(dll, "TestDll_BlockedDll"));
TestDll_GetBlacklistIndex =
reinterpret_cast<TestDll_GetBlacklistIndexFunction>(
::GetProcAddress(dll, "TestDll_GetBlacklistIndex"));
TestDll_IsBlacklistInitialized =
reinterpret_cast<TestDll_IsBlacklistInitializedFunction>(
::GetProcAddress(dll, "TestDll_IsBlacklistInitialized"));
TestDll_RemoveDllFromBlacklist =
reinterpret_cast<TestDll_RemoveDllFromBlacklistFunction>(
::GetProcAddress(dll, "TestDll_RemoveDllFromBlacklist"));
TestDll_SuccessfullyBlocked =
reinterpret_cast<TestDll_SuccessfullyBlockedFunction>(
::GetProcAddress(dll, "TestDll_SuccessfullyBlocked"));
InitTestDll = reinterpret_cast<InitTestDllFunction>(
::GetProcAddress(dll, "InitTestDll"));
if (!TestDll_AddDllsFromRegistryToBlacklist || !TestDll_AddDllToBlacklist ||
!TestDll_BlacklistSize || !TestDll_BlockedDll ||
!TestDll_GetBlacklistIndex || !TestDll_IsBlacklistInitialized ||
!TestDll_RemoveDllFromBlacklist || !TestDll_SuccessfullyBlocked ||
!InitTestDll)
return;
// We have to call this exported function every time this test setup runs.
// If the tests are running in single process mode, the test DLL does not
// get reloaded everytime - but we need to make sure it updates
// appropriately.
InitTestDll();
blacklist_registry_key_.reset(
new base::win::RegKey(HKEY_CURRENT_USER,
blacklist::kRegistryBeaconPath,
......@@ -142,6 +211,9 @@ class BlacklistTest : public testing::Test {
TestDll_RemoveDllFromBlacklist(kTestDllName2);
TestDll_RemoveDllFromBlacklist(kTestDllName3);
}
// A scoped temporary directory to be destroyed with this test.
base::ScopedTempDir reg_override_dir_;
};
TEST_F(BlacklistTest, Beacon) {
......@@ -254,15 +326,27 @@ TEST_F(BlacklistTest, AddDllsFromRegistryToBlacklist) {
KEY_QUERY_VALUE | KEY_SET_VALUE);
key.DeleteKey(L"");
// Add the test dlls to the registry (with their name as both key and value).
// Add the test dlls to the registry.
// (REG_MULTI_SZ: eos separated, double null terminated.)
base::win::RegKey finch_blacklist_registry_key(
HKEY_CURRENT_USER,
blacklist::kRegistryFinchListPath,
KEY_QUERY_VALUE | KEY_SET_VALUE);
std::vector<wchar_t>(reg_buffer);
for (size_t i = 0; i < arraysize(test_data); ++i) {
finch_blacklist_registry_key.WriteValue(test_data[i].dll_name,
test_data[i].dll_name);
if (reg_buffer.size() > 0)
reg_buffer.push_back(L'\0');
const wchar_t* dll = test_data[i].dll_name;
// Append the name, not including terminator.
reg_buffer.insert(reg_buffer.end(), dll, dll + ::wcslen(dll));
}
reg_buffer.push_back(L'\0');
reg_buffer.push_back(L'\0');
finch_blacklist_registry_key.WriteValue(
blacklist::kRegistryFinchListValueName, reg_buffer.data(),
(DWORD)(reg_buffer.size() * sizeof(wchar_t)), REG_MULTI_SZ);
TestDll_AddDllsFromRegistryToBlacklist();
CheckBlacklistedDllsNotLoaded();
......
// Copyright 2013 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.
#include "base/at_exit.h"
#include "chrome_elf/blacklist/test/blacklist_test_main_dll.h"
#include "testing/gtest/include/gtest/gtest.h"
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
base::AtExitManager at_exit_manager;
InitBlacklistTestDll();
RUN_ALL_TESTS();
}
......@@ -2,16 +2,49 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome_elf/blacklist/blacklist.h"
#include <windows.h>
#include "chrome/install_static/install_util.h"
#include "chrome_elf/blacklist/blacklist.h"
#include "chrome_elf/nt_registry/nt_registry.h"
namespace {
void GetIpcOverrides() {
DWORD buffer_size = ::GetEnvironmentVariableW(L"hkcu_override", nullptr, 0);
if (buffer_size > 0) {
wchar_t* content = new wchar_t[buffer_size];
buffer_size =
::GetEnvironmentVariableW(L"hkcu_override", content, buffer_size);
if (buffer_size)
::wcsncpy(nt::HKCU_override, content, nt::g_kRegMaxPathLen - 1);
delete[] content;
}
buffer_size = ::GetEnvironmentVariableW(L"hklm_override", nullptr, 0);
if (buffer_size > 0) {
wchar_t* content = new wchar_t[buffer_size];
buffer_size =
::GetEnvironmentVariableW(L"hklm_override", content, buffer_size);
if (buffer_size)
::wcsncpy(nt::HKLM_override, content, nt::g_kRegMaxPathLen - 1);
delete[] content;
}
return;
}
} // namespace
extern "C" void InitBlacklistTestDll() {
extern "C" __declspec(dllexport) void InitTestDll() {
// Make sure we've got the latest registry overrides.
GetIpcOverrides();
}
BOOL APIENTRY DllMain(HMODULE module, DWORD reason, LPVOID reserved) {
if (reason == DLL_PROCESS_ATTACH) {
GetIpcOverrides();
install_static::InitializeProcessType();
blacklist::Initialize(true); // force always on, no beacon
}
......
......@@ -13,4 +13,3 @@ EXPORTS
TestDll_IsBlacklistInitialized=IsBlacklistInitialized
TestDll_SuccessfullyBlocked=SuccessfullyBlocked
TestDll_RemoveDllFromBlacklist=RemoveDllFromBlacklist
InitBlacklistTestDll
\ No newline at end of file
......@@ -5,15 +5,12 @@
// This module contains the necessary code to register the Breakpad exception
// handler. This implementation is based on Chrome's crash reporting code.
#include "chrome_elf/breakpad.h"
#include "chrome_elf/breakpad/breakpad.h"
#include <sddl.h>
#include "base/macros.h"
#include "base/strings/string16.h"
#include "breakpad/src/client/windows/handler/exception_handler.h"
#include "chrome/common/chrome_version.h"
#include "chrome/install_static/install_util.h"
#include "chrome_elf/nt_registry/nt_registry.h"
google_breakpad::ExceptionHandler* g_elf_breakpad = NULL;
......@@ -39,56 +36,33 @@ const wchar_t kSystemPrincipalSid[] = L"S-1-5-18";
const wchar_t kNoErrorDialogs[] = L"noerrdialogs";
google_breakpad::CustomClientInfo* GetCustomInfo() {
base::string16 process =
std::wstring process =
install_static::IsNonBrowserProcess() ? L"renderer" : L"browser";
wchar_t exe_path[MAX_PATH] = {};
base::string16 channel;
if (GetModuleFileName(NULL, exe_path, arraysize(exe_path)) &&
std::wstring channel;
if (GetModuleFileName(NULL, exe_path, MAX_PATH) &&
install_static::IsSxSChrome(exe_path)) {
channel = L"canary";
}
static google_breakpad::CustomInfoEntry ver_entry(
kBreakpadVersionEntry, TEXT(CHROME_VERSION_STRING));
static google_breakpad::CustomInfoEntry prod_entry(
kBreakpadProdEntry, kBreakpadProductName);
static google_breakpad::CustomInfoEntry plat_entry(
kBreakpadPlatformEntry, kBreakpadPlatformWin32);
static google_breakpad::CustomInfoEntry proc_entry(
kBreakpadProcessEntry, process.c_str());
static google_breakpad::CustomInfoEntry channel_entry(
kBreakpadChannelEntry, channel.c_str());
static google_breakpad::CustomInfoEntry prod_entry(kBreakpadProdEntry,
kBreakpadProductName);
static google_breakpad::CustomInfoEntry plat_entry(kBreakpadPlatformEntry,
kBreakpadPlatformWin32);
static google_breakpad::CustomInfoEntry proc_entry(kBreakpadProcessEntry,
process.c_str());
static google_breakpad::CustomInfoEntry channel_entry(kBreakpadChannelEntry,
channel.c_str());
static google_breakpad::CustomInfoEntry entries[] = {
ver_entry, prod_entry, plat_entry, proc_entry, channel_entry};
static google_breakpad::CustomClientInfo custom_info = {
entries, arraysize(entries) };
entries, (sizeof(entries) / sizeof(google_breakpad::CustomInfoEntry))};
return &custom_info;
}
base::string16 GetUserSidString() {
// Get the current token.
HANDLE token = NULL;
base::string16 user_sid;
if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, &token))
return user_sid;
DWORD size = sizeof(TOKEN_USER) + SECURITY_MAX_SID_SIZE;
BYTE user_bytes[sizeof(TOKEN_USER) + SECURITY_MAX_SID_SIZE] = {};
TOKEN_USER* user = reinterpret_cast<TOKEN_USER*>(user_bytes);
wchar_t* sid_string = NULL;
if (::GetTokenInformation(token, TokenUser, user, size, &size) &&
user->User.Sid &&
::ConvertSidToStringSid(user->User.Sid, &sid_string)) {
user_sid = sid_string;
::LocalFree(sid_string);
}
CloseHandle(token);
return user_sid;
}
bool IsHeadless() {
DWORD ret = ::GetEnvironmentVariable(L"CHROME_HEADLESS", NULL, 0);
if (ret != 0)
......@@ -118,7 +92,7 @@ int GenerateCrashDump(EXCEPTION_POINTERS* exinfo) {
void InitializeCrashReporting() {
wchar_t exe_path[MAX_PATH] = {};
if (!::GetModuleFileName(NULL, exe_path, arraysize(exe_path)))
if (!::GetModuleFileName(NULL, exe_path, MAX_PATH))
return;
// Disable the message box for assertions.
......@@ -145,7 +119,7 @@ void InitializeCrashReporting() {
bool is_official_chrome_build = false;
#endif
base::string16 pipe_name;
std::wstring pipe_name;
bool enabled_by_policy = false;
bool use_policy =
......@@ -161,9 +135,9 @@ void InitializeCrashReporting() {
// 32-bit user: \\.\pipe\GoogleCrashServices\<user SID>
// 64-bit system: \\.\pipe\GoogleCrashServices\S-1-5-18-x64
// 64-bit user: \\.\pipe\GoogleCrashServices\<user SID>-x64
base::string16 user_sid = install_static::IsSystemInstall(exe_path)
std::wstring user_sid = install_static::IsSystemInstall(exe_path)
? kSystemPrincipalSid
: GetUserSidString();
: nt::GetCurrentUserSidString();
if (user_sid.empty())
return;
......@@ -180,14 +154,9 @@ void InitializeCrashReporting() {
}
g_elf_breakpad = new google_breakpad::ExceptionHandler(
temp_directory,
NULL,
NULL,
NULL,
google_breakpad::ExceptionHandler::HANDLER_ALL,
dump_type,
pipe_name.c_str(),
GetCustomInfo());
temp_directory, NULL, NULL, NULL,
google_breakpad::ExceptionHandler::HANDLER_ALL, dump_type,
pipe_name.c_str(), GetCustomInfo());
if (g_elf_breakpad->IsOutOfProcess()) {
// Tells breakpad to handle breakpoint and single step exceptions.
......
......@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_ELF_BREAKPAD_H_
#define CHROME_ELF_BREAKPAD_H_
#ifndef CHROME_ELF_BREAKPAD_BREAKPAD_H_
#define CHROME_ELF_BREAKPAD_BREAKPAD_H_
#include <windows.h>
......@@ -31,4 +31,4 @@ int GenerateCrashDump(EXCEPTION_POINTERS* exinfo);
// InitializeCrashReporting() and used by GenerateCrashDump() to record dumps.
extern google_breakpad::ExceptionHandler* g_elf_breakpad;
#endif // CHROME_ELF_BREAKPAD_H_
#endif // CHROME_ELF_BREAKPAD_BREAKPAD_H_
......@@ -12,6 +12,9 @@
'dll_hash.gypi',
],
'targets': [
##--------------------------------------------------------------------------
## chrome_elf
##--------------------------------------------------------------------------
{
'target_name': 'chrome_elf_resources',
'type': 'none',
......@@ -42,9 +45,12 @@
'<(SHARED_INTERMEDIATE_DIR)/chrome_elf/chrome_elf_version.rc',
],
'dependencies': [
'../chrome/chrome.gyp:install_static_util',
'blacklist',
'chrome_elf_breakpad',
'chrome_elf_hook_util',
'chrome_elf_resources',
'nt_registry/nt_registry.gyp:chrome_elf_nt_registry',
'../chrome/chrome.gyp:install_static_util',
'../components/components.gyp:crash_component',
'../components/components.gyp:crash_core_common',
......@@ -68,6 +74,52 @@
},
},
},
##--------------------------------------------------------------------------
## chrome_elf sub targets
##--------------------------------------------------------------------------
{
'target_name': 'chrome_elf_constants',
'type': 'static_library',
'include_dirs': [
'..',
],
'sources': [
'chrome_elf_constants.cc',
'chrome_elf_constants.h',
],
},
{
'target_name': 'chrome_elf_breakpad',
'type': 'static_library',
'include_dirs': [
'..',
'<(SHARED_INTERMEDIATE_DIR)',
],
'sources': [
'breakpad/breakpad.cc',
'breakpad/breakpad.h',
],
'dependencies': [
'../breakpad/breakpad.gyp:breakpad_handler',
'../chrome/chrome.gyp:install_static_util',
'../chrome/common_constants.gyp:version_header',
'nt_registry/nt_registry.gyp:chrome_elf_nt_registry',
],
},
{
'target_name': 'chrome_elf_hook_util',
'type': 'static_library',
'include_dirs': [
'..',
],
'sources': [
'hook_util/thunk_getter.cc',
'hook_util/thunk_getter.h',
],
},
##--------------------------------------------------------------------------
## tests
##--------------------------------------------------------------------------
{
'target_name': 'chrome_elf_unittests_exe',
'product_name': 'chrome_elf_unittests',
......@@ -94,6 +146,8 @@
'blacklist_test_dll_2',
'blacklist_test_dll_3',
'blacklist_test_main_dll',
'chrome_elf_hook_util',
'nt_registry/nt_registry.gyp:chrome_elf_nt_registry',
],
'msvs_settings': {
'VCLinkerTool': {
......@@ -125,50 +179,10 @@
'chrome_elf_unittests_exe',
],
},
{
'target_name': 'chrome_elf_constants',
'type': 'static_library',
'include_dirs': [
'..',
],
'sources': [
'chrome_elf_constants.cc',
'chrome_elf_constants.h',
],
},
{
'target_name': 'chrome_elf_common',
'type': 'static_library',
'dependencies': [
'chrome_elf_constants',
],
'include_dirs': [
'..',
],
'sources': [
'thunk_getter.cc',
'thunk_getter.h',
],
},
{
'target_name': 'chrome_elf_breakpad',
'type': 'static_library',
'include_dirs': [
'..',
'<(SHARED_INTERMEDIATE_DIR)',
],
'sources': [
'breakpad.cc',
'breakpad.h',
],
'dependencies': [
'chrome_elf_common',
'../breakpad/breakpad.gyp:breakpad_handler',
'../chrome/common_constants.gyp:version_header',
'../chrome/chrome.gyp:install_static_util',
],
},
], # targets
##----------------------------------------------------------------------------
## conditionals
##----------------------------------------------------------------------------
'conditions': [
['test_isolation_mode != "noop"', {
'targets': [
......
......@@ -21,6 +21,8 @@ const wchar_t kRegistryBeaconPath[] =
L"SOFTWARE\\" PRODUCT_STRING_PATH L"\\BLBeacon";
const wchar_t kRegistryFinchListPath[] =
L"SOFTWARE\\" PRODUCT_STRING_PATH L"\\BLFinchList";
const char kRegistryFinchListValueNameStr[] = "BLDlls";
const wchar_t kRegistryFinchListValueName[] = L"BLDlls";
const wchar_t kBeaconVersion[] = L"version";
const wchar_t kBeaconState[] = L"state";
const wchar_t kBeaconAttemptCount[] = L"failed_count";
......@@ -28,3 +30,13 @@ const wchar_t kBeaconAttemptCount[] = L"failed_count";
const DWORD kBeaconMaxAttempts = 2;
} // namespace blacklist
namespace elf_sec {
const wchar_t kRegSecurityFinchPath[] =
L"SOFTWARE\\" PRODUCT_STRING_PATH L"\\BrowserSboxFinch";
const wchar_t kRegSecurityPath[] =
L"SOFTWARE\\" PRODUCT_STRING_PATH L"\\BrowserSec";
} // namespace elf_sec
......@@ -17,6 +17,13 @@ extern const wchar_t kRegistryBeaconPath[];
// The registry path of the finch blacklist dlls.
extern const wchar_t kRegistryFinchListPath[];
// The registry value name for the REG_MULTI_SZ list of blacklist dlls.
// Note the char version is handy for use as the param name when
// appending dll names to the base::FieldTrial. Can be removed
// if no longer used.
extern const char kRegistryFinchListValueNameStr[];
extern const wchar_t kRegistryFinchListValueName[];
// The properties for the blacklist beacon.
extern const wchar_t kBeaconVersion[];
extern const wchar_t kBeaconState[];
......@@ -41,4 +48,14 @@ enum BlacklistState {
} // namespace blacklist
namespace elf_sec {
// The registry path of the finch "emergency-off"
// switch for sandbox::MITIGATION_EXTENSION_POINT_DISABLE.
extern const wchar_t kRegSecurityFinchPath[];
// The registry path for any early-browser security settings.
extern const wchar_t kRegSecurityPath[];
}
#endif // CHROME_ELF_CHROME_ELF_CONSTANTS_H_
......@@ -8,8 +8,7 @@
#include "chrome/install_static/install_util.h"
#include "chrome_elf/blacklist/blacklist.h"
#include "chrome_elf/breakpad.h"
#include "chrome_elf/breakpad/breakpad.h"
void SignalChromeElf() {
blacklist::ResetBeacon();
......
This diff is collapsed.
......@@ -5,7 +5,6 @@
#include <stdint.h>
#include <windows.h>
#include "base/macros.h"
#include "sandbox/win/src/interception_internal.h"
#include "sandbox/win/src/internal_types.h"
#include "sandbox/win/src/sandbox_utils.h"
......@@ -30,7 +29,11 @@ enum Version {
// WOW64_DISABLED for both "32-bit Chrome on 32-bit Windows" and "64-bit
// Chrome on 64-bit Windows". WOW64_UNKNOWN means "an error occurred", e.g.
// the process does not have sufficient access rights to determine this.
enum WOW64Status { WOW64_DISABLED, WOW64_ENABLED, WOW64_UNKNOWN, };
enum WOW64Status {
WOW64_DISABLED,
WOW64_ENABLED,
WOW64_UNKNOWN,
};
WOW64Status GetWOW64StatusForCurrentProcess() {
typedef BOOL(WINAPI * IsWow64ProcessFunc)(HANDLE, PBOOL);
......
......@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_ELF_THUNK_GETTER_H_
#define CHROME_ELF_THUNK_GETTER_H_
#ifndef CHROME_ELF_HOOK_UTIL_THUNK_GETTER_H_
#define CHROME_ELF_HOOK_UTIL_THUNK_GETTER_H_
namespace sandbox {
class ServiceResolverThunk;
......@@ -13,4 +13,4 @@ class ServiceResolverThunk;
// resulting thunk is passed to the caller.
sandbox::ServiceResolverThunk* GetThunk(bool relaxed);
#endif // CHROME_ELF_THUNK_GETTER_H_
#endif // CHROME_ELF_HOOK_UTIL_THUNK_GETTER_H_
# Copyright 2016 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.
import("//build/config/chrome_build.gni")
import("//testing/test.gni")
assert(is_win)
# This target only contains utility functions which must only depend on
# kernel32. Please don't add dependencies on other system libraries.
static_library("nt_registry") {
sources = [
"../../sandbox/win/src/nt_internals.h",
"nt_registry.cc",
"nt_registry.h",
]
libs = [ "kernel32.lib" ]
}
include_rules = [
# Nothing from base.
"-base",
# Nothing from chrome.
"-chrome",
"-chrome_elf",
"+chrome_elf/nt_registry/nt_registry.h",
]
This diff is collapsed.
# Copyright 2016 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.
# The nt_registry target should only depend on functions in kernel32.
# Please don't add dependencies on other system libraries.
{
'target_defaults': {
# This part is shared between the two versions of the target.
'type': 'static_library',
'sources': [
'nt_registry.cc',
'nt_registry.h',
],
'include_dirs': [
'../..',
'<(SHARED_INTERMEDIATE_DIR)',
],
'msvs_settings': {
'VCLinkerTool': {
# Please don't add dependencies on other system libraries.
'AdditionalDependencies': [
'kernel32.lib',
],
},
},
},
'conditions': [
['OS=="win"', {
'targets': [
{
# GN version: "//chrome_elf/nt_registry",
'target_name': 'chrome_elf_nt_registry',
},
],
}],
['OS=="win" and target_arch=="ia32"', {
'targets': [
{
# GN version: "//chrome_elf/nt_registry",
'target_name': 'chrome_elf_nt_registry_nacl_win64',
'configurations': {
'Common_Base': {
'msvs_target_platform': 'x64',
},
},
},
],
}],
],
}
// Copyright 2016 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.
// This API is a usability layer for direct registry access via NTDLL.
// It allows for "advapi32-free" registry access, which is especially
// useful for accessing registy from DllMain (holding loader lock),
// or if a dependency on/linkage of ADVAPI32.dll is not desired.
// The implementation of this API should only use ntdll and kernel32 system
// DLLs.
// Note that this API is currently lazy initialized. Any function that is
// NOT merely a wrapper function (i.e. any function that directly interacts with
// NTDLL) will immediately check:
// if (!g_initialized)
// InitNativeRegApi();
// There is currently no multi-threading lock around the lazy initialization,
// as the main client for this API (chrome_elf) does not introduce
// a multi-threading concern. This can easily be changed if needed.
#ifndef CHROME_ELF_NT_REGISTRY_NT_REGISTRY_H_
#define CHROME_ELF_NT_REGISTRY_NT_REGISTRY_H_
#include <vector>
#include "sandbox/win/src/nt_internals.h" // NTSTATUS
namespace nt {
// These globals are only used in test suites that use reg redirection
// of HKLM and/or HKCU.
extern const size_t g_kRegMaxPathLen;
extern wchar_t HKLM_override[];
extern wchar_t HKCU_override[];
// AUTO will choose depending on system install or not.
// Use HKLM or HKCU to override.
typedef enum _ROOT_KEY { AUTO = 0, HKLM, HKCU } ROOT_KEY;
// Create and/or open a registry key.
// - This function will recursively create multiple sub-keys if required for
// |key_path|.
// - If the key doesn't need to be left open, pass in nullptr for |out_handle|.
// - This function will happily succeed if the key already exists.
// - Optional |out_handle|. If nullptr, function will close handle when done.
// Otherwise, will hold the open handle to the deepest subkey.
// - Caller must call CloseRegKey on returned handle (on success).
bool CreateRegKey(ROOT_KEY root,
const wchar_t* key_path,
ACCESS_MASK access,
HANDLE* out_handle OPTIONAL);
// Open existing registry key.
// - Caller must call CloseRegKey on returned handle (on success).
// - Optional error code can be returned on failure for extra detail.
bool OpenRegKey(ROOT_KEY root,
const wchar_t* key_path,
ACCESS_MASK access,
HANDLE* out_handle,
NTSTATUS* error_code OPTIONAL);
// Delete a registry key.
// - Caller must still call CloseRegKey after the delete.
bool DeleteRegKey(HANDLE key);
// Delete a registry key.
// - WRAPPER: Function opens and closes the target key for caller.
bool DeleteRegKey(ROOT_KEY root, const wchar_t* key_path);
// Close a registry key handle that was opened with CreateRegKey or OpenRegKey.
void CloseRegKey(HANDLE key);
//------------------------------------------------------------------------------
// Getter functions
//------------------------------------------------------------------------------
// Main function to query a registry value.
// - Key handle should have been opened with CreateRegKey or OpenRegKey.
// - Types defined in winnt.h. E.g.: REG_DWORD, REG_SZ.
// - Caller is responsible for calling "delete[] *out_buffer" (on success).
bool QueryRegKeyValue(HANDLE key,
const wchar_t* value_name,
ULONG* out_type,
BYTE** out_buffer,
DWORD* out_size);
// Query DWORD value.
// - WRAPPER: Function works with DWORD data type.
// - Key handle should have been opened with CreateRegKey or OpenRegKey.
// - Handle will be left open. Caller must still call CloseRegKey when done.
bool QueryRegValueDWORD(HANDLE key,
const wchar_t* value_name,
DWORD* out_dword);
// Query DWORD value.
// - WRAPPER: Function opens and closes the target key for caller, and works
// with DWORD data type.
bool QueryRegValueDWORD(ROOT_KEY root,
const wchar_t* key_path,
const wchar_t* value_name,
DWORD* out_dword);
// Query SZ (string) value.
// - WRAPPER: Function works with SZ data type.
// - Key handle should have been opened with CreateRegKey or OpenRegKey.
// - Handle will be left open. Caller must still call CloseRegKey when done.
bool QueryRegValueSZ(HANDLE key,
const wchar_t* value_name,
std::wstring* out_sz);
// Query SZ (string) value.
// - WRAPPER: Function opens and closes the target key for caller, and works
// with SZ data type.
bool QueryRegValueSZ(ROOT_KEY root,
const wchar_t* key_path,
const wchar_t* value_name,
std::wstring* out_sz);
// Query MULTI_SZ (multiple strings) value.
// - WRAPPER: Function works with MULTI_SZ data type.
// - Key handle should have been opened with CreateRegKey or OpenRegKey.
// - Handle will be left open. Caller must still call CloseRegKey when done.
bool QueryRegValueMULTISZ(HANDLE key,
const wchar_t* value_name,
std::vector<std::wstring>* out_multi_sz);
// Query MULTI_SZ (multiple strings) value.
// - WRAPPER: Function opens and closes the target key for caller, and works
// with MULTI_SZ data type.
bool QueryRegValueMULTISZ(ROOT_KEY root,
const wchar_t* key_path,
const wchar_t* value_name,
std::vector<std::wstring>* out_multi_sz);
//------------------------------------------------------------------------------
// Setter functions
//------------------------------------------------------------------------------
// Main function to set a registry value.
// - Key handle should have been opened with CreateRegKey or OpenRegKey.
// - Types defined in winnt.h. E.g.: REG_DWORD, REG_SZ.
bool SetRegKeyValue(HANDLE key,
const wchar_t* value_name,
ULONG type,
const BYTE* data,
DWORD data_size);
// Set DWORD value.
// - WRAPPER: Function works with DWORD data type.
// - Key handle should have been opened with CreateRegKey or OpenRegKey.
// - Handle will be left open. Caller must still call CloseRegKey when done.
bool SetRegValueDWORD(HANDLE key, const wchar_t* value_name, DWORD value);
// Set DWORD value.
// - WRAPPER: Function opens and closes the target key for caller, and works
// with DWORD data type.
bool SetRegValueDWORD(ROOT_KEY root,
const wchar_t* key_path,
const wchar_t* value_name,
DWORD value);
// Set SZ (string) value.
// - WRAPPER: Function works with SZ data type.
// - Key handle should have been opened with CreateRegKey or OpenRegKey.
// - Handle will be left open. Caller must still call CloseRegKey when done.
bool SetRegValueSZ(HANDLE key,
const wchar_t* value_name,
const std::wstring& value);
// Set SZ (string) value.
// - WRAPPER: Function opens and closes the target key for caller, and works
// with SZ data type.
bool SetRegValueSZ(ROOT_KEY root,
const wchar_t* key_path,
const wchar_t* value_name,
const std::wstring& value);
// Set MULTI_SZ (multiple strings) value.
// - WRAPPER: Function works with MULTI_SZ data type.
// - Key handle should have been opened with CreateRegKey or OpenRegKey.
// - Handle will be left open. Caller must still call CloseRegKey when done.
bool SetRegValueMULTISZ(HANDLE key,
const wchar_t* value_name,
const std::vector<std::wstring>& values);
// Set MULTI_SZ (multiple strings) value.
// - WRAPPER: Function opens and closes the target key for caller, and works
// with MULTI_SZ data type.
bool SetRegValueMULTISZ(ROOT_KEY root,
const wchar_t* key_path,
const wchar_t* value_name,
const std::vector<std::wstring>& values);
//------------------------------------------------------------------------------
// Utils
//------------------------------------------------------------------------------
// Returns the current user SID in string form.
const wchar_t* GetCurrentUserSidString();
}; // namespace nt
#endif // CHROME_ELF_NT_REGISTRY_NT_REGISTRY_H_
......@@ -333,14 +333,14 @@ typedef struct _PROCESS_BASIC_INFORMATION {
};
} PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION;
typedef NTSTATUS (WINAPI *NtQueryInformationProcessFunction)(
typedef NTSTATUS(WINAPI* NtQueryInformationProcessFunction)(
IN HANDLE ProcessHandle,
IN PROCESSINFOCLASS ProcessInformationClass,
OUT PVOID ProcessInformation,
IN ULONG ProcessInformationLength,
OUT PULONG ReturnLength OPTIONAL);
typedef NTSTATUS (WINAPI *NtSetInformationProcessFunction)(
typedef NTSTATUS(WINAPI* NtSetInformationProcessFunction)(
HANDLE ProcessHandle,
IN PROCESSINFOCLASS ProcessInformationClass,
IN PVOID ProcessInformation,
......@@ -370,7 +370,14 @@ typedef NTSTATUS (WINAPI *NtOpenProcessTokenExFunction) (
IN ULONG HandleAttributes,
OUT PHANDLE TokenHandle);
typedef NTSTATUS (WINAPI * RtlCreateUserThreadFunction)(
typedef NTSTATUS(WINAPI* NtQueryInformationTokenFunction)(
IN HANDLE TokenHandle,
IN TOKEN_INFORMATION_CLASS TokenInformationClass,
OUT PVOID TokenInformation,
IN ULONG TokenInformationLength,
OUT PULONG ReturnLength);
typedef NTSTATUS(WINAPI* RtlCreateUserThreadFunction)(
IN HANDLE Process,
IN PSECURITY_DESCRIPTOR ThreadSecurityDescriptor,
IN BOOLEAN CreateSuspended,
......@@ -382,9 +389,31 @@ typedef NTSTATUS (WINAPI * RtlCreateUserThreadFunction)(
OUT PHANDLE Thread,
OUT PCLIENT_ID ClientId);
typedef NTSTATUS(WINAPI* RtlConvertSidToUnicodeStringFunction)(
OUT PUNICODE_STRING UnicodeString,
IN PSID Sid,
IN BOOLEAN AllocateDestinationString);
typedef VOID(WINAPI* RtlFreeUnicodeStringFunction)(
IN OUT PUNICODE_STRING UnicodeString);
// -----------------------------------------------------------------------
// Registry
typedef enum _KEY_VALUE_INFORMATION_CLASS {
KeyValueFullInformation = 1
} KEY_VALUE_INFORMATION_CLASS,
*PKEY_VALUE_INFORMATION_CLASS;
typedef struct _KEY_VALUE_FULL_INFORMATION {
ULONG TitleIndex;
ULONG Type;
ULONG DataOffset;
ULONG DataLength;
ULONG NameLength;
WCHAR Name[1];
} KEY_VALUE_FULL_INFORMATION, *PKEY_VALUE_FULL_INFORMATION;
typedef NTSTATUS (WINAPI *NtCreateKeyFunction)(
OUT PHANDLE KeyHandle,
IN ACCESS_MASK DesiredAccess,
......@@ -408,6 +437,24 @@ typedef NTSTATUS (WINAPI *NtOpenKeyExFunction)(
typedef NTSTATUS (WINAPI *NtDeleteKeyFunction)(
IN HANDLE KeyHandle);
typedef NTSTATUS(WINAPI* RtlFormatCurrentUserKeyPathFunction)(
OUT PUNICODE_STRING RegistryPath);
typedef NTSTATUS(WINAPI* NtQueryValueKeyFunction)(IN HANDLE KeyHandle,
IN PUNICODE_STRING ValueName,
IN KEY_VALUE_INFORMATION_CLASS
KeyValueInformationClass,
OUT PVOID KeyValueInformation,
IN ULONG Length,
OUT PULONG ResultLength);
typedef NTSTATUS(WINAPI* NtSetValueKeyFunction)(IN HANDLE KeyHandle,
IN PUNICODE_STRING ValueName,
IN ULONG TitleIndex OPTIONAL,
IN ULONG Type,
IN PVOID Data,
IN ULONG DataSize);
// -----------------------------------------------------------------------
// Memory
......
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