Commit 0eec8bac authored by Penny MacNeil's avatar Penny MacNeil Committed by Commit Bot

[chrome_elf, third-party block support] Turn on new hook, remove old.

This does not "turn on" full blocking.  The new hook will be in place,
ready to block, but behavior will be determined by
chrome/browser/conflicts/* in future CLs.  The hook will default
allow load.

Tests: chrome_elf_unittests.exe, ThirdParty*
Bug: 769590
Change-Id: I97b1f1d368a160e0f9856dfb55a0242af350328d
Reviewed-on: https://chromium-review.googlesource.com/1076972Reviewed-by: default avatarTom Sepez <tsepez@chromium.org>
Commit-Queue: Penny MacNeil <pennymac@chromium.org>
Cr-Commit-Position: refs/heads/master@{#567920}
parent 04cb9f94
...@@ -4230,7 +4230,6 @@ test("unit_tests") { ...@@ -4230,7 +4230,6 @@ test("unit_tests") {
"//chrome/app:chrome_dll_resources", "//chrome/app:chrome_dll_resources",
"//chrome/install_static:install_static_util", "//chrome/install_static:install_static_util",
"//chrome/installer/util:strings", "//chrome/installer/util:strings",
"//chrome_elf:blacklist_test_dll_1",
"//third_party/iaccessible2", "//third_party/iaccessible2",
"//third_party/isimpledom", "//third_party/isimpledom",
"//third_party/wtl", "//third_party/wtl",
......
...@@ -36,6 +36,24 @@ source_set("chrome_elf_main_include") { ...@@ -36,6 +36,24 @@ source_set("chrome_elf_main_include") {
] ]
} }
# For code that isn't Chrome-the browser, like test binaries, these stubs stand
# in for chrome_elf.;
static_library("test_stubs") {
testonly = true
sources = [
"chrome_elf_main.h",
"chrome_elf_test_stubs.cc",
]
deps = [
":sha1",
":third_party_shared_defines",
"//base",
"//chrome/common:constants",
]
}
# We should move chrome_result_codes.h to another target which does not bring # We should move chrome_result_codes.h to another target which does not bring
# in the world. # in the world.
shared_library("chrome_elf") { shared_library("chrome_elf") {
...@@ -81,119 +99,29 @@ shared_library("chrome_elf") { ...@@ -81,119 +99,29 @@ shared_library("chrome_elf") {
} }
} }
# For code that isn't Chrome-the browser, like test binaries, these stubs stand
# in for chrome_elf.;
static_library("test_stubs") {
testonly = true
sources = [
"chrome_elf_main.h",
"chrome_elf_test_stubs.cc",
]
deps = [
":sha1",
":third_party_shared_defines",
"//base",
"//chrome/common:constants",
]
}
##------------------------------------------------------------------------------
## source sets
##------------------------------------------------------------------------------
source_set("constants") {
sources = [
"chrome_elf_constants.cc",
"chrome_elf_constants.h",
]
}
source_set("dll_hash") {
deps = [
"//base",
]
sources = [
"dll_hash/dll_hash.cc",
"dll_hash/dll_hash.h",
]
}
source_set("pe_image_safe") {
sources = [
"pe_image_safe/pe_image_safe.cc",
"pe_image_safe/pe_image_safe.h",
]
}
source_set("security") {
sources = [
"chrome_elf_security.cc",
"chrome_elf_security.h",
]
deps = [
":constants",
":nt_registry",
"//chrome/install_static:install_static_util",
]
}
source_set("sha1") {
sources = [
"sha1/sha1.cc",
"sha1/sha1.h",
]
}
# This source_set defines third-party-related structures and APIs used from
# outside chrome_elf.dll. The APIs are exported from chrome_elf (add a
# data_dep on //chrome_elf:chrome_elf), which will always be loaded before
# chrome.dll.
source_set("third_party_shared_defines") {
sources = [
"sha1/sha1.h",
"third_party_dlls/logging_api.cc",
"third_party_dlls/logging_api.h",
"third_party_dlls/packed_list_format.cc",
"third_party_dlls/packed_list_format.h",
]
}
##------------------------------------------------------------------------------ ##------------------------------------------------------------------------------
## chrome_elf sub targets ## chrome_elf sub targets
##------------------------------------------------------------------------------ ##------------------------------------------------------------------------------
executable("dll_hash_main") {
sources = [
"dll_hash/dll_hash_main.cc",
]
deps = [
":dll_hash",
"//build/win:default_exe_manifest",
]
}
static_library("blacklist") { static_library("blacklist") {
sources = [ sources = [
"blacklist/blacklist.cc", "blacklist/blacklist.cc",
"blacklist/blacklist.h", "blacklist/blacklist.h",
"blacklist/blacklist_interceptions.cc",
"blacklist/blacklist_interceptions.h",
]
public_deps = [
"//sandbox",
] ]
deps = [ deps = [
":constants", ":constants",
":crash",
":hook_util",
":nt_registry", ":nt_registry",
"//base:base_static", # pe_image
"//chrome/install_static:install_static_util", "//chrome/install_static:install_static_util",
] ]
} }
source_set("constants") {
sources = [
"chrome_elf_constants.cc",
"chrome_elf_constants.h",
]
}
static_library("crash") { static_library("crash") {
sources = [ sources = [
"../chrome/app/chrome_crash_reporter_client_win.cc", "../chrome/app/chrome_crash_reporter_client_win.cc",
...@@ -215,6 +143,26 @@ static_library("crash") { ...@@ -215,6 +143,26 @@ static_library("crash") {
] ]
} }
source_set("dll_hash") {
deps = [
"//base",
]
sources = [
"dll_hash/dll_hash.cc",
"dll_hash/dll_hash.h",
]
}
executable("dll_hash_main") {
sources = [
"dll_hash/dll_hash_main.cc",
]
deps = [
":dll_hash",
"//build/win:default_exe_manifest",
]
}
static_library("hook_util") { static_library("hook_util") {
sources = [ sources = [
"../base/macros.h", "../base/macros.h",
...@@ -224,6 +172,8 @@ static_library("hook_util") { ...@@ -224,6 +172,8 @@ static_library("hook_util") {
deps = [ deps = [
":nt_registry", # utils ":nt_registry", # utils
"//base:base_static", # pe_image "//base:base_static", # pe_image
]
public_deps = [
"//sandbox", "//sandbox",
] ]
} }
...@@ -247,6 +197,32 @@ static_library("nt_registry") { ...@@ -247,6 +197,32 @@ static_library("nt_registry") {
libs = [ "kernel32.lib" ] libs = [ "kernel32.lib" ]
} }
source_set("pe_image_safe") {
sources = [
"pe_image_safe/pe_image_safe.cc",
"pe_image_safe/pe_image_safe.h",
]
}
source_set("security") {
sources = [
"chrome_elf_security.cc",
"chrome_elf_security.h",
]
deps = [
":constants",
":nt_registry",
"//chrome/install_static:install_static_util",
]
}
source_set("sha1") {
sources = [
"sha1/sha1.cc",
"sha1/sha1.h",
]
}
static_library("third_party_dlls") { static_library("third_party_dlls") {
visibility = [ ":*" ] # Only targets in this file can depend on this. visibility = [ ":*" ] # Only targets in this file can depend on this.
sources = [ sources = [
...@@ -273,6 +249,20 @@ static_library("third_party_dlls") { ...@@ -273,6 +249,20 @@ static_library("third_party_dlls") {
] ]
} }
# This source_set defines third-party-related structures and APIs used from
# outside chrome_elf.dll. The APIs are exported from chrome_elf (add a
# data_dep on //chrome_elf:chrome_elf), which will always be loaded before
# chrome.dll.
source_set("third_party_shared_defines") {
sources = [
"sha1/sha1.h",
"third_party_dlls/logging_api.cc",
"third_party_dlls/logging_api.h",
"third_party_dlls/packed_list_format.cc",
"third_party_dlls/packed_list_format.h",
]
}
##------------------------------------------------------------------------------ ##------------------------------------------------------------------------------
## tests ## tests
##------------------------------------------------------------------------------ ##------------------------------------------------------------------------------
...@@ -296,7 +286,6 @@ test("chrome_elf_unittests") { ...@@ -296,7 +286,6 @@ test("chrome_elf_unittests") {
include_dirs = [ "$target_gen_dir" ] include_dirs = [ "$target_gen_dir" ]
deps = [ deps = [
":blacklist", ":blacklist",
":blacklist_test_main_dll",
":constants", ":constants",
":crash", ":crash",
":hook_util", ":hook_util",
...@@ -317,9 +306,6 @@ test("chrome_elf_unittests") { ...@@ -317,9 +306,6 @@ test("chrome_elf_unittests") {
"//testing/gtest", "//testing/gtest",
] ]
data_deps = [ data_deps = [
":blacklist_test_dll_1",
":blacklist_test_dll_2",
":blacklist_test_dll_3",
":chrome_elf", ":chrome_elf",
":main_unittest_dll_1", ":main_unittest_dll_1",
":main_unittest_dll_2", ":main_unittest_dll_2",
...@@ -365,6 +351,21 @@ test("chrome_elf_import_unittests") { ...@@ -365,6 +351,21 @@ test("chrome_elf_import_unittests") {
] ]
} }
##------------------------------------------------------------------------------
## tests - data_deps
##------------------------------------------------------------------------------
shared_library("hook_util_test_dll") {
testonly = true
sources = [
"hook_util/test/hook_util_test_dll.cc",
"hook_util/test/hook_util_test_dll.h",
]
deps = [
"//build/config:exe_and_shlib_deps",
]
}
shared_library("main_unittest_dll_1") { shared_library("main_unittest_dll_1") {
testonly = true testonly = true
sources = [ sources = [
...@@ -408,55 +409,3 @@ executable("third_party_dlls_test_exe") { ...@@ -408,55 +409,3 @@ executable("third_party_dlls_test_exe") {
"//components/crash/content/app:crash_export_stubs", "//components/crash/content/app:crash_export_stubs",
] ]
} }
shared_library("blacklist_test_main_dll") {
testonly = true
sources = [
"blacklist/test/blacklist_test_main_dll.cc",
"blacklist/test/blacklist_test_main_dll.def",
"blacklist/test/blacklist_test_main_dll.h",
]
deps = [
":blacklist",
":nt_registry",
"//base",
"//chrome/install_static:install_static_util",
"//components/crash/content/app:test_support",
]
}
loadable_module("blacklist_test_dll_1") {
testonly = true
sources = [
"blacklist/test/blacklist_test_dll_1.cc",
"blacklist/test/blacklist_test_dll_1.def",
]
}
loadable_module("blacklist_test_dll_2") {
testonly = true
sources = [
"blacklist/test/blacklist_test_dll_2.cc",
"blacklist/test/blacklist_test_dll_2.def",
]
}
# As-is, this does not generate a .lib file because there are no exports and no
# .def file. The current definition of loadable_module does not declare a .lib
# file as an output, so this is OK. If it did (or if this used shared_library
# which does), Ninja would get confused and always rebuild this target because
# it sees a declared output file but that file doesn't exist on disk.
loadable_module("blacklist_test_dll_3") {
testonly = true
sources = [
"blacklist/test/blacklist_test_dll_3.cc",
]
}
shared_library("hook_util_test_dll") {
testonly = true
sources = [
"hook_util/test/hook_util_test_dll.cc",
"hook_util/test/hook_util_test_dll.h",
]
}
...@@ -7,21 +7,37 @@ ...@@ -7,21 +7,37 @@
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
#include <vector>
#include "chrome/install_static/install_util.h" #include "chrome/install_static/install_util.h"
#include "chrome_elf/blacklist/blacklist_interceptions.h"
#include "chrome_elf/chrome_elf_constants.h" #include "chrome_elf/chrome_elf_constants.h"
#include "chrome_elf/hook_util/hook_util.h"
#include "chrome_elf/nt_registry/nt_registry.h" #include "chrome_elf/nt_registry/nt_registry.h"
#include "sandbox/win/src/interception_internal.h"
#include "sandbox/win/src/internal_types.h"
#include "sandbox/win/src/service_resolver.h"
// http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx
extern "C" IMAGE_DOS_HEADER __ImageBase;
namespace blacklist { namespace blacklist {
namespace {
// Record if the blacklist was successfully initialized so processes can easily
// determine if the blacklist is enabled for them.
bool g_blacklist_initialized = false;
// Utility function for converting UTF-8 to UTF-16.
bool UTF8ToUTF16(const std::string& utf8, std::wstring* utf16) {
assert(utf16);
if (utf8.empty()) {
utf16->clear();
return true;
}
int size_needed_chars = ::MultiByteToWideChar(
CP_UTF8, 0, utf8.c_str(), static_cast<int>(utf8.size()), nullptr, 0);
if (!size_needed_chars)
return false;
utf16->resize(size_needed_chars);
return ::MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(),
static_cast<int>(utf8.size()), &(*utf16)[0],
size_needed_chars);
}
} // namespace
// The DLLs listed here are known (or under strong suspicion) of causing crashes // The DLLs listed here are known (or under strong suspicion) of causing crashes
// when they are loaded in the browser. DLLs should only be added to this list // when they are loaded in the browser. DLLs should only be added to this list
...@@ -76,50 +92,6 @@ const wchar_t* g_troublesome_dlls[kTroublesomeDllsMaxCount] = { ...@@ -76,50 +92,6 @@ const wchar_t* g_troublesome_dlls[kTroublesomeDllsMaxCount] = {
bool g_blocked_dlls[kTroublesomeDllsMaxCount] = {}; bool g_blocked_dlls[kTroublesomeDllsMaxCount] = {};
int g_num_blocked_dlls = 0; int g_num_blocked_dlls = 0;
} // namespace blacklist
// Allocate storage for thunks in a page of this module to save on doing
// an extra allocation at run time.
#pragma section(".crthunk", read, execute)
__declspec(allocate(".crthunk")) sandbox::ThunkData g_thunk_storage;
namespace {
// Record if the blacklist was successfully initialized so processes can easily
// determine if the blacklist is enabled for them.
bool g_blacklist_initialized = false;
// Utility function for converting UTF-8 to UTF-16.
bool UTF8ToUTF16(const std::string& utf8, std::wstring* utf16) {
assert(utf16);
if (utf8.empty()) {
utf16->clear();
return true;
}
int size_needed_chars = ::MultiByteToWideChar(
CP_UTF8, 0, utf8.c_str(), static_cast<int>(utf8.size()), nullptr, 0);
if (!size_needed_chars)
return false;
utf16->resize(size_needed_chars);
return ::MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(),
static_cast<int>(utf8.size()), &(*utf16)[0],
size_needed_chars);
}
} // namespace
namespace blacklist {
#if defined(_WIN64)
// Allocate storage for the pointer to the old NtMapViewOfSectionFunction.
#pragma section(".oldntmap", write, read)
__declspec(allocate(".oldntmap"))
NtMapViewOfSectionFunction g_nt_map_view_of_section_func = NULL;
#endif
bool LeaveSetupBeacon() { bool LeaveSetupBeacon() {
HANDLE key_handle = INVALID_HANDLE_VALUE; HANDLE key_handle = INVALID_HANDLE_VALUE;
...@@ -313,10 +285,6 @@ bool DllMatch(const std::string& module_name) { ...@@ -313,10 +285,6 @@ bool DllMatch(const std::string& module_name) {
} }
bool Initialize(bool force) { bool Initialize(bool force) {
// Check to see that we found the functions we need in ntdll.
if (!InitializeInterceptImports())
return false;
// Check to see if this is a non-browser process, abort if so. // Check to see if this is a non-browser process, abort if so.
if (install_static::IsNonBrowserProcess()) if (install_static::IsNonBrowserProcess())
return false; return false;
...@@ -326,68 +294,7 @@ bool Initialize(bool force) { ...@@ -326,68 +294,7 @@ bool Initialize(bool force) {
if (!force && !LeaveSetupBeacon()) if (!force && !LeaveSetupBeacon())
return false; return false;
// It is possible for other dlls to have already patched code by now and return true;
// attempting to patch their code might result in crashes.
const bool kRelaxed = false;
// Create a thunk via the appropriate ServiceResolver instance.
sandbox::ServiceResolverThunk* thunk = elf_hook::HookSystemService(kRelaxed);
// Don't try blacklisting on unsupported OS versions.
if (!thunk)
return false;
BYTE* thunk_storage = reinterpret_cast<BYTE*>(&g_thunk_storage);
// Mark the thunk storage as readable and writeable, since we
// ready to write to it.
DWORD old_protect = 0;
if (!VirtualProtect(&g_thunk_storage, sizeof(g_thunk_storage),
PAGE_EXECUTE_READWRITE, &old_protect)) {
return false;
}
thunk->AllowLocalPatches();
// We declare this early so it can be used in the 64-bit block below and
// still work on 32-bit build when referenced at the end of the function.
BOOL page_executable = false;
// Replace the default NtMapViewOfSection with our patched version.
#if defined(_WIN64)
NTSTATUS ret = thunk->Setup(
::GetModuleHandle(sandbox::kNtdllName),
reinterpret_cast<void*>(&__ImageBase), "NtMapViewOfSection", NULL,
reinterpret_cast<void*>(&blacklist::BlNtMapViewOfSection64),
thunk_storage, sizeof(sandbox::ThunkData), NULL);
// Keep a pointer to the original code, we don't have enough space to
// add it directly to the call.
g_nt_map_view_of_section_func =
reinterpret_cast<NtMapViewOfSectionFunction>(thunk_storage);
// Ensure that the pointer to the old function can't be changed.
page_executable = VirtualProtect(&g_nt_map_view_of_section_func,
sizeof(g_nt_map_view_of_section_func),
PAGE_EXECUTE_READ, &old_protect);
#else
NTSTATUS ret = thunk->Setup(
::GetModuleHandle(sandbox::kNtdllName),
reinterpret_cast<void*>(&__ImageBase), "NtMapViewOfSection", NULL,
reinterpret_cast<void*>(&blacklist::BlNtMapViewOfSection), thunk_storage,
sizeof(sandbox::ThunkData), NULL);
#endif
delete thunk;
// Record if we have initialized the blacklist.
g_blacklist_initialized = NT_SUCCESS(ret);
// Mark the thunk storage as executable and prevent any future writes to it.
page_executable = page_executable &&
VirtualProtect(&g_thunk_storage, sizeof(g_thunk_storage),
PAGE_EXECUTE_READ, &old_protect);
return NT_SUCCESS(ret) && page_executable;
} }
} // namespace blacklist } // namespace blacklist
...@@ -5,10 +5,6 @@ ...@@ -5,10 +5,6 @@
#ifndef CHROME_ELF_BLACKLIST_BLACKLIST_H_ #ifndef CHROME_ELF_BLACKLIST_BLACKLIST_H_
#define CHROME_ELF_BLACKLIST_BLACKLIST_H_ #define CHROME_ELF_BLACKLIST_BLACKLIST_H_
#if defined(_WIN64)
#include "sandbox/win/src/sandbox_nt_types.h"
#endif
#include <stddef.h> #include <stddef.h>
#include <string> #include <string>
...@@ -21,10 +17,6 @@ const size_t kTroublesomeDllsMaxCount = 64; ...@@ -21,10 +17,6 @@ const size_t kTroublesomeDllsMaxCount = 64;
// The DLL blacklist. // The DLL blacklist.
extern const wchar_t* g_troublesome_dlls[kTroublesomeDllsMaxCount]; extern const wchar_t* g_troublesome_dlls[kTroublesomeDllsMaxCount];
#if defined(_WIN64)
extern NtMapViewOfSectionFunction g_nt_map_view_of_section_func;
#endif
// Attempts to leave a beacon in the current user's registry hive. If the // Attempts to leave a beacon in the current user's registry hive. If the
// blacklist beacon doesn't say it is enabled or there are any other errors when // blacklist beacon doesn't say it is enabled or there are any other errors when
// creating the beacon, returns false. Otherwise returns true. The intent of the // creating the beacon, returns false. Otherwise returns true. The intent of the
...@@ -76,10 +68,9 @@ int DllMatch(const std::wstring& module_name); ...@@ -76,10 +68,9 @@ int DllMatch(const std::wstring& module_name);
// Note: |module_name| must be an ASCII encoded string. // Note: |module_name| must be an ASCII encoded string.
bool DllMatch(const std::string& module_name); bool DllMatch(const std::string& module_name);
// Initializes the DLL blacklist in the current process. This should be called // Initializes the deprecated DLL blacklist in the current process.
// before any undesirable DLLs might be loaded. If |force| is set to true, then // - If |force| is set to true, then initialization will take place even if a
// initialization will take place even if a beacon is present. This is useful // beacon is present. This is useful for tests.
// for tests.
bool Initialize(bool force); bool Initialize(bool force);
} // namespace blacklist } // namespace blacklist
......
// 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.
//
// Implementation of NtMapViewOfSection intercept for 32 bit builds.
//
// TODO(robertshield): Implement the 64 bit intercept.
#include "chrome_elf/blacklist/blacklist_interceptions.h"
#include <stddef.h>
#include <stdint.h>
#include <string>
#include <vector>
// 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/win/pe_image.h"
#include "chrome_elf/blacklist/blacklist.h"
#include "chrome_elf/crash/crash_helper.h"
#include "sandbox/win/src/internal_types.h"
#include "sandbox/win/src/nt_internals.h"
#include "sandbox/win/src/sandbox_nt_util.h"
#include "sandbox/win/src/sandbox_types.h"
namespace {
NtQuerySectionFunction g_nt_query_section_func = NULL;
NtQueryVirtualMemoryFunction g_nt_query_virtual_memory_func = NULL;
NtUnmapViewOfSectionFunction g_nt_unmap_view_of_section_func = NULL;
// TODO(robertshield): Merge with ntdll exports cache.
FARPROC GetNtDllExportByName(const char* export_name) {
HMODULE ntdll = ::GetModuleHandle(sandbox::kNtdllName);
return ::GetProcAddress(ntdll, export_name);
}
// TODO(robertshield): Some of the helper functions below overlap somewhat with
// code in sandbox_nt_util.cc. See if they can be unified.
// Native reimplementation of PSAPIs GetMappedFileName.
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.
SIZE_T buffer_bytes = MAX_PATH * 2;
std::vector<BYTE> buffer_data(buffer_bytes);
for (;;) {
MEMORY_SECTION_NAME* section_name =
reinterpret_cast<MEMORY_SECTION_NAME*>(&buffer_data[0]);
if (!section_name)
break;
SIZE_T returned_bytes;
NTSTATUS ret = g_nt_query_virtual_memory_func(
NtCurrentProcess, address, MemorySectionName, section_name,
buffer_bytes, &returned_bytes);
if (STATUS_BUFFER_OVERFLOW == ret) {
// Retry the call with the given buffer size.
buffer_bytes = returned_bytes + 1;
buffer_data.resize(buffer_bytes);
section_name = NULL;
continue;
}
if (!NT_SUCCESS(ret))
break;
UNICODE_STRING* section_string =
reinterpret_cast<UNICODE_STRING*>(section_name);
return std::wstring(section_string->Buffer,
section_string->Length / sizeof(wchar_t));
}
return std::wstring();
}
bool IsModuleValidImageSection(HANDLE section,
PVOID* base,
PLARGE_INTEGER offset,
PSIZE_T view_size) {
DCHECK_NT(g_nt_query_section_func);
if (!section || !base || !view_size || offset)
return false;
SECTION_BASIC_INFORMATION basic_info;
SIZE_T bytes_returned;
NTSTATUS ret = g_nt_query_section_func(section, SectionBasicInformation,
&basic_info, sizeof(basic_info),
&bytes_returned);
if (!NT_SUCCESS(ret) || sizeof(basic_info) != bytes_returned)
return false;
if (!(basic_info.Attributes & SEC_IMAGE))
return false;
return true;
}
std::wstring ExtractLoadedModuleName(const std::wstring& module_path) {
if (module_path.empty() || module_path.back() == L'\\')
return std::wstring();
size_t sep = module_path.find_last_of(L'\\');
if (sep == std::wstring::npos)
return module_path;
return module_path.substr(sep + 1);
}
// Fills |out_name| with the image name from the given |pe| image and |flags|
// with additional info about the image.
void SafeGetImageInfo(const base::win::PEImage& pe,
std::string* out_name,
uint32_t* flags) {
out_name->clear();
out_name->reserve(MAX_PATH);
*flags = 0;
__try {
if (pe.VerifyMagic()) {
*flags |= sandbox::MODULE_IS_PE_IMAGE;
PIMAGE_EXPORT_DIRECTORY exports = pe.GetExportDirectory();
if (exports) {
const char* image_name = reinterpret_cast<const char*>(
pe.RVAToAddr(exports->Name));
size_t i = 0;
for (; i < MAX_PATH && *image_name; ++i, ++image_name)
out_name->push_back(*image_name);
}
PIMAGE_NT_HEADERS headers = pe.GetNTHeaders();
if (headers) {
if (headers->OptionalHeader.AddressOfEntryPoint)
*flags |= sandbox::MODULE_HAS_ENTRY_POINT;
if (headers->OptionalHeader.SizeOfCode)
*flags |= sandbox::MODULE_HAS_CODE;
}
}
} __except((GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ||
GetExceptionCode() == EXCEPTION_GUARD_PAGE ||
GetExceptionCode() == EXCEPTION_IN_PAGE_ERROR) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
out_name->clear();
}
}
std::wstring GetImageInfoFromLoadedModule(HMODULE module, uint32_t* flags) {
std::string out_name;
base::win::PEImage pe(module);
SafeGetImageInfo(pe, &out_name, flags);
return std::wstring(out_name.begin(), out_name.end());
}
bool IsSameAsCurrentProcess(HANDLE process) {
return (NtCurrentProcess == process) ||
(::GetProcessId(process) == ::GetCurrentProcessId());
}
NTSTATUS BlNtMapViewOfSectionImpl(
NtMapViewOfSectionFunction orig_MapViewOfSection,
HANDLE section,
HANDLE process,
PVOID* base,
ULONG_PTR zero_bits,
SIZE_T commit_size,
PLARGE_INTEGER offset,
PSIZE_T view_size,
SECTION_INHERIT inherit,
ULONG allocation_type,
ULONG protect) {
NTSTATUS ret = orig_MapViewOfSection(section, process, base, zero_bits,
commit_size, offset, view_size, inherit,
allocation_type, protect);
if (!NT_SUCCESS(ret) || !IsSameAsCurrentProcess(process) ||
!IsModuleValidImageSection(section, base, offset, view_size)) {
return ret;
}
HMODULE module = reinterpret_cast<HMODULE>(*base);
if (module) {
UINT image_flags;
std::wstring module_name_from_image(GetImageInfoFromLoadedModule(
reinterpret_cast<HMODULE>(*base), &image_flags));
int blocked_index = blacklist::DllMatch(module_name_from_image);
// If the module name isn't blacklisted, see if the file name is different
// and blacklisted.
if (blocked_index == -1) {
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 = blacklist::DllMatch(module_name_from_file);
}
if (blocked_index != -1) {
DCHECK_NT(g_nt_unmap_view_of_section_func);
g_nt_unmap_view_of_section_func(process, *base);
ret = STATUS_UNSUCCESSFUL;
blacklist::BlockedDll(blocked_index);
}
}
return ret;
}
} // namespace
namespace blacklist {
bool InitializeInterceptImports() {
g_nt_query_section_func =
reinterpret_cast<NtQuerySectionFunction>(
GetNtDllExportByName("NtQuerySection"));
g_nt_query_virtual_memory_func =
reinterpret_cast<NtQueryVirtualMemoryFunction>(
GetNtDllExportByName("NtQueryVirtualMemory"));
g_nt_unmap_view_of_section_func =
reinterpret_cast<NtUnmapViewOfSectionFunction>(
GetNtDllExportByName("NtUnmapViewOfSection"));
return (g_nt_query_section_func && g_nt_query_virtual_memory_func &&
g_nt_unmap_view_of_section_func);
}
SANDBOX_INTERCEPT NTSTATUS WINAPI
BlNtMapViewOfSection(NtMapViewOfSectionFunction orig_MapViewOfSection,
HANDLE section,
HANDLE process,
PVOID* base,
ULONG_PTR zero_bits,
SIZE_T commit_size,
PLARGE_INTEGER offset,
PSIZE_T view_size,
SECTION_INHERIT inherit,
ULONG allocation_type,
ULONG protect) {
NTSTATUS ret = STATUS_UNSUCCESSFUL;
__try {
ret = BlNtMapViewOfSectionImpl(orig_MapViewOfSection, section, process,
base, zero_bits, commit_size, offset,
view_size, inherit, allocation_type,
protect);
} __except (elf_crash::GenerateCrashDump(GetExceptionInformation())) {
}
return ret;
}
#if defined(_WIN64)
NTSTATUS WINAPI BlNtMapViewOfSection64(
HANDLE section, HANDLE process, PVOID *base, ULONG_PTR zero_bits,
SIZE_T commit_size, PLARGE_INTEGER offset, PSIZE_T view_size,
SECTION_INHERIT inherit, ULONG allocation_type, ULONG protect) {
return BlNtMapViewOfSection(g_nt_map_view_of_section_func, section, process,
base, zero_bits, commit_size, offset, view_size,
inherit, allocation_type, protect);
}
#endif
} // namespace blacklist
// 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.
#ifndef CHROME_ELF_BLACKLIST_BLACKLIST_INTERCEPTIONS_H_
#define CHROME_ELF_BLACKLIST_BLACKLIST_INTERCEPTIONS_H_
#include "sandbox/win/src/nt_internals.h"
#include "sandbox/win/src/sandbox_types.h"
namespace blacklist {
bool InitializeInterceptImports();
// Interception of NtMapViewOfSection within the current process.
// It should never be called directly. This function provides the means to
// detect dlls being loaded, so we can patch them if needed.
SANDBOX_INTERCEPT NTSTATUS WINAPI BlNtMapViewOfSection(
NtMapViewOfSectionFunction orig_MapViewOfSection,
HANDLE section,
HANDLE process,
PVOID *base,
ULONG_PTR zero_bits,
SIZE_T commit_size,
PLARGE_INTEGER offset,
PSIZE_T view_size,
SECTION_INHERIT inherit,
ULONG allocation_type,
ULONG protect);
#if defined(_WIN64)
// Interception of NtMapViewOfSection within the current process.
// It should never be called directly. This function provides the means to
// detect dlls being loaded, so we can patch them if needed.
SANDBOX_INTERCEPT NTSTATUS WINAPI BlNtMapViewOfSection64(
HANDLE section, HANDLE process, PVOID *base, ULONG_PTR zero_bits,
SIZE_T commit_size, PLARGE_INTEGER offset, PSIZE_T view_size,
SECTION_INHERIT inherit, ULONG allocation_type, ULONG protect);
#endif
} // namespace blacklist
#endif // CHROME_ELF_BLACKLIST_BLACKLIST_INTERCEPTIONS_H_
This diff is collapsed.
// 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 <windows.h>
BOOL APIENTRY DllMain(HMODULE module, DWORD reason, LPVOID reserved) {
return TRUE;
}
; 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.
LIBRARY "blacklist_test_dll_1.dll"
// 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 <windows.h>
const wchar_t kDll2Beacon[] = L"{F70A0100-2889-4629-9B44-610FE5C73231}";
extern "C" {
// Have a dummy export so that the module gets an export table entry.
void DummyExport() {}
}
BOOL APIENTRY DllMain(HMODULE module, DWORD reason, LPVOID reserved) {
if (reason == DLL_PROCESS_ATTACH) {
::SetEnvironmentVariable(kDll2Beacon, L"1");
}
return TRUE;
}
; 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.
LIBRARY "blacklist_test_dll_2.dll"
EXPORTS
DummyExport
// 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 <windows.h>
const wchar_t kDll3Beacon[] = L"{9E056AEC-169E-400c-B2D0-5A07E3ACE2EB}";
BOOL APIENTRY DllMain(HMODULE module, DWORD reason, LPVOID reserved) {
if (reason == DLL_PROCESS_ATTACH) {
::SetEnvironmentVariable(kDll3Beacon, L"1");
}
return TRUE;
}
// 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 "chrome_elf/blacklist/blacklist.h"
#include <windows.h>
#include "chrome/install_static/install_util.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) {
std::wstring content(buffer_size, L'\0');
buffer_size =
::GetEnvironmentVariableW(L"hkcu_override", &content[0], buffer_size);
if (buffer_size)
nt::SetTestingOverride(nt::HKCU, content);
}
buffer_size = ::GetEnvironmentVariableW(L"hklm_override", nullptr, 0);
if (buffer_size > 0) {
std::wstring content(buffer_size, L'\0');
buffer_size =
::GetEnvironmentVariableW(L"hklm_override", &content[0], buffer_size);
if (buffer_size)
nt::SetTestingOverride(nt::HKLM, content);
}
return;
}
} // namespace
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
}
return TRUE;
}
; 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.
LIBRARY "blacklist_test_main_dll.dll"
EXPORTS
TestDll_AddDllToBlacklist=AddDllToBlacklist
TestDll_BlacklistSize=BlacklistSize
TestDll_BlockedDll=BlockedDll
TestDll_IsBlacklistInitialized=IsBlacklistInitialized
TestDll_SuccessfullyBlocked=SuccessfullyBlocked
TestDll_RemoveDllFromBlacklist=RemoveDllFromBlacklist
// 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.
#ifndef CHROME_ELF_BLACKLIST_TEST_BLACKLIST_TEST_MAIN_DLL_H_
#define CHROME_ELF_BLACKLIST_TEST_BLACKLIST_TEST_MAIN_DLL_H_
extern "C" void InitBlacklistTestDll();
#endif // CHROME_ELF_BLACKLIST_TEST_BLACKLIST_TEST_MAIN_DLL_H_
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "chrome/install_static/user_data_dir.h" #include "chrome/install_static/user_data_dir.h"
#include "chrome_elf/blacklist/blacklist.h" #include "chrome_elf/blacklist/blacklist.h"
#include "chrome_elf/crash/crash_helper.h" #include "chrome_elf/crash/crash_helper.h"
#include "chrome_elf/third_party_dlls/main.h"
// This function is a temporary workaround for https://crbug.com/655788. We // This function is a temporary workaround for https://crbug.com/655788. We
// need to come up with a better way to initialize crash reporting that can // need to come up with a better way to initialize crash reporting that can
...@@ -56,8 +57,16 @@ BOOL APIENTRY DllMain(HMODULE module, DWORD reason, LPVOID reserved) { ...@@ -56,8 +57,16 @@ BOOL APIENTRY DllMain(HMODULE module, DWORD reason, LPVOID reserved) {
install_static::InitializeProcessType(); install_static::InitializeProcessType();
// If this is not the browser process, all done.
if (install_static::IsNonBrowserProcess())
return TRUE;
__try { __try {
// Initialize blacklist before initializing third_party_dlls.
// Note: "blacklist" is deprecated in favor of "third_party_dlls", but
// beacon management temporarily remains in the blacklist project.
blacklist::Initialize(false); // Don't force, abort if beacon is present. blacklist::Initialize(false); // Don't force, abort if beacon is present.
third_party_dlls::Init();
} __except (elf_crash::GenerateCrashDump(GetExceptionInformation())) { } __except (elf_crash::GenerateCrashDump(GetExceptionInformation())) {
} }
} else if (reason == DLL_PROCESS_DETACH) { } else if (reason == DLL_PROCESS_DETACH) {
......
...@@ -152,7 +152,7 @@ TEST_F(ELFImportsTest, DISABLED_ChromeElfLoadSanityTestImpl) { ...@@ -152,7 +152,7 @@ TEST_F(ELFImportsTest, DISABLED_ChromeElfLoadSanityTestImpl) {
ASSERT_EQ(nullptr, ::GetModuleHandle(L"user32.dll")); ASSERT_EQ(nullptr, ::GetModuleHandle(L"user32.dll"));
HMODULE chrome_elf_module_handle = ::LoadLibrary(dll.value().c_str()); HMODULE chrome_elf_module_handle = ::LoadLibrary(dll.value().c_str());
EXPECT_TRUE(chrome_elf_module_handle != nullptr); ASSERT_TRUE(chrome_elf_module_handle != nullptr);
// Loading chrome_elf.dll should not load user32.dll // Loading chrome_elf.dll should not load user32.dll
EXPECT_EQ(nullptr, ::GetModuleHandle(L"user32.dll")); EXPECT_EQ(nullptr, ::GetModuleHandle(L"user32.dll"));
EXPECT_TRUE(!!::FreeLibrary(chrome_elf_module_handle)); EXPECT_TRUE(!!::FreeLibrary(chrome_elf_module_handle));
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <assert.h> #include <assert.h>
#include "chrome/install_static/install_util.h"
#include "chrome_elf/third_party_dlls/hook.h" #include "chrome_elf/third_party_dlls/hook.h"
#include "chrome_elf/third_party_dlls/imes.h" #include "chrome_elf/third_party_dlls/imes.h"
#include "chrome_elf/third_party_dlls/logs.h" #include "chrome_elf/third_party_dlls/logs.h"
...@@ -32,6 +33,11 @@ bool Init() { ...@@ -32,6 +33,11 @@ bool Init() {
// Debug check: Init should not be called more than once. // Debug check: Init should not be called more than once.
assert(!g_third_party_initialized); assert(!g_third_party_initialized);
// Sanity check: third_party_dlls should only be enabled in the browser
// process at this time.
if (install_static::IsNonBrowserProcess())
return false;
// Zero tolerance for unsupported versions of Windows. Third-party control // Zero tolerance for unsupported versions of Windows. Third-party control
// is too entwined with the operating system. // is too entwined with the operating system.
if (!::IsWindows7OrGreater()) if (!::IsWindows7OrGreater())
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "base/files/file.h" #include "base/files/file.h"
#include "base/scoped_native_library.h" #include "base/scoped_native_library.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "chrome/install_static/install_util.h"
#include "chrome/install_static/product_install_details.h" #include "chrome/install_static/product_install_details.h"
#include "chrome_elf/third_party_dlls/logging_api.h" #include "chrome_elf/third_party_dlls/logging_api.h"
#include "chrome_elf/third_party_dlls/main.h" #include "chrome_elf/third_party_dlls/main.h"
...@@ -68,6 +69,7 @@ int main() { ...@@ -68,6 +69,7 @@ int main() {
return kThirdPartyAlreadyInitialized; return kThirdPartyAlreadyInitialized;
install_static::InitializeProductDetailsForPrimaryModule(); install_static::InitializeProductDetailsForPrimaryModule();
install_static::InitializeProcessType();
// Get the required arguments, path to blacklist file and test id to run. // Get the required arguments, path to blacklist file and test id to run.
if (argument_count < 3) if (argument_count < 3)
......
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