summaryrefslogtreecommitdiffstats
path: root/security/sandbox/chromium/base/win
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
commit6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch)
treea68f146d7fa01f0134297619fbe7e33db084e0aa /security/sandbox/chromium/base/win
parentInitial commit. (diff)
downloadthunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz
thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'security/sandbox/chromium/base/win')
-rw-r--r--security/sandbox/chromium/base/win/current_module.h17
-rw-r--r--security/sandbox/chromium/base/win/pe_image.cc652
-rw-r--r--security/sandbox/chromium/base/win/pe_image.h308
-rw-r--r--security/sandbox/chromium/base/win/scoped_handle.cc44
-rw-r--r--security/sandbox/chromium/base/win/scoped_handle.h184
-rw-r--r--security/sandbox/chromium/base/win/scoped_handle_verifier.cc238
-rw-r--r--security/sandbox/chromium/base/win/scoped_handle_verifier.h88
-rw-r--r--security/sandbox/chromium/base/win/scoped_process_information.cc107
-rw-r--r--security/sandbox/chromium/base/win/scoped_process_information.h75
-rw-r--r--security/sandbox/chromium/base/win/startup_information.cc59
-rw-r--r--security/sandbox/chromium/base/win/startup_information.h53
-rw-r--r--security/sandbox/chromium/base/win/static_constants.cc13
-rw-r--r--security/sandbox/chromium/base/win/static_constants.h21
-rw-r--r--security/sandbox/chromium/base/win/windows_types.h278
-rw-r--r--security/sandbox/chromium/base/win/windows_version.cc313
-rw-r--r--security/sandbox/chromium/base/win/windows_version.h187
16 files changed, 2637 insertions, 0 deletions
diff --git a/security/sandbox/chromium/base/win/current_module.h b/security/sandbox/chromium/base/win/current_module.h
new file mode 100644
index 0000000000..ee141db211
--- /dev/null
+++ b/security/sandbox/chromium/base/win/current_module.h
@@ -0,0 +1,17 @@
+// 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.
+
+#ifndef BASE_WIN_CURRENT_MODULE_H_
+#define BASE_WIN_CURRENT_MODULE_H_
+
+#include <windows.h>
+
+// http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx
+extern "C" IMAGE_DOS_HEADER __ImageBase;
+
+// Returns the HMODULE of the dll the macro was expanded in.
+// Only use in cc files, not in h files.
+#define CURRENT_MODULE() reinterpret_cast<HMODULE>(&__ImageBase)
+
+#endif // BASE_WIN_CURRENT_MODULE_H_
diff --git a/security/sandbox/chromium/base/win/pe_image.cc b/security/sandbox/chromium/base/win/pe_image.cc
new file mode 100644
index 0000000000..3d52964a24
--- /dev/null
+++ b/security/sandbox/chromium/base/win/pe_image.cc
@@ -0,0 +1,652 @@
+// Copyright (c) 2010 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 file implements PEImage, a generic class to manipulate PE files.
+// This file was adapted from GreenBorder's Code.
+
+#include "base/win/pe_image.h"
+
+#include <stddef.h>
+#include <set>
+#include <string>
+
+#include "base/no_destructor.h"
+#include "base/win/current_module.h"
+
+namespace base {
+namespace win {
+
+// Structure to perform imports enumerations.
+struct EnumAllImportsStorage {
+ PEImage::EnumImportsFunction callback;
+ PVOID cookie;
+};
+
+namespace {
+
+// PdbInfo Signature
+const DWORD kPdbInfoSignature = 'SDSR';
+
+// Compare two strings byte by byte on an unsigned basis.
+// if s1 == s2, return 0
+// if s1 < s2, return negative
+// if s1 > s2, return positive
+// Exception if inputs are invalid.
+int StrCmpByByte(LPCSTR s1, LPCSTR s2) {
+ while (*s1 != '\0' && *s1 == *s2) {
+ ++s1;
+ ++s2;
+ }
+
+ return (*reinterpret_cast<const unsigned char*>(s1) -
+ *reinterpret_cast<const unsigned char*>(s2));
+}
+
+struct PdbInfo {
+ DWORD Signature;
+ GUID Guid;
+ DWORD Age;
+ char PdbFileName[1];
+};
+
+#define LDR_IS_DATAFILE(handle) (((ULONG_PTR)(handle)) & (ULONG_PTR)1)
+#define LDR_IS_IMAGEMAPPING(handle) (((ULONG_PTR)(handle)) & (ULONG_PTR)2)
+#define LDR_IS_RESOURCE(handle) \
+ (LDR_IS_IMAGEMAPPING(handle) || LDR_IS_DATAFILE(handle))
+
+} // namespace
+
+// Callback used to enumerate imports. See EnumImportChunksFunction.
+bool ProcessImportChunk(const PEImage& image,
+ LPCSTR module,
+ PIMAGE_THUNK_DATA name_table,
+ PIMAGE_THUNK_DATA iat,
+ PVOID cookie) {
+ EnumAllImportsStorage& storage =
+ *reinterpret_cast<EnumAllImportsStorage*>(cookie);
+
+ return image.EnumOneImportChunk(storage.callback, module, name_table, iat,
+ storage.cookie);
+}
+
+// Callback used to enumerate delay imports. See EnumDelayImportChunksFunction.
+bool ProcessDelayImportChunk(const PEImage& image,
+ PImgDelayDescr delay_descriptor,
+ LPCSTR module,
+ PIMAGE_THUNK_DATA name_table,
+ PIMAGE_THUNK_DATA iat,
+ PVOID cookie) {
+ EnumAllImportsStorage& storage =
+ *reinterpret_cast<EnumAllImportsStorage*>(cookie);
+
+ return image.EnumOneDelayImportChunk(storage.callback, delay_descriptor,
+ module, name_table, iat, storage.cookie);
+}
+
+void PEImage::set_module(HMODULE module) {
+ module_ = module;
+}
+
+PIMAGE_DOS_HEADER PEImage::GetDosHeader() const {
+ return reinterpret_cast<PIMAGE_DOS_HEADER>(module_);
+}
+
+PIMAGE_NT_HEADERS PEImage::GetNTHeaders() const {
+ PIMAGE_DOS_HEADER dos_header = GetDosHeader();
+
+ return reinterpret_cast<PIMAGE_NT_HEADERS>(
+ reinterpret_cast<char*>(dos_header) + dos_header->e_lfanew);
+}
+
+PIMAGE_SECTION_HEADER PEImage::GetSectionHeader(UINT section) const {
+ PIMAGE_NT_HEADERS nt_headers = GetNTHeaders();
+ PIMAGE_SECTION_HEADER first_section = IMAGE_FIRST_SECTION(nt_headers);
+
+ if (section < nt_headers->FileHeader.NumberOfSections)
+ return first_section + section;
+ else
+ return nullptr;
+}
+
+WORD PEImage::GetNumSections() const {
+ return GetNTHeaders()->FileHeader.NumberOfSections;
+}
+
+DWORD PEImage::GetImageDirectoryEntrySize(UINT directory) const {
+ const IMAGE_DATA_DIRECTORY* const entry = GetDataDirectory(directory);
+ return entry ? entry->Size : 0;
+}
+
+PVOID PEImage::GetImageDirectoryEntryAddr(UINT directory) const {
+ const IMAGE_DATA_DIRECTORY* const entry = GetDataDirectory(directory);
+ return entry ? RVAToAddr(entry->VirtualAddress) : nullptr;
+}
+
+PIMAGE_SECTION_HEADER PEImage::GetImageSectionFromAddr(PVOID address) const {
+ PBYTE target = reinterpret_cast<PBYTE>(address);
+ PIMAGE_SECTION_HEADER section;
+
+ for (UINT i = 0; nullptr != (section = GetSectionHeader(i)); i++) {
+ // Don't use the virtual RVAToAddr.
+ PBYTE start =
+ reinterpret_cast<PBYTE>(PEImage::RVAToAddr(section->VirtualAddress));
+
+ DWORD size = section->Misc.VirtualSize;
+
+ if ((start <= target) && (start + size > target))
+ return section;
+ }
+
+ return nullptr;
+}
+
+PIMAGE_SECTION_HEADER PEImage::GetImageSectionHeaderByName(
+ LPCSTR section_name) const {
+ if (nullptr == section_name)
+ return nullptr;
+
+ PIMAGE_SECTION_HEADER ret = nullptr;
+ int num_sections = GetNumSections();
+
+ for (int i = 0; i < num_sections; i++) {
+ PIMAGE_SECTION_HEADER section = GetSectionHeader(i);
+ if (_strnicmp(reinterpret_cast<LPCSTR>(section->Name), section_name,
+ sizeof(section->Name)) == 0) {
+ ret = section;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+bool PEImage::GetDebugId(LPGUID guid,
+ LPDWORD age,
+ LPCSTR* pdb_filename,
+ size_t* pdb_filename_length) const {
+ DWORD debug_directory_size =
+ GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_DEBUG);
+ PIMAGE_DEBUG_DIRECTORY debug_directory =
+ reinterpret_cast<PIMAGE_DEBUG_DIRECTORY>(
+ GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_DEBUG));
+ if (!debug_directory)
+ return false;
+
+ size_t directory_count = debug_directory_size / sizeof(IMAGE_DEBUG_DIRECTORY);
+ for (size_t index = 0; index < directory_count; ++index) {
+ const IMAGE_DEBUG_DIRECTORY& entry = debug_directory[index];
+ if (entry.Type != IMAGE_DEBUG_TYPE_CODEVIEW)
+ continue; // Unsupported debugging info format.
+ if (entry.SizeOfData < sizeof(PdbInfo))
+ continue; // The data is too small to hold PDB info.
+ const PdbInfo* pdb_info =
+ reinterpret_cast<const PdbInfo*>(RVAToAddr(entry.AddressOfRawData));
+ if (!pdb_info)
+ continue; // The data is not present in a mapped section.
+ if (pdb_info->Signature != kPdbInfoSignature)
+ continue; // Unsupported PdbInfo signature
+
+ if (guid)
+ *guid = pdb_info->Guid;
+ if (age)
+ *age = pdb_info->Age;
+ if (pdb_filename) {
+ const size_t length_max =
+ entry.SizeOfData - offsetof(PdbInfo, PdbFileName);
+ const char* eos = pdb_info->PdbFileName;
+ for (const char* const end = pdb_info->PdbFileName + length_max;
+ eos < end && *eos; ++eos)
+ ;
+ *pdb_filename_length = eos - pdb_info->PdbFileName;
+ *pdb_filename = pdb_info->PdbFileName;
+ }
+ return true;
+ }
+ return false;
+}
+
+PDWORD PEImage::GetExportEntry(LPCSTR name) const {
+ PIMAGE_EXPORT_DIRECTORY exports = GetExportDirectory();
+
+ if (nullptr == exports)
+ return nullptr;
+
+ WORD ordinal = 0;
+ if (!GetProcOrdinal(name, &ordinal))
+ return nullptr;
+
+ PDWORD functions =
+ reinterpret_cast<PDWORD>(RVAToAddr(exports->AddressOfFunctions));
+
+ return functions + ordinal - exports->Base;
+}
+
+FARPROC PEImage::GetProcAddress(LPCSTR function_name) const {
+ PDWORD export_entry = GetExportEntry(function_name);
+ if (nullptr == export_entry)
+ return nullptr;
+
+ PBYTE function = reinterpret_cast<PBYTE>(RVAToAddr(*export_entry));
+
+ PBYTE exports = reinterpret_cast<PBYTE>(
+ GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_EXPORT));
+ DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_EXPORT);
+ if (!exports || !size)
+ return nullptr;
+
+ // Check for forwarded exports as a special case.
+ if (exports <= function && exports + size > function)
+ return reinterpret_cast<FARPROC>(-1);
+
+ return reinterpret_cast<FARPROC>(function);
+}
+
+bool PEImage::GetProcOrdinal(LPCSTR function_name, WORD* ordinal) const {
+ if (nullptr == ordinal)
+ return false;
+
+ PIMAGE_EXPORT_DIRECTORY exports = GetExportDirectory();
+
+ if (nullptr == exports)
+ return false;
+
+ if (IsOrdinal(function_name)) {
+ *ordinal = ToOrdinal(function_name);
+ } else {
+ PDWORD names = reinterpret_cast<PDWORD>(RVAToAddr(exports->AddressOfNames));
+ PDWORD lower = names;
+ PDWORD upper = names + exports->NumberOfNames;
+ int cmp = -1;
+
+ // Binary Search for the name.
+ while (lower != upper) {
+ PDWORD middle = lower + (upper - lower) / 2;
+ LPCSTR name = reinterpret_cast<LPCSTR>(RVAToAddr(*middle));
+
+ // This may be called by sandbox before MSVCRT dll loads, so can't use
+ // CRT function here.
+ cmp = StrCmpByByte(function_name, name);
+
+ if (cmp == 0) {
+ lower = middle;
+ break;
+ }
+
+ if (cmp > 0)
+ lower = middle + 1;
+ else
+ upper = middle;
+ }
+
+ if (cmp != 0)
+ return false;
+
+ PWORD ordinals =
+ reinterpret_cast<PWORD>(RVAToAddr(exports->AddressOfNameOrdinals));
+
+ *ordinal = ordinals[lower - names] + static_cast<WORD>(exports->Base);
+ }
+
+ return true;
+}
+
+bool PEImage::EnumSections(EnumSectionsFunction callback, PVOID cookie) const {
+ PIMAGE_NT_HEADERS nt_headers = GetNTHeaders();
+ UINT num_sections = nt_headers->FileHeader.NumberOfSections;
+ PIMAGE_SECTION_HEADER section = GetSectionHeader(0);
+
+ for (UINT i = 0; i < num_sections; i++, section++) {
+ PVOID section_start = RVAToAddr(section->VirtualAddress);
+ DWORD size = section->Misc.VirtualSize;
+
+ if (!callback(*this, section, section_start, size, cookie))
+ return false;
+ }
+
+ return true;
+}
+
+bool PEImage::EnumExports(EnumExportsFunction callback, PVOID cookie) const {
+ PVOID directory = GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_EXPORT);
+ DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_EXPORT);
+
+ // Check if there are any exports at all.
+ if (!directory || !size)
+ return true;
+
+ PIMAGE_EXPORT_DIRECTORY exports =
+ reinterpret_cast<PIMAGE_EXPORT_DIRECTORY>(directory);
+ UINT ordinal_base = exports->Base;
+ UINT num_funcs = exports->NumberOfFunctions;
+ UINT num_names = exports->NumberOfNames;
+ PDWORD functions =
+ reinterpret_cast<PDWORD>(RVAToAddr(exports->AddressOfFunctions));
+ PDWORD names = reinterpret_cast<PDWORD>(RVAToAddr(exports->AddressOfNames));
+ PWORD ordinals =
+ reinterpret_cast<PWORD>(RVAToAddr(exports->AddressOfNameOrdinals));
+
+ for (UINT count = 0; count < num_funcs; count++) {
+ PVOID func = RVAToAddr(functions[count]);
+ if (nullptr == func)
+ continue;
+
+ // Check for a name.
+ LPCSTR name = nullptr;
+ UINT hint;
+ for (hint = 0; hint < num_names; hint++) {
+ if (ordinals[hint] == count) {
+ name = reinterpret_cast<LPCSTR>(RVAToAddr(names[hint]));
+ break;
+ }
+ }
+
+ if (name == nullptr)
+ hint = 0;
+
+ // Check for forwarded exports.
+ LPCSTR forward = nullptr;
+ if (reinterpret_cast<char*>(func) >= reinterpret_cast<char*>(directory) &&
+ reinterpret_cast<char*>(func) <=
+ reinterpret_cast<char*>(directory) + size) {
+ forward = reinterpret_cast<LPCSTR>(func);
+ func = nullptr;
+ }
+
+ if (!callback(*this, ordinal_base + count, hint, name, func, forward,
+ cookie))
+ return false;
+ }
+
+ return true;
+}
+
+bool PEImage::EnumRelocs(EnumRelocsFunction callback, PVOID cookie) const {
+ PVOID directory = GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_BASERELOC);
+ DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_BASERELOC);
+
+ if (!directory || !size)
+ return true;
+
+ PIMAGE_BASE_RELOCATION base =
+ reinterpret_cast<PIMAGE_BASE_RELOCATION>(directory);
+ while (size >= sizeof(IMAGE_BASE_RELOCATION) && base->SizeOfBlock &&
+ size >= base->SizeOfBlock) {
+ PWORD reloc = reinterpret_cast<PWORD>(base + 1);
+ UINT num_relocs =
+ (base->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD);
+
+ for (UINT i = 0; i < num_relocs; i++, reloc++) {
+ WORD type = *reloc >> 12;
+ PVOID address = RVAToAddr(base->VirtualAddress + (*reloc & 0x0FFF));
+
+ if (!callback(*this, type, address, cookie))
+ return false;
+ }
+
+ size -= base->SizeOfBlock;
+ base = reinterpret_cast<PIMAGE_BASE_RELOCATION>(
+ reinterpret_cast<char*>(base) + base->SizeOfBlock);
+ }
+
+ return true;
+}
+
+bool PEImage::EnumImportChunks(EnumImportChunksFunction callback,
+ PVOID cookie,
+ LPCSTR target_module_name) const {
+ DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_IMPORT);
+ PIMAGE_IMPORT_DESCRIPTOR import = GetFirstImportChunk();
+
+ if (import == nullptr || size < sizeof(IMAGE_IMPORT_DESCRIPTOR))
+ return true;
+
+ for (; import->FirstThunk; import++) {
+ LPCSTR module_name = reinterpret_cast<LPCSTR>(RVAToAddr(import->Name));
+ PIMAGE_THUNK_DATA name_table = reinterpret_cast<PIMAGE_THUNK_DATA>(
+ RVAToAddr(import->OriginalFirstThunk));
+ PIMAGE_THUNK_DATA iat =
+ reinterpret_cast<PIMAGE_THUNK_DATA>(RVAToAddr(import->FirstThunk));
+
+ if (target_module_name == nullptr ||
+ (lstrcmpiA(module_name, target_module_name) == 0)) {
+ if (!callback(*this, module_name, name_table, iat, cookie))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool PEImage::EnumOneImportChunk(EnumImportsFunction callback,
+ LPCSTR module_name,
+ PIMAGE_THUNK_DATA name_table,
+ PIMAGE_THUNK_DATA iat,
+ PVOID cookie) const {
+ if (nullptr == name_table)
+ return false;
+
+ for (; name_table && name_table->u1.Ordinal; name_table++, iat++) {
+ LPCSTR name = nullptr;
+ WORD ordinal = 0;
+ WORD hint = 0;
+
+ if (IMAGE_SNAP_BY_ORDINAL(name_table->u1.Ordinal)) {
+ ordinal = static_cast<WORD>(IMAGE_ORDINAL32(name_table->u1.Ordinal));
+ } else {
+ PIMAGE_IMPORT_BY_NAME import = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>(
+ RVAToAddr(name_table->u1.ForwarderString));
+
+ hint = import->Hint;
+ name = reinterpret_cast<LPCSTR>(&import->Name);
+ }
+
+ if (!callback(*this, module_name, ordinal, name, hint, iat, cookie))
+ return false;
+ }
+
+ return true;
+}
+
+bool PEImage::EnumAllImports(EnumImportsFunction callback,
+ PVOID cookie,
+ LPCSTR target_module_name) const {
+ EnumAllImportsStorage temp = {callback, cookie};
+ return EnumImportChunks(ProcessImportChunk, &temp, target_module_name);
+}
+
+bool PEImage::EnumDelayImportChunks(EnumDelayImportChunksFunction callback,
+ PVOID cookie,
+ LPCSTR target_module_name) const {
+ PVOID directory =
+ GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT);
+ DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT);
+
+ if (!directory || !size)
+ return true;
+
+ PImgDelayDescr delay_descriptor = reinterpret_cast<PImgDelayDescr>(directory);
+ for (; delay_descriptor->rvaHmod; delay_descriptor++) {
+ PIMAGE_THUNK_DATA name_table;
+ PIMAGE_THUNK_DATA iat;
+ LPCSTR module_name;
+
+ // check if VC7-style imports, using RVAs instead of
+ // VC6-style addresses.
+ bool rvas = (delay_descriptor->grAttrs & dlattrRva) != 0;
+
+ if (rvas) {
+ module_name =
+ reinterpret_cast<LPCSTR>(RVAToAddr(delay_descriptor->rvaDLLName));
+ name_table = reinterpret_cast<PIMAGE_THUNK_DATA>(
+ RVAToAddr(delay_descriptor->rvaINT));
+ iat = reinterpret_cast<PIMAGE_THUNK_DATA>(
+ RVAToAddr(delay_descriptor->rvaIAT));
+ } else {
+ // Values in IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT are 32-bit, even on 64-bit
+ // platforms. See section 4.8 of PECOFF image spec rev 8.3.
+ module_name = reinterpret_cast<LPCSTR>(
+ static_cast<uintptr_t>(delay_descriptor->rvaDLLName));
+ name_table = reinterpret_cast<PIMAGE_THUNK_DATA>(
+ static_cast<uintptr_t>(delay_descriptor->rvaINT));
+ iat = reinterpret_cast<PIMAGE_THUNK_DATA>(
+ static_cast<uintptr_t>(delay_descriptor->rvaIAT));
+ }
+
+ if (target_module_name == nullptr ||
+ (lstrcmpiA(module_name, target_module_name) == 0)) {
+ if (target_module_name) {
+ // Ensure all imports are properly loaded for the target module so that
+ // the callback is operating on a fully-realized set of imports.
+ // This call only loads the imports for the module where this code is
+ // executing, so it is only helpful or meaningful to do this if the
+ // current module is the module whose IAT we are enumerating.
+ // Use the module_name as retrieved from the IAT because this method
+ // is case sensitive.
+ if (module_ == CURRENT_MODULE() && !LDR_IS_RESOURCE(module_)) {
+ static base::NoDestructor<std::set<std::string>> loaded_dlls;
+ // pair.second is true if this is a new element
+ if (loaded_dlls.get()->emplace(module_name).second)
+ ::__HrLoadAllImportsForDll(module_name);
+ }
+ }
+
+ if (!callback(*this, delay_descriptor, module_name, name_table, iat,
+ cookie))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool PEImage::EnumOneDelayImportChunk(EnumImportsFunction callback,
+ PImgDelayDescr delay_descriptor,
+ LPCSTR module_name,
+ PIMAGE_THUNK_DATA name_table,
+ PIMAGE_THUNK_DATA iat,
+ PVOID cookie) const {
+ for (; name_table->u1.Ordinal; name_table++, iat++) {
+ LPCSTR name = nullptr;
+ WORD ordinal = 0;
+ WORD hint = 0;
+
+ if (IMAGE_SNAP_BY_ORDINAL(name_table->u1.Ordinal)) {
+ ordinal = static_cast<WORD>(IMAGE_ORDINAL32(name_table->u1.Ordinal));
+ } else {
+ PIMAGE_IMPORT_BY_NAME import;
+ bool rvas = (delay_descriptor->grAttrs & dlattrRva) != 0;
+
+ if (rvas) {
+ import = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>(
+ RVAToAddr(name_table->u1.ForwarderString));
+ } else {
+ import = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>(
+ name_table->u1.ForwarderString);
+ }
+
+ hint = import->Hint;
+ name = reinterpret_cast<LPCSTR>(&import->Name);
+ }
+
+ if (!callback(*this, module_name, ordinal, name, hint, iat, cookie))
+ return false;
+ }
+
+ return true;
+}
+
+bool PEImage::EnumAllDelayImports(EnumImportsFunction callback,
+ PVOID cookie,
+ LPCSTR target_module_name) const {
+ EnumAllImportsStorage temp = {callback, cookie};
+ return EnumDelayImportChunks(ProcessDelayImportChunk, &temp,
+ target_module_name);
+}
+
+bool PEImage::VerifyMagic() const {
+ PIMAGE_DOS_HEADER dos_header = GetDosHeader();
+
+ if (dos_header->e_magic != IMAGE_DOS_SIGNATURE)
+ return false;
+
+ PIMAGE_NT_HEADERS nt_headers = GetNTHeaders();
+
+ if (nt_headers->Signature != IMAGE_NT_SIGNATURE)
+ return false;
+
+ if (nt_headers->FileHeader.SizeOfOptionalHeader !=
+ sizeof(IMAGE_OPTIONAL_HEADER))
+ return false;
+
+ if (nt_headers->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC)
+ return false;
+
+ return true;
+}
+
+bool PEImage::ImageRVAToOnDiskOffset(uintptr_t rva,
+ DWORD* on_disk_offset) const {
+ LPVOID address = RVAToAddr(rva);
+ return ImageAddrToOnDiskOffset(address, on_disk_offset);
+}
+
+bool PEImage::ImageAddrToOnDiskOffset(LPVOID address,
+ DWORD* on_disk_offset) const {
+ if (nullptr == address)
+ return false;
+
+ // Get the section that this address belongs to.
+ PIMAGE_SECTION_HEADER section_header = GetImageSectionFromAddr(address);
+ if (nullptr == section_header)
+ return false;
+
+ // Don't follow the virtual RVAToAddr, use the one on the base.
+ DWORD offset_within_section =
+ static_cast<DWORD>(reinterpret_cast<uintptr_t>(address)) -
+ static_cast<DWORD>(reinterpret_cast<uintptr_t>(
+ PEImage::RVAToAddr(section_header->VirtualAddress)));
+
+ *on_disk_offset = section_header->PointerToRawData + offset_within_section;
+ return true;
+}
+
+PVOID PEImage::RVAToAddr(uintptr_t rva) const {
+ if (rva == 0)
+ return nullptr;
+
+ return reinterpret_cast<char*>(module_) + rva;
+}
+
+const IMAGE_DATA_DIRECTORY* PEImage::GetDataDirectory(UINT directory) const {
+ PIMAGE_NT_HEADERS nt_headers = GetNTHeaders();
+
+ // Does the image report that it includes this directory entry?
+ if (directory >= nt_headers->OptionalHeader.NumberOfRvaAndSizes)
+ return nullptr;
+
+ // Is there space for this directory entry in the optional header?
+ if (nt_headers->FileHeader.SizeOfOptionalHeader <
+ (offsetof(IMAGE_OPTIONAL_HEADER, DataDirectory) +
+ (directory + 1) * sizeof(IMAGE_DATA_DIRECTORY))) {
+ return nullptr;
+ }
+
+ return &nt_headers->OptionalHeader.DataDirectory[directory];
+}
+
+PVOID PEImageAsData::RVAToAddr(uintptr_t rva) const {
+ if (rva == 0)
+ return nullptr;
+
+ PVOID in_memory = PEImage::RVAToAddr(rva);
+ DWORD disk_offset;
+
+ if (!ImageAddrToOnDiskOffset(in_memory, &disk_offset))
+ return nullptr;
+
+ return PEImage::RVAToAddr(disk_offset);
+}
+
+} // namespace win
+} // namespace base
diff --git a/security/sandbox/chromium/base/win/pe_image.h b/security/sandbox/chromium/base/win/pe_image.h
new file mode 100644
index 0000000000..cec959a940
--- /dev/null
+++ b/security/sandbox/chromium/base/win/pe_image.h
@@ -0,0 +1,308 @@
+// Copyright (c) 2010 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 file was adapted from GreenBorder's Code.
+// To understand what this class is about (for other than well known functions
+// as GetProcAddress), a good starting point is "An In-Depth Look into the
+// Win32 Portable Executable File Format" by Matt Pietrek:
+// http://msdn.microsoft.com/msdnmag/issues/02/02/PE/default.aspx
+
+#ifndef BASE_WIN_PE_IMAGE_H_
+#define BASE_WIN_PE_IMAGE_H_
+
+#include <windows.h>
+
+#include <stdint.h>
+
+#if defined(_WIN32_WINNT_WIN8)
+// The Windows 8 SDK defines FACILITY_VISUALCPP in winerror.h.
+#undef FACILITY_VISUALCPP
+#endif
+#include <delayimp.h>
+
+namespace base {
+namespace win {
+
+// This class is a wrapper for the Portable Executable File Format (PE).
+// Its main purpose is to provide an easy way to work with imports and exports
+// from a file, mapped in memory as image.
+class PEImage {
+ public:
+ // Callback to enumerate sections.
+ // cookie is the value passed to the enumerate method.
+ // Returns true to continue the enumeration.
+ using EnumSectionsFunction =
+ bool (*)(const PEImage&, PIMAGE_SECTION_HEADER, PVOID, DWORD, PVOID);
+
+ // Callback to enumerate exports.
+ // function is the actual address of the symbol. If forward is not null, it
+ // contains the dll and symbol to forward this export to. cookie is the value
+ // passed to the enumerate method.
+ // Returns true to continue the enumeration.
+ using EnumExportsFunction =
+ bool (*)(const PEImage&, DWORD, DWORD, LPCSTR, PVOID, LPCSTR, PVOID);
+
+ // Callback to enumerate import blocks.
+ // name_table and iat point to the imports name table and address table for
+ // this block. cookie is the value passed to the enumerate method.
+ // Returns true to continue the enumeration.
+ using EnumImportChunksFunction = bool (*)(const PEImage&,
+ LPCSTR,
+ PIMAGE_THUNK_DATA,
+ PIMAGE_THUNK_DATA,
+ PVOID);
+
+ // Callback to enumerate imports.
+ // module is the dll that exports this symbol. cookie is the value passed to
+ // the enumerate method.
+ // Returns true to continue the enumeration.
+ using EnumImportsFunction = bool (*)(const PEImage&,
+ LPCSTR,
+ DWORD,
+ LPCSTR,
+ DWORD,
+ PIMAGE_THUNK_DATA,
+ PVOID);
+
+ // Callback to enumerate delayed import blocks.
+ // module is the dll that exports this block of symbols. cookie is the value
+ // passed to the enumerate method.
+ // Returns true to continue the enumeration.
+ using EnumDelayImportChunksFunction = bool (*)(const PEImage&,
+ PImgDelayDescr,
+ LPCSTR,
+ PIMAGE_THUNK_DATA,
+ PIMAGE_THUNK_DATA,
+ PVOID);
+
+ // Callback to enumerate relocations.
+ // cookie is the value passed to the enumerate method.
+ // Returns true to continue the enumeration.
+ using EnumRelocsFunction = bool (*)(const PEImage&, WORD, PVOID, PVOID);
+
+ explicit PEImage(HMODULE module) : module_(module) {}
+ explicit PEImage(const void* module) {
+ module_ = reinterpret_cast<HMODULE>(const_cast<void*>(module));
+ }
+
+ virtual ~PEImage() = default;
+
+ // Gets the HMODULE for this object.
+ HMODULE module() const;
+
+ // Sets this object's HMODULE.
+ void set_module(HMODULE module);
+
+ // Checks if this symbol is actually an ordinal.
+ static bool IsOrdinal(LPCSTR name);
+
+ // Converts a named symbol to the corresponding ordinal.
+ static WORD ToOrdinal(LPCSTR name);
+
+ // Returns the DOS_HEADER for this PE.
+ PIMAGE_DOS_HEADER GetDosHeader() const;
+
+ // Returns the NT_HEADER for this PE.
+ PIMAGE_NT_HEADERS GetNTHeaders() const;
+
+ // Returns number of sections of this PE.
+ WORD GetNumSections() const;
+
+ // Returns the header for a given section.
+ // returns NULL if there is no such section.
+ PIMAGE_SECTION_HEADER GetSectionHeader(UINT section) const;
+
+ // Returns the size of a given directory entry or 0 if |directory| is out of
+ // bounds.
+ DWORD GetImageDirectoryEntrySize(UINT directory) const;
+
+ // Returns the address of a given directory entry or NULL if |directory| is
+ // out of bounds.
+ PVOID GetImageDirectoryEntryAddr(UINT directory) const;
+
+ // Returns the section header for a given address.
+ // Use: s = image.GetImageSectionFromAddr(a);
+ // Post: 's' is the section header of the section that contains 'a'
+ // or NULL if there is no such section.
+ PIMAGE_SECTION_HEADER GetImageSectionFromAddr(PVOID address) const;
+
+ // Returns the section header for a given section.
+ PIMAGE_SECTION_HEADER GetImageSectionHeaderByName(LPCSTR section_name) const;
+
+ // Returns the first block of imports.
+ PIMAGE_IMPORT_DESCRIPTOR GetFirstImportChunk() const;
+
+ // Returns the exports directory.
+ PIMAGE_EXPORT_DIRECTORY GetExportDirectory() const;
+
+ // Retrieves the contents of the image's CodeView debug entry, returning true
+ // if such an entry is found and is within a section mapped into the current
+ // process's memory. |guid|, |age|, and |pdb_filename| are each optional and
+ // may be NULL. |pdb_filename_length| is mandatory if |pdb_filename| is not
+ // NULL, as the latter is populated with a direct reference to a string in the
+ // image that is is not guaranteed to be terminated (note: informal
+ // documentation indicates that it should be terminated, but the data is
+ // untrusted). Furthermore, owing to its nature of being a string in the
+ // image, it is only valid while the image is mapped into the process, and the
+ // caller is not responsible for freeing it. |pdb_filename_length| is
+ // populated with the string length of |pdb_filename| (not including a
+ // terminator) and must be used rather than relying on |pdb_filename| being
+ // properly terminated.
+ bool GetDebugId(LPGUID guid,
+ LPDWORD age,
+ LPCSTR* pdb_filename,
+ size_t* pdb_filename_length) const;
+
+ // Returns a given export entry.
+ // Use: e = image.GetExportEntry(f);
+ // Pre: 'f' is either a zero terminated string or ordinal
+ // Post: 'e' is a pointer to the export directory entry
+ // that contains 'f's export RVA, or NULL if 'f'
+ // is not exported from this image
+ PDWORD GetExportEntry(LPCSTR name) const;
+
+ // Returns the address for a given exported symbol.
+ // Use: p = image.GetProcAddress(f);
+ // Pre: 'f' is either a zero terminated string or ordinal.
+ // Post: if 'f' is a non-forwarded export from image, 'p' is
+ // the exported function. If 'f' is a forwarded export
+ // then p is the special value -1. In this case
+ // RVAToAddr(*GetExportEntry) can be used to resolve
+ // the string that describes the forward.
+ FARPROC GetProcAddress(LPCSTR function_name) const;
+
+ // Retrieves the ordinal for a given exported symbol.
+ // Returns true if the symbol was found.
+ bool GetProcOrdinal(LPCSTR function_name, WORD* ordinal) const;
+
+ // Enumerates PE sections.
+ // cookie is a generic cookie to pass to the callback.
+ // Returns true on success.
+ bool EnumSections(EnumSectionsFunction callback, PVOID cookie) const;
+
+ // Enumerates PE exports.
+ // cookie is a generic cookie to pass to the callback.
+ // Returns true on success.
+ bool EnumExports(EnumExportsFunction callback, PVOID cookie) const;
+
+ // Enumerates PE imports.
+ // cookie is a generic cookie to pass to the callback.
+ // Returns true on success.
+ // Use |target_module_name| to ensure the callback is only invoked for the
+ // specified module.
+ bool EnumAllImports(EnumImportsFunction callback,
+ PVOID cookie,
+ LPCSTR target_module_name) const;
+
+ // Enumerates PE import blocks.
+ // cookie is a generic cookie to pass to the callback.
+ // Returns true on success.
+ // Use |target_module_name| to ensure the callback is only invoked for the
+ // specified module.
+ bool EnumImportChunks(EnumImportChunksFunction callback,
+ PVOID cookie,
+ LPCSTR target_module_name) const;
+
+ // Enumerates the imports from a single PE import block.
+ // cookie is a generic cookie to pass to the callback.
+ // Returns true on success.
+ bool EnumOneImportChunk(EnumImportsFunction callback,
+ LPCSTR module_name,
+ PIMAGE_THUNK_DATA name_table,
+ PIMAGE_THUNK_DATA iat,
+ PVOID cookie) const;
+
+ // Enumerates PE delay imports.
+ // cookie is a generic cookie to pass to the callback.
+ // Returns true on success.
+ // Use |target_module_name| to ensure the callback is only invoked for the
+ // specified module. If this parameter is non-null then all delayloaded
+ // imports are resolved when the target module is found.
+ bool EnumAllDelayImports(EnumImportsFunction callback,
+ PVOID cookie,
+ LPCSTR target_module_name) const;
+
+ // Enumerates PE delay import blocks.
+ // cookie is a generic cookie to pass to the callback.
+ // Returns true on success.
+ // Use |target_module_name| to ensure the callback is only invoked for the
+ // specified module. If this parameter is non-null then all delayloaded
+ // imports are resolved when the target module is found.
+ bool EnumDelayImportChunks(EnumDelayImportChunksFunction callback,
+ PVOID cookie,
+ LPCSTR target_module_name) const;
+
+ // Enumerates imports from a single PE delay import block.
+ // cookie is a generic cookie to pass to the callback.
+ // Returns true on success.
+ bool EnumOneDelayImportChunk(EnumImportsFunction callback,
+ PImgDelayDescr delay_descriptor,
+ LPCSTR module_name,
+ PIMAGE_THUNK_DATA name_table,
+ PIMAGE_THUNK_DATA iat,
+ PVOID cookie) const;
+
+ // Enumerates PE relocation entries.
+ // cookie is a generic cookie to pass to the callback.
+ // Returns true on success.
+ bool EnumRelocs(EnumRelocsFunction callback, PVOID cookie) const;
+
+ // Verifies the magic values on the PE file.
+ // Returns true if all values are correct.
+ bool VerifyMagic() const;
+
+ // Converts an rva value to the appropriate address.
+ virtual PVOID RVAToAddr(uintptr_t rva) const;
+
+ // Converts an rva value to an offset on disk.
+ // Returns true on success.
+ bool ImageRVAToOnDiskOffset(uintptr_t rva, DWORD* on_disk_offset) const;
+
+ // Converts an address to an offset on disk.
+ // Returns true on success.
+ bool ImageAddrToOnDiskOffset(LPVOID address, DWORD* on_disk_offset) const;
+
+ private:
+ // Returns a pointer to a data directory, or NULL if |directory| is out of
+ // range.
+ const IMAGE_DATA_DIRECTORY* GetDataDirectory(UINT directory) const;
+
+ HMODULE module_;
+};
+
+// This class is an extension to the PEImage class that allows working with PE
+// files mapped as data instead of as image file.
+class PEImageAsData : public PEImage {
+ public:
+ explicit PEImageAsData(HMODULE hModule) : PEImage(hModule) {}
+
+ PVOID RVAToAddr(uintptr_t rva) const override;
+};
+
+inline bool PEImage::IsOrdinal(LPCSTR name) {
+ return reinterpret_cast<uintptr_t>(name) <= 0xFFFF;
+}
+
+inline WORD PEImage::ToOrdinal(LPCSTR name) {
+ return static_cast<WORD>(reinterpret_cast<intptr_t>(name));
+}
+
+inline HMODULE PEImage::module() const {
+ return module_;
+}
+
+inline PIMAGE_IMPORT_DESCRIPTOR PEImage::GetFirstImportChunk() const {
+ return reinterpret_cast<PIMAGE_IMPORT_DESCRIPTOR>(
+ GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_IMPORT));
+}
+
+inline PIMAGE_EXPORT_DIRECTORY PEImage::GetExportDirectory() const {
+ return reinterpret_cast<PIMAGE_EXPORT_DIRECTORY>(
+ GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_EXPORT));
+}
+
+} // namespace win
+} // namespace base
+
+#endif // BASE_WIN_PE_IMAGE_H_
diff --git a/security/sandbox/chromium/base/win/scoped_handle.cc b/security/sandbox/chromium/base/win/scoped_handle.cc
new file mode 100644
index 0000000000..de6854591b
--- /dev/null
+++ b/security/sandbox/chromium/base/win/scoped_handle.cc
@@ -0,0 +1,44 @@
+// Copyright (c) 2012 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/win/scoped_handle.h"
+#include "base/win/scoped_handle_verifier.h"
+#include "base/win/windows_types.h"
+
+namespace base {
+namespace win {
+
+using base::win::internal::ScopedHandleVerifier;
+
+// Static.
+bool HandleTraits::CloseHandle(HANDLE handle) {
+ return ScopedHandleVerifier::Get()->CloseHandle(handle);
+}
+
+// Static.
+void VerifierTraits::StartTracking(HANDLE handle,
+ const void* owner,
+ const void* pc1,
+ const void* pc2) {
+ return ScopedHandleVerifier::Get()->StartTracking(handle, owner, pc1, pc2);
+}
+
+// Static.
+void VerifierTraits::StopTracking(HANDLE handle,
+ const void* owner,
+ const void* pc1,
+ const void* pc2) {
+ return ScopedHandleVerifier::Get()->StopTracking(handle, owner, pc1, pc2);
+}
+
+void DisableHandleVerifier() {
+ return ScopedHandleVerifier::Get()->Disable();
+}
+
+void OnHandleBeingClosed(HANDLE handle) {
+ return ScopedHandleVerifier::Get()->OnHandleBeingClosed(handle);
+}
+
+} // namespace win
+} // namespace base
diff --git a/security/sandbox/chromium/base/win/scoped_handle.h b/security/sandbox/chromium/base/win/scoped_handle.h
new file mode 100644
index 0000000000..02c2533649
--- /dev/null
+++ b/security/sandbox/chromium/base/win/scoped_handle.h
@@ -0,0 +1,184 @@
+// Copyright (c) 2012 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 BASE_WIN_SCOPED_HANDLE_H_
+#define BASE_WIN_SCOPED_HANDLE_H_
+
+#include "base/win/windows_types.h"
+
+#include "base/base_export.h"
+#include "base/compiler_specific.h"
+#include "base/gtest_prod_util.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/macros.h"
+
+// TODO(rvargas): remove this with the rest of the verifier.
+#if defined(COMPILER_MSVC)
+#include <intrin.h>
+#define BASE_WIN_GET_CALLER _ReturnAddress()
+#elif defined(COMPILER_GCC)
+#define BASE_WIN_GET_CALLER \
+ __builtin_extract_return_addr(__builtin_return_address(0))
+#endif
+
+namespace base {
+namespace win {
+
+// Generic wrapper for raw handles that takes care of closing handles
+// automatically. The class interface follows the style of
+// the ScopedFILE class with two additions:
+// - IsValid() method can tolerate multiple invalid handle values such as NULL
+// and INVALID_HANDLE_VALUE (-1) for Win32 handles.
+// - Set() (and the constructors and assignment operators that call it)
+// preserve the Windows LastError code. This ensures that GetLastError() can
+// be called after stashing a handle in a GenericScopedHandle object. Doing
+// this explicitly is necessary because of bug 528394 and VC++ 2015.
+template <class Traits, class Verifier>
+class GenericScopedHandle {
+ public:
+ using Handle = typename Traits::Handle;
+
+ GenericScopedHandle() : handle_(Traits::NullHandle()) {}
+
+ explicit GenericScopedHandle(Handle handle) : handle_(Traits::NullHandle()) {
+ Set(handle);
+ }
+
+ GenericScopedHandle(GenericScopedHandle&& other)
+ : handle_(Traits::NullHandle()) {
+ Set(other.Take());
+ }
+
+ ~GenericScopedHandle() { Close(); }
+
+ bool IsValid() const { return Traits::IsHandleValid(handle_); }
+
+ GenericScopedHandle& operator=(GenericScopedHandle&& other) {
+ DCHECK_NE(this, &other);
+ Set(other.Take());
+ return *this;
+ }
+
+ void Set(Handle handle) {
+ if (handle_ != handle) {
+ // Preserve old LastError to avoid bug 528394.
+ auto last_error = ::GetLastError();
+ Close();
+
+ if (Traits::IsHandleValid(handle)) {
+ handle_ = handle;
+ Verifier::StartTracking(handle, this, BASE_WIN_GET_CALLER,
+ GetProgramCounter());
+ }
+ ::SetLastError(last_error);
+ }
+ }
+
+ Handle Get() const { return handle_; }
+
+ // Transfers ownership away from this object.
+ Handle Take() WARN_UNUSED_RESULT {
+ Handle temp = handle_;
+ handle_ = Traits::NullHandle();
+ if (Traits::IsHandleValid(temp)) {
+ Verifier::StopTracking(temp, this, BASE_WIN_GET_CALLER,
+ GetProgramCounter());
+ }
+ return temp;
+ }
+
+ // Explicitly closes the owned handle.
+ void Close() {
+ if (Traits::IsHandleValid(handle_)) {
+ Verifier::StopTracking(handle_, this, BASE_WIN_GET_CALLER,
+ GetProgramCounter());
+
+ Traits::CloseHandle(handle_);
+ handle_ = Traits::NullHandle();
+ }
+ }
+
+ private:
+ FRIEND_TEST_ALL_PREFIXES(ScopedHandleTest, ActiveVerifierWrongOwner);
+ FRIEND_TEST_ALL_PREFIXES(ScopedHandleTest, ActiveVerifierUntrackedHandle);
+ Handle handle_;
+
+ DISALLOW_COPY_AND_ASSIGN(GenericScopedHandle);
+};
+
+#undef BASE_WIN_GET_CALLER
+
+// The traits class for Win32 handles that can be closed via CloseHandle() API.
+class HandleTraits {
+ public:
+ using Handle = HANDLE;
+
+ // Closes the handle.
+ static bool BASE_EXPORT CloseHandle(HANDLE handle);
+
+ // Returns true if the handle value is valid.
+ static bool IsHandleValid(HANDLE handle) {
+ return handle != nullptr && handle != INVALID_HANDLE_VALUE;
+ }
+
+ // Returns NULL handle value.
+ static HANDLE NullHandle() { return nullptr; }
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(HandleTraits);
+};
+
+// Do-nothing verifier.
+class DummyVerifierTraits {
+ public:
+ using Handle = HANDLE;
+
+ static void StartTracking(HANDLE handle,
+ const void* owner,
+ const void* pc1,
+ const void* pc2) {}
+ static void StopTracking(HANDLE handle,
+ const void* owner,
+ const void* pc1,
+ const void* pc2) {}
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(DummyVerifierTraits);
+};
+
+// Performs actual run-time tracking.
+class BASE_EXPORT VerifierTraits {
+ public:
+ using Handle = HANDLE;
+
+ static void StartTracking(HANDLE handle,
+ const void* owner,
+ const void* pc1,
+ const void* pc2);
+ static void StopTracking(HANDLE handle,
+ const void* owner,
+ const void* pc1,
+ const void* pc2);
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(VerifierTraits);
+};
+
+using ScopedHandle = GenericScopedHandle<HandleTraits, VerifierTraits>;
+
+// This function may be called by the embedder to disable the use of
+// VerifierTraits at runtime. It has no effect if DummyVerifierTraits is used
+// for ScopedHandle.
+BASE_EXPORT void DisableHandleVerifier();
+
+// This should be called whenever the OS is closing a handle, if extended
+// verification of improper handle closing is desired. If |handle| is being
+// tracked by the handle verifier and ScopedHandle is not the one closing it,
+// a CHECK is generated.
+BASE_EXPORT void OnHandleBeingClosed(HANDLE handle);
+} // namespace win
+} // namespace base
+
+#endif // BASE_WIN_SCOPED_HANDLE_H_
diff --git a/security/sandbox/chromium/base/win/scoped_handle_verifier.cc b/security/sandbox/chromium/base/win/scoped_handle_verifier.cc
new file mode 100644
index 0000000000..316606c0bf
--- /dev/null
+++ b/security/sandbox/chromium/base/win/scoped_handle_verifier.cc
@@ -0,0 +1,238 @@
+// Copyright 2018 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/win/scoped_handle_verifier.h"
+
+#include <windows.h>
+
+#include <stddef.h>
+
+#include <unordered_map>
+
+#include "base/debug/alias.h"
+#include "base/debug/stack_trace.h"
+#include "base/synchronization/lock_impl.h"
+#include "base/win/base_win_buildflags.h"
+#include "base/win/current_module.h"
+
+extern "C" {
+__declspec(dllexport) void* GetHandleVerifier();
+
+void* GetHandleVerifier() {
+ return base::win::internal::ScopedHandleVerifier::Get();
+}
+} // extern C
+
+namespace {
+
+base::win::internal::ScopedHandleVerifier* g_active_verifier = nullptr;
+using GetHandleVerifierFn = void* (*)();
+using HandleMap =
+ std::unordered_map<HANDLE,
+ base::win::internal::ScopedHandleVerifierInfo,
+ base::win::internal::HandleHash>;
+using NativeLock = base::internal::LockImpl;
+
+NativeLock* GetLock() {
+ static auto* native_lock = new NativeLock();
+ return native_lock;
+}
+
+// Simple automatic locking using a native critical section so it supports
+// recursive locking.
+class AutoNativeLock {
+ public:
+ explicit AutoNativeLock(NativeLock& lock) : lock_(lock) { lock_.Lock(); }
+
+ ~AutoNativeLock() { lock_.Unlock(); }
+
+ private:
+ NativeLock& lock_;
+ DISALLOW_COPY_AND_ASSIGN(AutoNativeLock);
+};
+
+} // namespace
+
+namespace base {
+namespace win {
+namespace internal {
+
+ScopedHandleVerifier::ScopedHandleVerifier(bool enabled)
+ : enabled_(enabled), lock_(GetLock()) {}
+
+// static
+ScopedHandleVerifier* ScopedHandleVerifier::Get() {
+ if (!g_active_verifier)
+ ScopedHandleVerifier::InstallVerifier();
+
+ return g_active_verifier;
+}
+
+bool CloseHandleWrapper(HANDLE handle) {
+ if (!::CloseHandle(handle))
+ // Making this DCHECK on non-Nighly as we are hitting this frequently,
+ // looks like we are closing handles twice somehow. See bug 1564899.
+#if defined(NIGHTLY_BUILD)
+ CHECK(false); // CloseHandle failed.
+#else
+ DCHECK(false); // CloseHandle failed.
+#endif
+ return true;
+}
+
+// Assigns the g_active_verifier global within the GetLock() lock.
+// If |existing_verifier| is non-null then |enabled| is ignored.
+void ThreadSafeAssignOrCreateScopedHandleVerifier(
+ ScopedHandleVerifier* existing_verifier,
+ bool enabled) {
+ AutoNativeLock lock(*GetLock());
+ // Another thread in this module might be trying to assign the global
+ // verifier, so check that within the lock here.
+ if (g_active_verifier)
+ return;
+ g_active_verifier =
+ existing_verifier ? existing_verifier : new ScopedHandleVerifier(enabled);
+}
+
+// static
+void ScopedHandleVerifier::InstallVerifier() {
+#if BUILDFLAG(SINGLE_MODULE_MODE_HANDLE_VERIFIER)
+ // Component build has one Active Verifier per module.
+ ThreadSafeAssignOrCreateScopedHandleVerifier(nullptr, true);
+#else
+ // If you are reading this, wondering why your process seems deadlocked, take
+ // a look at your DllMain code and remove things that should not be done
+ // there, like doing whatever gave you that nice windows handle you are trying
+ // to store in a ScopedHandle.
+ HMODULE main_module = ::GetModuleHandle(NULL);
+ GetHandleVerifierFn get_handle_verifier =
+ reinterpret_cast<GetHandleVerifierFn>(
+ ::GetProcAddress(main_module, "GetHandleVerifier"));
+
+ // This should only happen if running in a DLL is linked with base but the
+ // hosting EXE is not. In this case, create an ScopedHandleVerifier for the
+ // current
+ // module but leave it disabled.
+ if (!get_handle_verifier) {
+ ThreadSafeAssignOrCreateScopedHandleVerifier(nullptr, false);
+ return;
+ }
+
+ // Check if in the main module.
+ if (get_handle_verifier == GetHandleVerifier) {
+ ThreadSafeAssignOrCreateScopedHandleVerifier(nullptr, true);
+ return;
+ }
+
+ ScopedHandleVerifier* main_module_verifier =
+ reinterpret_cast<ScopedHandleVerifier*>(get_handle_verifier());
+
+ // Main module should always on-demand create a verifier.
+ DCHECK(main_module_verifier);
+
+ ThreadSafeAssignOrCreateScopedHandleVerifier(main_module_verifier, false);
+#endif
+}
+
+bool ScopedHandleVerifier::CloseHandle(HANDLE handle) {
+ if (!enabled_)
+ return CloseHandleWrapper(handle);
+
+ closing_.Set(true);
+ CloseHandleWrapper(handle);
+ closing_.Set(false);
+
+ return true;
+}
+
+// static
+NativeLock* ScopedHandleVerifier::GetLock() {
+ return ::GetLock();
+}
+
+void ScopedHandleVerifier::StartTracking(HANDLE handle,
+ const void* owner,
+ const void* pc1,
+ const void* pc2) {
+ if (!enabled_)
+ return;
+
+ // Grab the thread id before the lock.
+ DWORD thread_id = GetCurrentThreadId();
+
+ AutoNativeLock lock(*lock_);
+
+ ScopedHandleVerifierInfo handle_info = {owner, pc1, pc2,
+ base::debug::StackTrace(), thread_id};
+ std::pair<HANDLE, ScopedHandleVerifierInfo> item(handle, handle_info);
+ std::pair<HandleMap::iterator, bool> result = map_.insert(item);
+ if (!result.second) {
+ ScopedHandleVerifierInfo other = result.first->second;
+ base::debug::Alias(&other);
+ auto creation_stack = creation_stack_;
+ base::debug::Alias(&creation_stack);
+ CHECK(false); // Attempt to start tracking already tracked handle.
+ }
+}
+
+void ScopedHandleVerifier::StopTracking(HANDLE handle,
+ const void* owner,
+ const void* pc1,
+ const void* pc2) {
+ if (!enabled_)
+ return;
+
+ AutoNativeLock lock(*lock_);
+ HandleMap::iterator i = map_.find(handle);
+ if (i == map_.end()) {
+ auto creation_stack = creation_stack_;
+ base::debug::Alias(&creation_stack);
+ CHECK(false); // Attempting to close an untracked handle.
+ }
+
+ ScopedHandleVerifierInfo other = i->second;
+ if (other.owner != owner) {
+ base::debug::Alias(&other);
+ auto creation_stack = creation_stack_;
+ base::debug::Alias(&creation_stack);
+ CHECK(false); // Attempting to close a handle not owned by opener.
+ }
+
+ map_.erase(i);
+}
+
+void ScopedHandleVerifier::Disable() {
+ enabled_ = false;
+}
+
+void ScopedHandleVerifier::OnHandleBeingClosed(HANDLE handle) {
+ if (!enabled_)
+ return;
+
+ if (closing_.Get())
+ return;
+
+ AutoNativeLock lock(*lock_);
+ HandleMap::iterator i = map_.find(handle);
+ if (i == map_.end())
+ return;
+
+ ScopedHandleVerifierInfo other = i->second;
+ base::debug::Alias(&other);
+ auto creation_stack = creation_stack_;
+ base::debug::Alias(&creation_stack);
+ CHECK(false); // CloseHandle called on tracked handle.
+}
+
+HMODULE ScopedHandleVerifier::GetModule() const {
+ return CURRENT_MODULE();
+}
+
+HMODULE GetHandleVerifierModuleForTesting() {
+ return g_active_verifier->GetModule();
+}
+
+} // namespace internal
+} // namespace win
+} // namespace base
diff --git a/security/sandbox/chromium/base/win/scoped_handle_verifier.h b/security/sandbox/chromium/base/win/scoped_handle_verifier.h
new file mode 100644
index 0000000000..596e2c47eb
--- /dev/null
+++ b/security/sandbox/chromium/base/win/scoped_handle_verifier.h
@@ -0,0 +1,88 @@
+// Copyright 2018 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 BASE_WIN_SCOPED_HANDLE_VERIFIER_H_
+#define BASE_WIN_SCOPED_HANDLE_VERIFIER_H_
+
+#include "base/win/windows_types.h"
+
+#include <unordered_map>
+
+#include "base/base_export.h"
+#include "base/debug/stack_trace.h"
+#include "base/hash/hash.h"
+#include "base/synchronization/lock_impl.h"
+#include "base/threading/thread_local.h"
+
+namespace base {
+namespace win {
+namespace internal {
+
+struct HandleHash {
+ size_t operator()(const HANDLE& handle) const {
+ return base::FastHash(as_bytes(make_span(&handle, 1)));
+ }
+};
+
+struct ScopedHandleVerifierInfo {
+ const void* owner;
+ const void* pc1;
+ const void* pc2;
+ base::debug::StackTrace stack;
+ DWORD thread_id;
+};
+
+// Implements the actual object that is verifying handles for this process.
+// The active instance is shared across the module boundary but there is no
+// way to delete this object from the wrong side of it (or any side, actually).
+// We need [[clang::lto_visibility_public]] because instances of this class are
+// passed across module boundaries. This means different modules must have
+// compatible definitions of the class even when whole program optimization is
+// enabled - which is what this attribute accomplishes. The pragma stops MSVC
+// from emitting an unrecognized attribute warning.
+#pragma warning(push)
+#pragma warning(disable : 5030)
+class [[clang::lto_visibility_public]] ScopedHandleVerifier {
+#pragma warning(pop)
+ public:
+ explicit ScopedHandleVerifier(bool enabled);
+
+ // Retrieves the current verifier.
+ static ScopedHandleVerifier* Get();
+
+ // The methods required by HandleTraits. They are virtual because we need to
+ // forward the call execution to another module, instead of letting the
+ // compiler call the version that is linked in the current module.
+ virtual bool CloseHandle(HANDLE handle);
+ virtual void StartTracking(HANDLE handle, const void* owner, const void* pc1,
+ const void* pc2);
+ virtual void StopTracking(HANDLE handle, const void* owner, const void* pc1,
+ const void* pc2);
+ virtual void Disable();
+ virtual void OnHandleBeingClosed(HANDLE handle);
+ virtual HMODULE GetModule() const;
+
+ private:
+ ~ScopedHandleVerifier(); // Not implemented.
+
+ static base::internal::LockImpl* GetLock();
+ static void InstallVerifier();
+
+ base::debug::StackTrace creation_stack_;
+ bool enabled_;
+ base::ThreadLocalBoolean closing_;
+ base::internal::LockImpl* lock_;
+ std::unordered_map<HANDLE, ScopedHandleVerifierInfo, HandleHash> map_;
+ DISALLOW_COPY_AND_ASSIGN(ScopedHandleVerifier);
+};
+
+// This testing function returns the module that the ActiveVerifier concrete
+// implementation was instantiated in.
+BASE_EXPORT HMODULE GetHandleVerifierModuleForTesting();
+
+} // namespace internal
+} // namespace win
+} // namespace base
+
+#endif // BASE_WIN_SCOPED_HANDLE_VERIFIER_H_
diff --git a/security/sandbox/chromium/base/win/scoped_process_information.cc b/security/sandbox/chromium/base/win/scoped_process_information.cc
new file mode 100644
index 0000000000..d3024bb5e9
--- /dev/null
+++ b/security/sandbox/chromium/base/win/scoped_process_information.cc
@@ -0,0 +1,107 @@
+// Copyright (c) 2012 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/win/scoped_process_information.h"
+
+#include "base/logging.h"
+#include "base/win/scoped_handle.h"
+
+namespace base {
+namespace win {
+
+namespace {
+
+// Duplicates source into target, returning true upon success. |target| is
+// guaranteed to be untouched in case of failure. Succeeds with no side-effects
+// if source is NULL.
+bool CheckAndDuplicateHandle(HANDLE source, ScopedHandle* target) {
+ if (!source)
+ return true;
+
+ HANDLE temp = nullptr;
+ if (!::DuplicateHandle(::GetCurrentProcess(), source, ::GetCurrentProcess(),
+ &temp, 0, FALSE, DUPLICATE_SAME_ACCESS)) {
+ DWORD last_error = ::GetLastError();
+ DPLOG(ERROR) << "Failed to duplicate a handle " << last_error;
+ ::SetLastError(last_error);
+ return false;
+ }
+ target->Set(temp);
+ return true;
+}
+
+} // namespace
+
+ScopedProcessInformation::ScopedProcessInformation() = default;
+
+ScopedProcessInformation::ScopedProcessInformation(
+ const PROCESS_INFORMATION& process_info) {
+ Set(process_info);
+}
+
+ScopedProcessInformation::~ScopedProcessInformation() {
+ Close();
+}
+
+bool ScopedProcessInformation::IsValid() const {
+ return process_id_ || process_handle_.Get() || thread_id_ ||
+ thread_handle_.Get();
+}
+
+void ScopedProcessInformation::Close() {
+ process_handle_.Close();
+ thread_handle_.Close();
+ process_id_ = 0;
+ thread_id_ = 0;
+}
+
+void ScopedProcessInformation::Set(const PROCESS_INFORMATION& process_info) {
+ if (IsValid())
+ Close();
+
+ process_handle_.Set(process_info.hProcess);
+ thread_handle_.Set(process_info.hThread);
+ process_id_ = process_info.dwProcessId;
+ thread_id_ = process_info.dwThreadId;
+}
+
+bool ScopedProcessInformation::DuplicateFrom(
+ const ScopedProcessInformation& other) {
+ DCHECK(!IsValid()) << "target ScopedProcessInformation must be NULL";
+ DCHECK(other.IsValid()) << "source ScopedProcessInformation must be valid";
+
+ if (CheckAndDuplicateHandle(other.process_handle(), &process_handle_) &&
+ CheckAndDuplicateHandle(other.thread_handle(), &thread_handle_)) {
+ process_id_ = other.process_id();
+ thread_id_ = other.thread_id();
+ return true;
+ }
+
+ return false;
+}
+
+PROCESS_INFORMATION ScopedProcessInformation::Take() {
+ PROCESS_INFORMATION process_information = {};
+ process_information.hProcess = process_handle_.Take();
+ process_information.hThread = thread_handle_.Take();
+ process_information.dwProcessId = process_id();
+ process_information.dwThreadId = thread_id();
+ process_id_ = 0;
+ thread_id_ = 0;
+
+ return process_information;
+}
+
+HANDLE ScopedProcessInformation::TakeProcessHandle() {
+ process_id_ = 0;
+ return process_handle_.Take();
+}
+
+HANDLE ScopedProcessInformation::TakeThreadHandle() {
+ thread_id_ = 0;
+ return thread_handle_.Take();
+}
+
+} // namespace win
+} // namespace base
diff --git a/security/sandbox/chromium/base/win/scoped_process_information.h b/security/sandbox/chromium/base/win/scoped_process_information.h
new file mode 100644
index 0000000000..3b85d1bfab
--- /dev/null
+++ b/security/sandbox/chromium/base/win/scoped_process_information.h
@@ -0,0 +1,75 @@
+// Copyright (c) 2012 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 BASE_WIN_SCOPED_PROCESS_INFORMATION_H_
+#define BASE_WIN_SCOPED_PROCESS_INFORMATION_H_
+
+#include <windows.h>
+
+#include "base/base_export.h"
+#include "base/macros.h"
+#include "base/win/scoped_handle.h"
+
+namespace base {
+namespace win {
+
+// Manages the closing of process and thread handles from PROCESS_INFORMATION
+// structures. Allows clients to take ownership of either handle independently.
+class BASE_EXPORT ScopedProcessInformation {
+ public:
+ ScopedProcessInformation();
+ explicit ScopedProcessInformation(const PROCESS_INFORMATION& process_info);
+ ~ScopedProcessInformation();
+
+ // Returns true iff this instance is holding a thread and/or process handle.
+ bool IsValid() const;
+
+ // Closes the held thread and process handles, if any.
+ void Close();
+
+ // Populates this instance with the provided |process_info|.
+ void Set(const PROCESS_INFORMATION& process_info);
+
+ // Populates this instance with duplicate handles and the thread/process IDs
+ // from |other|. Returns false in case of failure, in which case this instance
+ // will be completely unpopulated.
+ bool DuplicateFrom(const ScopedProcessInformation& other);
+
+ // Transfers ownership of the held PROCESS_INFORMATION, if any, away from this
+ // instance.
+ PROCESS_INFORMATION Take();
+
+ // Transfers ownership of the held process handle, if any, away from this
+ // instance. Note that the related process_id will also be cleared.
+ HANDLE TakeProcessHandle();
+
+ // Transfers ownership of the held thread handle, if any, away from this
+ // instance. Note that the related thread_id will also be cleared.
+ HANDLE TakeThreadHandle();
+
+ // Returns the held process handle, if any, while retaining ownership.
+ HANDLE process_handle() const { return process_handle_.Get(); }
+
+ // Returns the held thread handle, if any, while retaining ownership.
+ HANDLE thread_handle() const { return thread_handle_.Get(); }
+
+ // Returns the held process id, if any.
+ DWORD process_id() const { return process_id_; }
+
+ // Returns the held thread id, if any.
+ DWORD thread_id() const { return thread_id_; }
+
+ private:
+ ScopedHandle process_handle_;
+ ScopedHandle thread_handle_;
+ DWORD process_id_ = 0;
+ DWORD thread_id_ = 0;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedProcessInformation);
+};
+
+} // namespace win
+} // namespace base
+
+#endif // BASE_WIN_SCOPED_PROCESS_INFORMATION_H_
diff --git a/security/sandbox/chromium/base/win/startup_information.cc b/security/sandbox/chromium/base/win/startup_information.cc
new file mode 100644
index 0000000000..a78508dcad
--- /dev/null
+++ b/security/sandbox/chromium/base/win/startup_information.cc
@@ -0,0 +1,59 @@
+// Copyright (c) 2012 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/win/startup_information.h"
+
+#include "base/logging.h"
+
+namespace base {
+namespace win {
+
+StartupInformation::StartupInformation() : startup_info_() {
+ startup_info_.StartupInfo.cb = sizeof(startup_info_);
+}
+
+StartupInformation::~StartupInformation() {
+ if (startup_info_.lpAttributeList) {
+ ::DeleteProcThreadAttributeList(startup_info_.lpAttributeList);
+ }
+}
+
+bool StartupInformation::InitializeProcThreadAttributeList(
+ DWORD attribute_count) {
+ if (startup_info_.StartupInfo.cb != sizeof(startup_info_) ||
+ startup_info_.lpAttributeList) {
+ return false;
+ }
+
+ SIZE_T size = 0;
+ ::InitializeProcThreadAttributeList(nullptr, attribute_count, 0, &size);
+ if (size == 0)
+ return false;
+
+ auto attribute_list = std::make_unique<char[]>(size);
+ auto* attribute_list_ptr =
+ reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST>(attribute_list.get());
+ if (!::InitializeProcThreadAttributeList(attribute_list_ptr, attribute_count,
+ 0, &size)) {
+ return false;
+ }
+
+ attribute_list_ = std::move(attribute_list);
+ startup_info_.lpAttributeList = attribute_list_ptr;
+
+ return true;
+}
+
+bool StartupInformation::UpdateProcThreadAttribute(DWORD_PTR attribute,
+ void* value,
+ size_t size) {
+ if (!startup_info_.lpAttributeList)
+ return false;
+ return !!::UpdateProcThreadAttribute(startup_info_.lpAttributeList, 0,
+ attribute, value, size, nullptr,
+ nullptr);
+}
+
+} // namespace win
+} // namespace base
diff --git a/security/sandbox/chromium/base/win/startup_information.h b/security/sandbox/chromium/base/win/startup_information.h
new file mode 100644
index 0000000000..7ef6965dd5
--- /dev/null
+++ b/security/sandbox/chromium/base/win/startup_information.h
@@ -0,0 +1,53 @@
+// Copyright (c) 2012 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 BASE_WIN_STARTUP_INFORMATION_H_
+#define BASE_WIN_STARTUP_INFORMATION_H_
+
+#include <windows.h>
+
+#include <stddef.h>
+
+#include <memory>
+
+#include "base/base_export.h"
+#include "base/macros.h"
+
+namespace base {
+namespace win {
+
+// Manages the lifetime of additional attributes in STARTUPINFOEX.
+class BASE_EXPORT StartupInformation {
+ public:
+ StartupInformation();
+
+ ~StartupInformation();
+
+ // Initialize the attribute list for the specified number of entries.
+ bool InitializeProcThreadAttributeList(DWORD attribute_count);
+
+ // Sets one entry in the initialized attribute list.
+ // |value| needs to live at least as long as the StartupInformation object
+ // this is called on.
+ bool UpdateProcThreadAttribute(DWORD_PTR attribute, void* value, size_t size);
+
+ LPSTARTUPINFOW startup_info() { return &startup_info_.StartupInfo; }
+ LPSTARTUPINFOW startup_info() const {
+ return const_cast<const LPSTARTUPINFOW>(&startup_info_.StartupInfo);
+ }
+
+ bool has_extended_startup_info() const {
+ return !!startup_info_.lpAttributeList;
+ }
+
+ private:
+ std::unique_ptr<char[]> attribute_list_;
+ STARTUPINFOEXW startup_info_;
+ DISALLOW_COPY_AND_ASSIGN(StartupInformation);
+};
+
+} // namespace win
+} // namespace base
+
+#endif // BASE_WIN_STARTUP_INFORMATION_H_
diff --git a/security/sandbox/chromium/base/win/static_constants.cc b/security/sandbox/chromium/base/win/static_constants.cc
new file mode 100644
index 0000000000..f9894a22bd
--- /dev/null
+++ b/security/sandbox/chromium/base/win/static_constants.cc
@@ -0,0 +1,13 @@
+// Copyright 2019 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/win/static_constants.h"
+
+namespace base {
+namespace win {
+
+const char kApplicationVerifierDllName[] = "verifier.dll";
+
+} // namespace win
+} // namespace base
diff --git a/security/sandbox/chromium/base/win/static_constants.h b/security/sandbox/chromium/base/win/static_constants.h
new file mode 100644
index 0000000000..98a631f7cf
--- /dev/null
+++ b/security/sandbox/chromium/base/win/static_constants.h
@@ -0,0 +1,21 @@
+// Copyright 2019 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.
+
+// Defines constants needed before imports (like base.dll) are fully resolved.
+// For example, constants defined here can be used by interceptions (i.e. hooks)
+// in the sandbox, which run before imports are resolved, and can therefore only
+// reference static variables.
+
+#ifndef BASE_WIN_STATIC_CONSTANTS_H_
+#define BASE_WIN_STATIC_CONSTANTS_H_
+
+namespace base {
+namespace win {
+
+extern const char kApplicationVerifierDllName[];
+
+} // namespace win
+} // namespace base
+
+#endif // BASE_WIN_STATIC_CONSTANTS_H_
diff --git a/security/sandbox/chromium/base/win/windows_types.h b/security/sandbox/chromium/base/win/windows_types.h
new file mode 100644
index 0000000000..9be05f3c25
--- /dev/null
+++ b/security/sandbox/chromium/base/win/windows_types.h
@@ -0,0 +1,278 @@
+// Copyright (c) 2014 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 file contains defines and typedefs that allow popular Windows types to
+// be used without the overhead of including windows.h.
+
+#ifndef BASE_WIN_WINDOWS_TYPES_H
+#define BASE_WIN_WINDOWS_TYPES_H
+
+// Needed for function prototypes.
+#if defined(__MINGW32__)
+// MinGW doesn't have this file yet, but we only need this define.
+// Bug 1552706 tracks removing this and the one below.
+#define _Releases_exclusive_lock_(lock)
+// MinGW doesn't appear to have this in specstrings.h either.
+#define _Post_equals_last_error_
+#else
+#include <concurrencysal.h>
+#endif
+#include <sal.h>
+#include <specstrings.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// typedef and define the most commonly used Windows integer types.
+
+typedef unsigned long DWORD;
+typedef long LONG;
+typedef __int64 LONGLONG;
+typedef unsigned __int64 ULONGLONG;
+
+#define VOID void
+typedef char CHAR;
+typedef short SHORT;
+typedef long LONG;
+typedef int INT;
+typedef unsigned int UINT;
+typedef unsigned int* PUINT;
+typedef void* LPVOID;
+typedef void* PVOID;
+typedef void* HANDLE;
+typedef int BOOL;
+typedef unsigned char BYTE;
+typedef BYTE BOOLEAN;
+typedef DWORD ULONG;
+typedef unsigned short WORD;
+typedef WORD UWORD;
+typedef WORD ATOM;
+
+#if defined(_WIN64)
+typedef __int64 INT_PTR, *PINT_PTR;
+typedef unsigned __int64 UINT_PTR, *PUINT_PTR;
+
+typedef __int64 LONG_PTR, *PLONG_PTR;
+typedef unsigned __int64 ULONG_PTR, *PULONG_PTR;
+#else
+typedef __w64 int INT_PTR, *PINT_PTR;
+typedef __w64 unsigned int UINT_PTR, *PUINT_PTR;
+
+typedef __w64 long LONG_PTR, *PLONG_PTR;
+typedef __w64 unsigned long ULONG_PTR, *PULONG_PTR;
+#endif
+
+typedef UINT_PTR WPARAM;
+typedef LONG_PTR LPARAM;
+typedef LONG_PTR LRESULT;
+#define LRESULT LONG_PTR
+typedef _Return_type_success_(return >= 0) long HRESULT;
+
+typedef ULONG_PTR SIZE_T, *PSIZE_T;
+typedef LONG_PTR SSIZE_T, *PSSIZE_T;
+
+typedef DWORD ACCESS_MASK;
+typedef ACCESS_MASK REGSAM;
+
+// As defined in guiddef.h.
+#ifndef _REFGUID_DEFINED
+#define _REFGUID_DEFINED
+#define REFGUID const GUID&
+#endif
+
+// Forward declare Windows compatible handles.
+
+#define CHROME_DECLARE_HANDLE(name) \
+ struct name##__; \
+ typedef struct name##__* name
+CHROME_DECLARE_HANDLE(HDESK);
+CHROME_DECLARE_HANDLE(HGLRC);
+CHROME_DECLARE_HANDLE(HICON);
+CHROME_DECLARE_HANDLE(HINSTANCE);
+CHROME_DECLARE_HANDLE(HKEY);
+CHROME_DECLARE_HANDLE(HKL);
+CHROME_DECLARE_HANDLE(HMENU);
+CHROME_DECLARE_HANDLE(HWINSTA);
+CHROME_DECLARE_HANDLE(HWND);
+#undef CHROME_DECLARE_HANDLE
+
+typedef LPVOID HINTERNET;
+typedef HINSTANCE HMODULE;
+typedef PVOID LSA_HANDLE;
+
+// Forward declare some Windows struct/typedef sets.
+
+typedef struct _OVERLAPPED OVERLAPPED;
+typedef struct tagMSG MSG, *PMSG, *NPMSG, *LPMSG;
+
+typedef struct _RTL_SRWLOCK RTL_SRWLOCK;
+typedef RTL_SRWLOCK SRWLOCK, *PSRWLOCK;
+
+typedef struct _GUID GUID;
+typedef GUID CLSID;
+
+typedef struct tagLOGFONTW LOGFONTW, *PLOGFONTW, *NPLOGFONTW, *LPLOGFONTW;
+typedef LOGFONTW LOGFONT;
+
+typedef struct _FILETIME FILETIME;
+
+typedef struct tagMENUITEMINFOW MENUITEMINFOW, MENUITEMINFO;
+
+typedef struct tagNMHDR NMHDR;
+
+typedef PVOID PSID;
+
+// Declare Chrome versions of some Windows structures. These are needed for
+// when we need a concrete type but don't want to pull in Windows.h. We can't
+// declare the Windows types so we declare our types and cast to the Windows
+// types in a few places.
+
+struct CHROME_SRWLOCK {
+ PVOID Ptr;
+};
+
+struct CHROME_CONDITION_VARIABLE {
+ PVOID Ptr;
+};
+
+// Define some commonly used Windows constants. Note that the layout of these
+// macros - including internal spacing - must be 100% consistent with windows.h.
+
+// clang-format off
+
+#ifndef INVALID_HANDLE_VALUE
+// Work around there being two slightly different definitions in the SDK.
+#define INVALID_HANDLE_VALUE ((HANDLE)(LONG_PTR)-1)
+#endif
+#define TLS_OUT_OF_INDEXES ((DWORD)0xFFFFFFFF)
+#define HTNOWHERE 0
+#define MAX_PATH 260
+#define CS_GLOBALCLASS 0x4000
+
+#define ERROR_SUCCESS 0L
+#define ERROR_FILE_NOT_FOUND 2L
+#define ERROR_ACCESS_DENIED 5L
+#define ERROR_INVALID_HANDLE 6L
+#define ERROR_SHARING_VIOLATION 32L
+#define ERROR_LOCK_VIOLATION 33L
+#define REG_BINARY ( 3ul )
+
+#define STATUS_PENDING ((DWORD )0x00000103L)
+#define STILL_ACTIVE STATUS_PENDING
+#define SUCCEEDED(hr) (((HRESULT)(hr)) >= 0)
+#define FAILED(hr) (((HRESULT)(hr)) < 0)
+
+#define HKEY_CLASSES_ROOT (( HKEY ) (ULONG_PTR)((LONG)0x80000000) )
+#define HKEY_LOCAL_MACHINE (( HKEY ) (ULONG_PTR)((LONG)0x80000002) )
+#define HKEY_CURRENT_USER (( HKEY ) (ULONG_PTR)((LONG)0x80000001) )
+#define KEY_QUERY_VALUE (0x0001)
+#define KEY_SET_VALUE (0x0002)
+#define KEY_CREATE_SUB_KEY (0x0004)
+#define KEY_ENUMERATE_SUB_KEYS (0x0008)
+#define KEY_NOTIFY (0x0010)
+#define KEY_CREATE_LINK (0x0020)
+#define KEY_WOW64_32KEY (0x0200)
+#define KEY_WOW64_64KEY (0x0100)
+#define KEY_WOW64_RES (0x0300)
+
+#define READ_CONTROL (0x00020000L)
+#define SYNCHRONIZE (0x00100000L)
+
+#define STANDARD_RIGHTS_READ (READ_CONTROL)
+#define STANDARD_RIGHTS_WRITE (READ_CONTROL)
+#define STANDARD_RIGHTS_ALL (0x001F0000L)
+
+#define KEY_READ ((STANDARD_RIGHTS_READ |\
+ KEY_QUERY_VALUE |\
+ KEY_ENUMERATE_SUB_KEYS |\
+ KEY_NOTIFY) \
+ & \
+ (~SYNCHRONIZE))
+
+
+#define KEY_WRITE ((STANDARD_RIGHTS_WRITE |\
+ KEY_SET_VALUE |\
+ KEY_CREATE_SUB_KEY) \
+ & \
+ (~SYNCHRONIZE))
+
+#define KEY_ALL_ACCESS ((STANDARD_RIGHTS_ALL |\
+ KEY_QUERY_VALUE |\
+ KEY_SET_VALUE |\
+ KEY_CREATE_SUB_KEY |\
+ KEY_ENUMERATE_SUB_KEYS |\
+ KEY_NOTIFY |\
+ KEY_CREATE_LINK) \
+ & \
+ (~SYNCHRONIZE))
+
+// clang-format on
+
+// Define some macros needed when prototyping Windows functions.
+
+#define DECLSPEC_IMPORT __declspec(dllimport)
+#define WINBASEAPI DECLSPEC_IMPORT
+#define WINUSERAPI DECLSPEC_IMPORT
+#define WINAPI __stdcall
+#define CALLBACK __stdcall
+
+// Needed for optimal lock performance.
+WINBASEAPI _Releases_exclusive_lock_(*SRWLock) VOID WINAPI
+ ReleaseSRWLockExclusive(_Inout_ PSRWLOCK SRWLock);
+
+// Needed to support protobuf's GetMessage macro magic.
+WINUSERAPI BOOL WINAPI GetMessageW(_Out_ LPMSG lpMsg,
+ _In_opt_ HWND hWnd,
+ _In_ UINT wMsgFilterMin,
+ _In_ UINT wMsgFilterMax);
+
+// Needed for thread_local_storage.h
+WINBASEAPI LPVOID WINAPI TlsGetValue(_In_ DWORD dwTlsIndex);
+
+// Needed for scoped_handle.h
+WINBASEAPI _Check_return_ _Post_equals_last_error_ DWORD WINAPI
+ GetLastError(VOID);
+
+WINBASEAPI VOID WINAPI SetLastError(_In_ DWORD dwErrCode);
+
+#ifdef __cplusplus
+}
+#endif
+
+// These macros are all defined by windows.h and are also used as the names of
+// functions in the Chromium code base. Add to this list as needed whenever
+// there is a Windows macro which causes a function call to be renamed. This
+// ensures that the same renaming will happen everywhere. Includes of this file
+// can be added wherever needed to ensure this consistent renaming.
+
+#define CopyFile CopyFileW
+#define CreateDirectory CreateDirectoryW
+#define CreateEvent CreateEventW
+#define CreateFile CreateFileW
+#define CreateService CreateServiceW
+#define DeleteFile DeleteFileW
+#define DispatchMessage DispatchMessageW
+#define DrawText DrawTextW
+#define FindFirstFile FindFirstFileW
+#define FindNextFile FindNextFileW
+#define GetComputerName GetComputerNameW
+#define GetCurrentDirectory GetCurrentDirectoryW
+#define GetCurrentTime() GetTickCount()
+#define GetFileAttributes GetFileAttributesW
+#define GetMessage GetMessageW
+#define GetUserName GetUserNameW
+#define LoadIcon LoadIconW
+#define LoadImage LoadImageW
+#define PostMessage PostMessageW
+#define RemoveDirectory RemoveDirectoryW
+#define ReplaceFile ReplaceFileW
+#define ReportEvent ReportEventW
+#define SendMessage SendMessageW
+#define SendMessageCallback SendMessageCallbackW
+#define SetCurrentDirectory SetCurrentDirectoryW
+#define StartService StartServiceW
+#define UpdateResource UpdateResourceW
+
+#endif // BASE_WIN_WINDOWS_TYPES_H
diff --git a/security/sandbox/chromium/base/win/windows_version.cc b/security/sandbox/chromium/base/win/windows_version.cc
new file mode 100644
index 0000000000..ef96f8796f
--- /dev/null
+++ b/security/sandbox/chromium/base/win/windows_version.cc
@@ -0,0 +1,313 @@
+// Copyright (c) 2012 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/win/windows_version.h"
+
+#include <windows.h>
+
+#include <memory>
+#include <tuple>
+#include <utility>
+
+#include "base/file_version_info_win.h"
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/no_destructor.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/win/registry.h"
+
+#if !defined(__clang__) && _MSC_FULL_VER < 191125507
+#error VS 2017 Update 3.2 or higher is required
+#endif
+
+#if !defined(NTDDI_WIN10_RS4)
+#error Windows 10.0.17134.0 SDK or higher required.
+#endif
+
+namespace base {
+namespace win {
+
+namespace {
+
+// The values under the CurrentVersion registry hive are mirrored under
+// the corresponding Wow6432 hive.
+constexpr wchar_t kRegKeyWindowsNTCurrentVersion[] =
+ L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion";
+
+// Returns the "UBR" (Windows 10 patch number) and "ReleaseId" (Windows 10
+// release number) from the registry. "UBR" is an undocumented value and will be
+// 0 if the value was not found. "ReleaseId" will be an empty string if the
+// value is not found.
+std::pair<int, std::string> GetVersionData() {
+ DWORD ubr = 0;
+ std::wstring release_id;
+ RegKey key;
+
+ if (key.Open(HKEY_LOCAL_MACHINE, kRegKeyWindowsNTCurrentVersion,
+ KEY_QUERY_VALUE) == ERROR_SUCCESS) {
+ key.ReadValueDW(L"UBR", &ubr);
+ key.ReadValue(L"ReleaseId", &release_id);
+ }
+
+ return std::make_pair(static_cast<int>(ubr), WideToUTF8(release_id));
+}
+
+const _SYSTEM_INFO& GetSystemInfoStorage() {
+ static const NoDestructor<_SYSTEM_INFO> system_info([] {
+ _SYSTEM_INFO info = {};
+ ::GetNativeSystemInfo(&info);
+ return info;
+ }());
+ return *system_info;
+}
+
+} // namespace
+
+// static
+OSInfo** OSInfo::GetInstanceStorage() {
+ // Note: we don't use the Singleton class because it depends on AtExitManager,
+ // and it's convenient for other modules to use this class without it.
+ static OSInfo* info = []() {
+ _OSVERSIONINFOEXW version_info = {sizeof(version_info)};
+ ::GetVersionEx(reinterpret_cast<_OSVERSIONINFOW*>(&version_info));
+
+ DWORD os_type = 0;
+ ::GetProductInfo(version_info.dwMajorVersion, version_info.dwMinorVersion,
+ 0, 0, &os_type);
+
+ return new OSInfo(version_info, GetSystemInfoStorage(), os_type);
+ }();
+
+ return &info;
+}
+
+// static
+OSInfo* OSInfo::GetInstance() {
+ return *GetInstanceStorage();
+}
+
+// static
+OSInfo::WindowsArchitecture OSInfo::GetArchitecture() {
+ switch (GetSystemInfoStorage().wProcessorArchitecture) {
+ case PROCESSOR_ARCHITECTURE_INTEL:
+ return X86_ARCHITECTURE;
+ case PROCESSOR_ARCHITECTURE_AMD64:
+ return X64_ARCHITECTURE;
+ case PROCESSOR_ARCHITECTURE_IA64:
+ return IA64_ARCHITECTURE;
+ case PROCESSOR_ARCHITECTURE_ARM64:
+ return ARM64_ARCHITECTURE;
+ default:
+ return OTHER_ARCHITECTURE;
+ }
+}
+
+OSInfo::OSInfo(const _OSVERSIONINFOEXW& version_info,
+ const _SYSTEM_INFO& system_info,
+ int os_type)
+ : version_(Version::PRE_XP),
+ wow64_status_(GetWOW64StatusForProcess(GetCurrentProcess())) {
+ version_number_.major = version_info.dwMajorVersion;
+ version_number_.minor = version_info.dwMinorVersion;
+ version_number_.build = version_info.dwBuildNumber;
+ std::tie(version_number_.patch, release_id_) = GetVersionData();
+ version_ = MajorMinorBuildToVersion(
+ version_number_.major, version_number_.minor, version_number_.build);
+ service_pack_.major = version_info.wServicePackMajor;
+ service_pack_.minor = version_info.wServicePackMinor;
+ service_pack_str_ = WideToUTF8(version_info.szCSDVersion);
+
+ processors_ = system_info.dwNumberOfProcessors;
+ allocation_granularity_ = system_info.dwAllocationGranularity;
+
+ if (version_info.dwMajorVersion == 6 || version_info.dwMajorVersion == 10) {
+ // Only present on Vista+.
+ switch (os_type) {
+ case PRODUCT_CLUSTER_SERVER:
+ case PRODUCT_DATACENTER_SERVER:
+ case PRODUCT_DATACENTER_SERVER_CORE:
+ case PRODUCT_ENTERPRISE_SERVER:
+ case PRODUCT_ENTERPRISE_SERVER_CORE:
+ case PRODUCT_ENTERPRISE_SERVER_IA64:
+ case PRODUCT_SMALLBUSINESS_SERVER:
+ case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM:
+ case PRODUCT_STANDARD_SERVER:
+ case PRODUCT_STANDARD_SERVER_CORE:
+ case PRODUCT_WEB_SERVER:
+ version_type_ = SUITE_SERVER;
+ break;
+ case PRODUCT_PROFESSIONAL:
+ case PRODUCT_ULTIMATE:
+ version_type_ = SUITE_PROFESSIONAL;
+ break;
+ case PRODUCT_ENTERPRISE:
+ case PRODUCT_ENTERPRISE_E:
+ case PRODUCT_ENTERPRISE_EVALUATION:
+ case PRODUCT_ENTERPRISE_N:
+ case PRODUCT_ENTERPRISE_N_EVALUATION:
+ case PRODUCT_ENTERPRISE_S:
+ case PRODUCT_ENTERPRISE_S_EVALUATION:
+ case PRODUCT_ENTERPRISE_S_N:
+ case PRODUCT_ENTERPRISE_S_N_EVALUATION:
+ case PRODUCT_BUSINESS:
+ case PRODUCT_BUSINESS_N:
+ version_type_ = SUITE_ENTERPRISE;
+ break;
+ case PRODUCT_EDUCATION:
+ case PRODUCT_EDUCATION_N:
+ version_type_ = SUITE_EDUCATION;
+ break;
+ case PRODUCT_HOME_BASIC:
+ case PRODUCT_HOME_PREMIUM:
+ case PRODUCT_STARTER:
+ default:
+ version_type_ = SUITE_HOME;
+ break;
+ }
+ } else if (version_info.dwMajorVersion == 5 &&
+ version_info.dwMinorVersion == 2) {
+ if (version_info.wProductType == VER_NT_WORKSTATION &&
+ system_info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) {
+ version_type_ = SUITE_PROFESSIONAL;
+ } else if (version_info.wSuiteMask & VER_SUITE_WH_SERVER) {
+ version_type_ = SUITE_HOME;
+ } else {
+ version_type_ = SUITE_SERVER;
+ }
+ } else if (version_info.dwMajorVersion == 5 &&
+ version_info.dwMinorVersion == 1) {
+ if (version_info.wSuiteMask & VER_SUITE_PERSONAL)
+ version_type_ = SUITE_HOME;
+ else
+ version_type_ = SUITE_PROFESSIONAL;
+ } else {
+ // Windows is pre XP so we don't care but pick a safe default.
+ version_type_ = SUITE_HOME;
+ }
+}
+
+OSInfo::~OSInfo() = default;
+
+Version OSInfo::Kernel32Version() const {
+ static const Version kernel32_version =
+ MajorMinorBuildToVersion(Kernel32BaseVersion().components()[0],
+ Kernel32BaseVersion().components()[1],
+ Kernel32BaseVersion().components()[2]);
+ return kernel32_version;
+}
+
+Version OSInfo::UcrtVersion() const {
+ auto ucrt_version_info = FileVersionInfoWin::CreateFileVersionInfoWin(
+ FilePath(FILE_PATH_LITERAL("ucrtbase.dll")));
+ if (ucrt_version_info) {
+ auto ucrt_components = ucrt_version_info->GetFileVersion().components();
+ if (ucrt_components.size() == 4) {
+ return MajorMinorBuildToVersion(ucrt_components[0], ucrt_components[1],
+ ucrt_components[2]);
+ }
+ }
+ return Version();
+}
+
+// Retrieve a version from kernel32. This is useful because when running in
+// compatibility mode for a down-level version of the OS, the file version of
+// kernel32 will still be the "real" version.
+base::Version OSInfo::Kernel32BaseVersion() const {
+ static const NoDestructor<base::Version> version([] {
+ std::unique_ptr<FileVersionInfoWin> file_version_info =
+ FileVersionInfoWin::CreateFileVersionInfoWin(
+ FilePath(FILE_PATH_LITERAL("kernel32.dll")));
+ if (!file_version_info) {
+ // crbug.com/912061: on some systems it seems kernel32.dll might be
+ // corrupted or not in a state to get version info. In this case try
+ // kernelbase.dll as a fallback.
+ file_version_info = FileVersionInfoWin::CreateFileVersionInfoWin(
+ FilePath(FILE_PATH_LITERAL("kernelbase.dll")));
+ }
+ CHECK(file_version_info);
+ return file_version_info->GetFileVersion();
+ }());
+ return *version;
+}
+
+std::string OSInfo::processor_model_name() {
+ if (processor_model_name_.empty()) {
+ const wchar_t kProcessorNameString[] =
+ L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0";
+ RegKey key(HKEY_LOCAL_MACHINE, kProcessorNameString, KEY_READ);
+ std::wstring value;
+ key.ReadValue(L"ProcessorNameString", &value);
+ processor_model_name_ = WideToUTF8(value);
+ }
+ return processor_model_name_;
+}
+
+// static
+OSInfo::WOW64Status OSInfo::GetWOW64StatusForProcess(HANDLE process_handle) {
+ BOOL is_wow64 = FALSE;
+ if (!::IsWow64Process(process_handle, &is_wow64))
+ return WOW64_UNKNOWN;
+ return is_wow64 ? WOW64_ENABLED : WOW64_DISABLED;
+}
+
+// With the exception of Server 2003, server variants are treated the same as
+// the corresponding workstation release.
+// static
+Version OSInfo::MajorMinorBuildToVersion(int major, int minor, int build) {
+ if (major == 10) {
+ if (build >= 19041)
+ return Version::WIN10_20H1;
+ if (build >= 18362)
+ return Version::WIN10_19H1;
+ if (build >= 17763)
+ return Version::WIN10_RS5;
+ if (build >= 17134)
+ return Version::WIN10_RS4;
+ if (build >= 16299)
+ return Version::WIN10_RS3;
+ if (build >= 15063)
+ return Version::WIN10_RS2;
+ if (build >= 14393)
+ return Version::WIN10_RS1;
+ if (build >= 10586)
+ return Version::WIN10_TH2;
+ return Version::WIN10;
+ }
+
+ if (major > 6) {
+ // Hitting this likely means that it's time for a >10 block above.
+ NOTREACHED() << major << "." << minor << "." << build;
+ return Version::WIN_LAST;
+ }
+
+ if (major == 6) {
+ switch (minor) {
+ case 0:
+ return Version::VISTA;
+ case 1:
+ return Version::WIN7;
+ case 2:
+ return Version::WIN8;
+ default:
+ DCHECK_EQ(minor, 3);
+ return Version::WIN8_1;
+ }
+ }
+
+ if (major == 5 && minor != 0) {
+ // Treat XP Pro x64, Home Server, and Server 2003 R2 as Server 2003.
+ return minor == 1 ? Version::XP : Version::SERVER_2003;
+ }
+
+ // Win 2000 or older.
+ return Version::PRE_XP;
+}
+
+Version GetVersion() {
+ return OSInfo::GetInstance()->version();
+}
+
+} // namespace win
+} // namespace base
diff --git a/security/sandbox/chromium/base/win/windows_version.h b/security/sandbox/chromium/base/win/windows_version.h
new file mode 100644
index 0000000000..08d6e274ef
--- /dev/null
+++ b/security/sandbox/chromium/base/win/windows_version.h
@@ -0,0 +1,187 @@
+// Copyright (c) 2012 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 BASE_WIN_WINDOWS_VERSION_H_
+#define BASE_WIN_WINDOWS_VERSION_H_
+
+#include <stddef.h>
+
+#include <string>
+
+#include "base/base_export.h"
+#include "base/gtest_prod_util.h"
+#include "base/macros.h"
+#include "base/version.h"
+
+using HANDLE = void*;
+struct _OSVERSIONINFOEXW;
+struct _SYSTEM_INFO;
+
+namespace base {
+namespace test {
+class ScopedOSInfoOverride;
+} // namespace test
+} // namespace base
+
+namespace base {
+namespace win {
+
+// The running version of Windows. This is declared outside OSInfo for
+// syntactic sugar reasons; see the declaration of GetVersion() below.
+// NOTE: Keep these in order so callers can do things like
+// "if (base::win::GetVersion() >= base::win::Version::VISTA) ...".
+//
+// This enum is used in metrics histograms, so they shouldn't be reordered or
+// removed. New values can be added before Version::WIN_LAST.
+enum class Version {
+ PRE_XP = 0, // Not supported.
+ XP = 1,
+ SERVER_2003 = 2, // Also includes XP Pro x64 and Server 2003 R2.
+ VISTA = 3, // Also includes Windows Server 2008.
+ WIN7 = 4, // Also includes Windows Server 2008 R2.
+ WIN8 = 5, // Also includes Windows Server 2012.
+ WIN8_1 = 6, // Also includes Windows Server 2012 R2.
+ WIN10 = 7, // Threshold 1: Version 1507, Build 10240.
+ WIN10_TH2 = 8, // Threshold 2: Version 1511, Build 10586.
+ WIN10_RS1 = 9, // Redstone 1: Version 1607, Build 14393.
+ WIN10_RS2 = 10, // Redstone 2: Version 1703, Build 15063.
+ WIN10_RS3 = 11, // Redstone 3: Version 1709, Build 16299.
+ WIN10_RS4 = 12, // Redstone 4: Version 1803, Build 17134.
+ WIN10_RS5 = 13, // Redstone 5: Version 1809, Build 17763.
+ WIN10_19H1 = 14, // 19H1: Version 1903, Build 18362.
+ WIN10_20H1 = 15, // 20H1: Version 2004, Build 19041.
+ // On edit, update tools\metrics\histograms\enums.xml "WindowsVersion" and
+ // "GpuBlacklistFeatureTestResultsWindows2".
+ WIN_LAST, // Indicates error condition.
+};
+
+// A rough bucketing of the available types of versions of Windows. This is used
+// to distinguish enterprise enabled versions from home versions and potentially
+// server versions. Keep these values in the same order, since they are used as
+// is for metrics histogram ids.
+enum VersionType {
+ SUITE_HOME = 0,
+ SUITE_PROFESSIONAL,
+ SUITE_SERVER,
+ SUITE_ENTERPRISE,
+ SUITE_EDUCATION,
+ SUITE_LAST,
+};
+
+// A singleton that can be used to query various pieces of information about the
+// OS and process state. Note that this doesn't use the base Singleton class, so
+// it can be used without an AtExitManager.
+class BASE_EXPORT OSInfo {
+ public:
+ struct VersionNumber {
+ int major;
+ int minor;
+ int build;
+ int patch;
+ };
+
+ struct ServicePack {
+ int major;
+ int minor;
+ };
+
+ // The processor architecture this copy of Windows natively uses. For
+ // example, given an x64-capable processor, we have three possibilities:
+ // 32-bit Chrome running on 32-bit Windows: X86_ARCHITECTURE
+ // 32-bit Chrome running on 64-bit Windows via WOW64: X64_ARCHITECTURE
+ // 64-bit Chrome running on 64-bit Windows: X64_ARCHITECTURE
+ enum WindowsArchitecture {
+ X86_ARCHITECTURE,
+ X64_ARCHITECTURE,
+ IA64_ARCHITECTURE,
+ ARM64_ARCHITECTURE,
+ OTHER_ARCHITECTURE,
+ };
+
+ // Whether a process is running under WOW64 (the wrapper that allows 32-bit
+ // processes to run on 64-bit versions of Windows). This will return
+ // 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,
+ };
+
+ static OSInfo* GetInstance();
+
+ // Separate from the rest of OSInfo so it can be used during early process
+ // initialization.
+ static WindowsArchitecture GetArchitecture();
+
+ // Like wow64_status(), but for the supplied handle instead of the current
+ // process. This doesn't touch member state, so you can bypass the singleton.
+ static WOW64Status GetWOW64StatusForProcess(HANDLE process_handle);
+
+ const Version& version() const { return version_; }
+ Version Kernel32Version() const;
+ Version UcrtVersion() const;
+ base::Version Kernel32BaseVersion() const;
+ // The next two functions return arrays of values, [major, minor(, build)].
+ const VersionNumber& version_number() const { return version_number_; }
+ const VersionType& version_type() const { return version_type_; }
+ const ServicePack& service_pack() const { return service_pack_; }
+ const std::string& service_pack_str() const { return service_pack_str_; }
+ const int& processors() const { return processors_; }
+ const size_t& allocation_granularity() const {
+ return allocation_granularity_;
+ }
+ const WOW64Status& wow64_status() const { return wow64_status_; }
+ std::string processor_model_name();
+ const std::string& release_id() const { return release_id_; }
+
+ private:
+ friend class base::test::ScopedOSInfoOverride;
+ FRIEND_TEST_ALL_PREFIXES(OSInfo, MajorMinorBuildToVersion);
+ static OSInfo** GetInstanceStorage();
+
+ OSInfo(const _OSVERSIONINFOEXW& version_info,
+ const _SYSTEM_INFO& system_info,
+ int os_type);
+ ~OSInfo();
+
+ // Returns a Version value for a given OS version tuple.
+ static Version MajorMinorBuildToVersion(int major, int minor, int build);
+
+ Version version_;
+ VersionNumber version_number_;
+ VersionType version_type_;
+ ServicePack service_pack_;
+
+ // Represents the version of the OS associated to a release of
+ // Windows 10. Each version may have different releases (such as patch
+ // updates). This is the identifier of the release.
+ // Example:
+ // Windows 10 Version 1809 (OS build 17763) has multiple releases
+ // (i.e. build 17763.1, build 17763.195, build 17763.379, ...).
+ // See https://docs.microsoft.com/en-us/windows/windows-10/release-information
+ // for more information.
+ std::string release_id_;
+
+ // A string, such as "Service Pack 3", that indicates the latest Service Pack
+ // installed on the system. If no Service Pack has been installed, the string
+ // is empty.
+ std::string service_pack_str_;
+ int processors_;
+ size_t allocation_granularity_;
+ WOW64Status wow64_status_;
+ std::string processor_model_name_;
+
+ DISALLOW_COPY_AND_ASSIGN(OSInfo);
+};
+
+// Because this is by far the most commonly-requested value from the above
+// singleton, we add a global-scope accessor here as syntactic sugar.
+BASE_EXPORT Version GetVersion();
+
+} // namespace win
+} // namespace base
+
+#endif // BASE_WIN_WINDOWS_VERSION_H_