Backed out 3 changesets (bug 1639030) for MDA failures in dom/media/test/test_eme_autoplay.html. CLOSED TREE

Backed out changeset e614d160ab92 (bug 1639030)
Backed out changeset e93c2e3b1e62 (bug 1639030)
Backed out changeset c40a82e96834 (bug 1639030)
This commit is contained in:
Dorel Luca 2020-07-06 16:16:42 +03:00
Родитель 6aa252b6bf
Коммит feebf13084
325 изменённых файлов: 13153 добавлений и 17703 удалений

Просмотреть файл

@ -15,6 +15,4 @@
#include "build/buildflag.h"
#define BUILDFLAG_INTERNAL_USE_TCMALLOC() (0)
#endif // BASE_ALLOCATOR_BUILDFLAGS_H_

Просмотреть файл

@ -1,22 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// This is a dummy version of base/debug/crash_logging.cc
#include "base/debug/crash_logging.h"
namespace base {
namespace debug {
CrashKeyString* AllocateCrashKeyString(const char name[],
CrashKeySize value_length) {
return nullptr;
}
void SetCrashKeyString(CrashKeyString* crash_key, base::StringPiece value) {}
} // namespace debug
} // namespace base

Просмотреть файл

@ -4,24 +4,18 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// This is a dummy version of Chromium source file base/debug/stack_trace.h
// to provide a dummy class StackTrace.
// This is a dummy version of Chromium source file base/debug/stack_trace.h.
// To provide a dummy class StackTrace required in base/win/scoped_handle.cc.
#ifndef BASE_DEBUG_STACK_TRACE_H_
#define BASE_DEBUG_STACK_TRACE_H_
#include <iosfwd>
namespace base {
namespace debug {
class BASE_EXPORT StackTrace {
public:
StackTrace() {};
#if !defined(__UCLIBC__) & !defined(_AIX)
void OutputToStream(std::ostream*) const {}
#endif
};
} // namespace debug

Просмотреть файл

@ -10,8 +10,6 @@
#ifndef BASE_FEATURE_LIST_H_
#define BASE_FEATURE_LIST_H_
#include "base/macros.h"
namespace base {
// Specifies whether a given feature is enabled or disabled by default.

Просмотреть файл

@ -7,6 +7,8 @@
#include "base/files/file_path.h"
#include "mozilla/Assertions.h"
namespace base {
using StringType = FilePath::StringType;
@ -16,41 +18,6 @@ namespace {
const FilePath::CharType kStringTerminator = FILE_PATH_LITERAL('\0');
// If this FilePath contains a drive letter specification, returns the
// position of the last character of the drive letter specification,
// otherwise returns npos. This can only be true on Windows, when a pathname
// begins with a letter followed by a colon. On other platforms, this always
// returns npos.
StringPieceType::size_type FindDriveLetter(StringPieceType path) {
#if defined(FILE_PATH_USES_DRIVE_LETTERS)
// This is dependent on an ASCII-based character set, but that's a
// reasonable assumption. iswalpha can be too inclusive here.
if (path.length() >= 2 && path[1] == L':' &&
((path[0] >= L'A' && path[0] <= L'Z') ||
(path[0] >= L'a' && path[0] <= L'z'))) {
return 1;
}
#endif // FILE_PATH_USES_DRIVE_LETTERS
return StringType::npos;
}
bool IsPathAbsolute(StringPieceType path) {
#if defined(FILE_PATH_USES_DRIVE_LETTERS)
StringType::size_type letter = FindDriveLetter(path);
if (letter != StringType::npos) {
// Look for a separator right after the drive specification.
return path.length() > letter + 1 &&
FilePath::IsSeparator(path[letter + 1]);
}
// Look for a pair of leading separators.
return path.length() > 1 &&
FilePath::IsSeparator(path[0]) && FilePath::IsSeparator(path[1]);
#else // FILE_PATH_USES_DRIVE_LETTERS
// Look for a separator in the first position.
return path.length() > 0 && FilePath::IsSeparator(path[0]);
#endif // FILE_PATH_USES_DRIVE_LETTERS
}
} // namespace
FilePath::FilePath() = default;
@ -70,148 +37,4 @@ FilePath& FilePath::operator=(const FilePath& that) = default;
FilePath& FilePath::operator=(FilePath&& that) = default;
// static
bool FilePath::IsSeparator(CharType character) {
for (size_t i = 0; i < kSeparatorsLength - 1; ++i) {
if (character == kSeparators[i]) {
return true;
}
}
return false;
}
// libgen's dirname and basename aren't guaranteed to be thread-safe and aren't
// guaranteed to not modify their input strings, and in fact are implemented
// differently in this regard on different platforms. Don't use them, but
// adhere to their behavior.
FilePath FilePath::DirName() const {
FilePath new_path(path_);
new_path.StripTrailingSeparatorsInternal();
// The drive letter, if any, always needs to remain in the output. If there
// is no drive letter, as will always be the case on platforms which do not
// support drive letters, letter will be npos, or -1, so the comparisons and
// resizes below using letter will still be valid.
StringType::size_type letter = FindDriveLetter(new_path.path_);
StringType::size_type last_separator =
new_path.path_.find_last_of(kSeparators, StringType::npos,
kSeparatorsLength - 1);
if (last_separator == StringType::npos) {
// path_ is in the current directory.
new_path.path_.resize(letter + 1);
} else if (last_separator == letter + 1) {
// path_ is in the root directory.
new_path.path_.resize(letter + 2);
} else if (last_separator == letter + 2 &&
IsSeparator(new_path.path_[letter + 1])) {
// path_ is in "//" (possibly with a drive letter); leave the double
// separator intact indicating alternate root.
new_path.path_.resize(letter + 3);
} else if (last_separator != 0) {
// path_ is somewhere else, trim the basename.
new_path.path_.resize(last_separator);
}
new_path.StripTrailingSeparatorsInternal();
if (!new_path.path_.length())
new_path.path_ = kCurrentDirectory;
return new_path;
}
FilePath FilePath::BaseName() const {
FilePath new_path(path_);
new_path.StripTrailingSeparatorsInternal();
// The drive letter, if any, is always stripped.
StringType::size_type letter = FindDriveLetter(new_path.path_);
if (letter != StringType::npos) {
new_path.path_.erase(0, letter + 1);
}
// Keep everything after the final separator, but if the pathname is only
// one character and it's a separator, leave it alone.
StringType::size_type last_separator =
new_path.path_.find_last_of(kSeparators, StringType::npos,
kSeparatorsLength - 1);
if (last_separator != StringType::npos &&
last_separator < new_path.path_.length() - 1) {
new_path.path_.erase(0, last_separator + 1);
}
return new_path;
}
FilePath FilePath::Append(StringPieceType component) const {
StringPieceType appended = component;
StringType without_nuls;
StringType::size_type nul_pos = component.find(kStringTerminator);
if (nul_pos != StringPieceType::npos) {
without_nuls = StringType(component.substr(0, nul_pos));
appended = StringPieceType(without_nuls);
}
DCHECK(!IsPathAbsolute(appended));
if (path_.compare(kCurrentDirectory) == 0 && !appended.empty()) {
// Append normally doesn't do any normalization, but as a special case,
// when appending to kCurrentDirectory, just return a new path for the
// component argument. Appending component to kCurrentDirectory would
// serve no purpose other than needlessly lengthening the path, and
// it's likely in practice to wind up with FilePath objects containing
// only kCurrentDirectory when calling DirName on a single relative path
// component.
return FilePath(appended);
}
FilePath new_path(path_);
new_path.StripTrailingSeparatorsInternal();
// Don't append a separator if the path is empty (indicating the current
// directory) or if the path component is empty (indicating nothing to
// append).
if (!appended.empty() && !new_path.path_.empty()) {
// Don't append a separator if the path still ends with a trailing
// separator after stripping (indicating the root directory).
if (!IsSeparator(new_path.path_.back())) {
// Don't append a separator if the path is just a drive letter.
if (FindDriveLetter(new_path.path_) + 1 != new_path.path_.length()) {
new_path.path_.append(1, kSeparators[0]);
}
}
}
new_path.path_.append(appended.data(), appended.size());
return new_path;
}
FilePath FilePath::Append(const FilePath& component) const {
return Append(component.value());
}
void FilePath::StripTrailingSeparatorsInternal() {
// If there is no drive letter, start will be 1, which will prevent stripping
// the leading separator if there is only one separator. If there is a drive
// letter, start will be set appropriately to prevent stripping the first
// separator following the drive letter, if a separator immediately follows
// the drive letter.
StringType::size_type start = FindDriveLetter(path_) + 2;
StringType::size_type last_stripped = StringType::npos;
for (StringType::size_type pos = path_.length();
pos > start && IsSeparator(path_[pos - 1]);
--pos) {
// If the string only has two separators and they're at the beginning,
// don't strip them, unless the string began with more than two separators.
if (pos != start + 1 || last_stripped == start + 2 ||
!IsSeparator(path_[start - 1])) {
path_.resize(pos - 1);
last_stripped = pos;
}
}
}
} // namespace base

Просмотреть файл

@ -1,20 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// This is a copy of a file that is generated by the chromium build, with
// only the build flags we require.
// Generated by build/write_buildflag_header.py
// From "//base:logging_buildflags"
#ifndef BASE_LOGGING_BUILDFLAGS_H_
#define BASE_LOGGING_BUILDFLAGS_H_
#include "build/buildflag.h"
#define BUILDFLAG_INTERNAL_ENABLE_LOG_ERROR_NOT_REACHED() (0)
#endif // BASE_LOGGING_BUILDFLAGS_H_

Просмотреть файл

@ -24,9 +24,9 @@ class BASE_EXPORT SharedMemoryTracker {
return instance;
}
void IncrementMemoryUsage(const SharedMemoryMapping& mapping) {};
void IncrementMemoryUsage(const SharedMemory& shared_memory) {};
void DecrementMemoryUsage(const SharedMemoryMapping& mapping) {};
void DecrementMemoryUsage(const SharedMemory& shared_memory) {};
private:
SharedMemoryTracker() {};

Просмотреть файл

@ -11,6 +11,7 @@
#ifndef BASE_METRICS_HISTOGRAM_MACROS_H_
#define BASE_METRICS_HISTOGRAM_MACROS_H_
#define UMA_HISTOGRAM_ENUMERATION(name, sample) do { } while (0)
#define UMA_HISTOGRAM_ENUMERATION(name, sample, enum_max) do { } while (0)
#define SCOPED_UMA_HISTOGRAM_TIMER(name) do { } while (0)
#endif // BASE_METRICS_HISTOGRAM_MACROS_H_

Просмотреть файл

@ -1,12 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// This is a cut down version of //base/observer_list.h
#ifndef BASE_OBSERVER_LIST_H_
#define BASE_OBSERVER_LIST_H_
#endif // BASE_OBSERVER_LIST_H_

Просмотреть файл

@ -1,25 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// This is a reduced version of Chromium's //base/process/launch.h
// to satisfy compiler.
#ifndef BASE_PROCESS_LAUNCH_H_
#define BASE_PROCESS_LAUNCH_H_
#include <vector>
#include "base/environment.h"
namespace base {
#if defined(OS_WIN)
typedef std::vector<HANDLE> HandlesToInheritVector;
#endif
} // namespace base
#endif // BASE_PROCESS_LAUNCH_H_

Просмотреть файл

@ -1,17 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "base/process/memory.h"
#include "mozilla/Assertions.h"
namespace base {
void TerminateBecauseOutOfMemory(size_t size) {
MOZ_CRASH("Hit base::TerminateBecauseOutOfMemory");
}
} // namespace base

Просмотреть файл

@ -35,8 +35,7 @@ namespace internal {
class BASE_EXPORT ScopedBlockingCallWithBaseSyncPrimitives {
public:
ScopedBlockingCallWithBaseSyncPrimitives(const Location& from_here,
BlockingType blocking_type) {}
ScopedBlockingCallWithBaseSyncPrimitives(BlockingType blocking_type) {};
~ScopedBlockingCallWithBaseSyncPrimitives() {};
};

Просмотреть файл

@ -330,30 +330,6 @@ DeriveAppContainerSidFromAppContainerName(
#define PROC_THREAD_ATTRIBUTE_ALL_APPLICATION_PACKAGES_POLICY \
ProcThreadAttributeValue (ProcThreadAttributeAllApplicationPackagesPolicy, FALSE, TRUE, FALSE)
//
// Define functions declared only when _WIN32_WINNT >= 0x0A00
//
WINBASEAPI
BOOL
WINAPI
IsWow64Process2(
_In_ HANDLE hProcess,
_Out_ USHORT* pProcessMachine,
_Out_opt_ USHORT* pNativeMachine
);
#endif // (_WIN32_WINNT < 0x0A00)
#if defined(__MINGW32__)
// winnt.h
#define THREAD_DYNAMIC_CODE_ALLOW 1 // Opt-out of dynamic code generation.
// Mingw uses an old version THREAD_INFORMATION_CLASS defined in winbase.h
// where ThreadDynamicCodePolicy does not exist.
#define ThreadDynamicCodePolicy static_cast<THREAD_INFORMATION_CLASS>(2)
#endif // defined(__MINGW32__)
#endif // (_WIN32_WINNT >= 0x0A00)
#endif // _SECURITY_SANDBOX_BASE_SHIM_SDKDECLS_H_

Просмотреть файл

@ -1,42 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// This is a partial implementation of Chromium's source file
// base/win/win_util.cc
#include "base/win/win_util.h"
#include "base/logging.h"
#include "base/strings/string_util.h"
namespace base {
namespace win {
std::wstring GetWindowObjectName(HANDLE handle) {
// Get the size of the name.
std::wstring object_name;
DWORD size = 0;
::GetUserObjectInformation(handle, UOI_NAME, nullptr, 0, &size);
if (!size) {
DPCHECK(false);
return object_name;
}
LOG_ASSERT(size % sizeof(wchar_t) == 0u);
// Query the name of the object.
if (!::GetUserObjectInformation(
handle, UOI_NAME, WriteInto(&object_name, size / sizeof(wchar_t)),
size, &size)) {
DPCHECK(false);
}
return object_name;
}
} // namespace win
} // namespace base

Просмотреть файл

@ -1,26 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// This is a partial implementation of Chromium's source file
// base/win/win_util.h
#ifndef BASE_WIN_WIN_UTIL_H_
#define BASE_WIN_WIN_UTIL_H_
#include <string>
#include "base/base_export.h"
namespace base {
namespace win {
// Returns the name of a desktop or a window station.
BASE_EXPORT std::wstring GetWindowObjectName(HANDLE handle);
} // namespace win
} // namespace base
#endif // BASE_WIN_WIN_UTIL_H_

Просмотреть файл

@ -30,5 +30,5 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/registry_policy.cc b/secu
// |access| with the new value.
NTSTATUS TranslateMaximumAllowed(OBJECT_ATTRIBUTES* obj_attributes,
DWORD* access) {
NtOpenKeyFunction NtOpenKey = nullptr;
NtOpenKeyFunction NtOpenKey = NULL;
ResolveNTFunctionPtr("NtOpenKey", &NtOpenKey);

Просмотреть файл

@ -132,7 +132,7 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/filesystem_interception.c
break;
@@ -227,32 +246,39 @@ TargetNtQueryAttributesFile(NtQueryAttri
ResultCode code = CrossCall(ipc, IpcTag::NTQUERYATTRIBUTESFILE, name.get(),
ResultCode code = CrossCall(ipc, IPC_NTQUERYATTRIBUTESFILE_TAG, name.get(),
attributes, file_info, &answer);
if (SBOX_ALL_OK != code)
@ -173,7 +173,7 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/filesystem_interception.c
break;
@@ -284,16 +310,20 @@ NTSTATUS WINAPI TargetNtQueryFullAttribu
CrossCallReturn answer = {0};
ResultCode code = CrossCall(ipc, IpcTag::NTQUERYFULLATTRIBUTESFILE,
ResultCode code = CrossCall(ipc, IPC_NTQUERYFULLATTRIBUTESFILE_TAG,
name.get(), attributes, file_info, &answer);
if (SBOX_ALL_OK != code)
@ -213,7 +213,7 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/filesystem_interception.c
break;
@@ -366,14 +398,15 @@ TargetNtSetInformationFile(NtSetInformat
ResultCode code =
CrossCall(ipc, IpcTag::NTSETINFO_RENAME, file, io_status_buffer,
CrossCall(ipc, IPC_NTSETINFO_RENAME_TAG, file, io_status_buffer,
file_info_buffer, length, file_info_class, &answer);
if (SBOX_ALL_OK != code)
@ -249,7 +249,7 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/handle_interception.cc b/
DWORD desired_access,
DWORD options) {
@@ -29,17 +30,19 @@ ResultCode DuplicateHandleProxy(HANDLE s
ResultCode code = CrossCall(ipc, IpcTag::DUPLICATEHANDLEPROXY,
ResultCode code = CrossCall(ipc, IPC_DUPLICATEHANDLEPROXY_TAG,
source_handle, target_process_id,
desired_access, options, &answer);
if (SBOX_ALL_OK != code)
@ -652,64 +652,6 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/registry_interception.cc
}
} // namespace sandbox
diff --git a/security/sandbox/chromium/sandbox/win/src/signed_interception.cc b/security/sandbox/chromium/sandbox/win/src/signed_interception.cc
--- a/security/sandbox/chromium/sandbox/win/src/signed_interception.cc
+++ b/security/sandbox/chromium/sandbox/win/src/signed_interception.cc
@@ -9,16 +9,17 @@
#include "sandbox/win/src/crosscall_client.h"
#include "sandbox/win/src/ipc_tags.h"
#include "sandbox/win/src/policy_params.h"
#include "sandbox/win/src/policy_target.h"
#include "sandbox/win/src/sandbox_factory.h"
#include "sandbox/win/src/sandbox_nt_util.h"
#include "sandbox/win/src/sharedmem_ipc_client.h"
#include "sandbox/win/src/target_services.h"
+#include "mozilla/sandboxing/sandboxLogging.h"
namespace sandbox {
NTSTATUS WINAPI
TargetNtCreateSection(NtCreateSectionFunction orig_CreateSection,
PHANDLE section_handle,
ACCESS_MASK desired_access,
POBJECT_ATTRIBUTES object_attributes,
@@ -37,16 +38,18 @@ TargetNtCreateSection(NtCreateSectionFun
break;
if (maximum_size)
break;
if (section_page_protection != PAGE_EXECUTE)
break;
if (allocation_attributes != SEC_IMAGE)
break;
+ mozilla::sandboxing::LogBlocked("NtCreateSection");
+
// IPC must be fully started.
void* memory = GetGlobalIPCMemory();
if (!memory)
break;
std::unique_ptr<wchar_t, NtAllocDeleter> path;
if (!NtGetPathFromHandle(file_handle, &path))
@@ -73,16 +76,17 @@ TargetNtCreateSection(NtCreateSectionFun
if (code != SBOX_ALL_OK)
break;
if (!NT_SUCCESS(answer.nt_status))
break;
__try {
*section_handle = answer.handle;
+ mozilla::sandboxing::LogAllowed("NtCreateSection");
return answer.nt_status;
} __except (EXCEPTION_EXECUTE_HANDLER) {
break;
}
} while (false);
// Fall back to the original API in all failure cases.
return orig_CreateSection(section_handle, desired_access, object_attributes,
diff --git a/security/sandbox/chromium/sandbox/win/src/sync_interception.cc b/security/sandbox/chromium/sandbox/win/src/sync_interception.cc
--- a/security/sandbox/chromium/sandbox/win/src/sync_interception.cc
+++ b/security/sandbox/chromium/sandbox/win/src/sync_interception.cc

Просмотреть файл

@ -14,14 +14,14 @@ https://hg.mozilla.org/mozilla-central/rev/0f64b24c40c4
diff --git a/security/sandbox/chromium/sandbox/win/src/filesystem_dispatcher.cc b/security/sandbox/chromium/sandbox/win/src/filesystem_dispatcher.cc
--- a/security/sandbox/chromium/sandbox/win/src/filesystem_dispatcher.cc
+++ b/security/sandbox/chromium/sandbox/win/src/filesystem_dispatcher.cc
@@ -213,16 +213,25 @@ bool FilesystemDispatcher::NtQueryAttrib
@@ -221,16 +221,25 @@ bool FilesystemDispatcher::NtQueryAttrib
params[FileName::BROKER] = ParamPickerMake(broker);
// To evaluate the policy we need to call back to the policy object. We
// are just middlemen in the operation since is the FileSystemPolicy which
// knows what to do.
EvalResult result =
policy_base_->EvalPolicy(IpcTag::NTQUERYATTRIBUTESFILE, params.GetBase());
policy_base_->EvalPolicy(IPC_NTQUERYATTRIBUTESFILE_TAG, params.GetBase());
+ // If the policies forbid access (any result other than ASK_BROKER),
+ // then check for user-granted access to file.
@ -40,14 +40,14 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/filesystem_dispatcher.cc
information, &nt_status)) {
ipc->return_info.nt_status = STATUS_ACCESS_DENIED;
return true;
@@ -253,16 +262,25 @@ bool FilesystemDispatcher::NtQueryFullAt
@@ -261,16 +270,25 @@ bool FilesystemDispatcher::NtQueryFullAt
params[FileName::BROKER] = ParamPickerMake(broker);
// To evaluate the policy we need to call back to the policy object. We
// are just middlemen in the operation since is the FileSystemPolicy which
// knows what to do.
EvalResult result = policy_base_->EvalPolicy(
IpcTag::NTQUERYFULLATTRIBUTESFILE, params.GetBase());
IPC_NTQUERYFULLATTRIBUTESFILE_TAG, params.GetBase());
+ // If the policies forbid access (any result other than ASK_BROKER),
+ // then check for user-granted access to file.
@ -66,14 +66,14 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/filesystem_dispatcher.cc
&nt_status)) {
ipc->return_info.nt_status = STATUS_ACCESS_DENIED;
return true;
@@ -306,16 +324,26 @@ bool FilesystemDispatcher::NtSetInformat
@@ -316,16 +334,26 @@ bool FilesystemDispatcher::NtSetInformat
params[FileName::BROKER] = ParamPickerMake(broker);
// To evaluate the policy we need to call back to the policy object. We
// are just middlemen in the operation since is the FileSystemPolicy which
// knows what to do.
EvalResult result =
policy_base_->EvalPolicy(IpcTag::NTSETINFO_RENAME, params.GetBase());
policy_base_->EvalPolicy(IPC_NTSETINFO_RENAME_TAG, params.GetBase());
+ // If the policies forbid access (any result other than ASK_BROKER),
+ // then check for user-granted write access to file. We only permit
@ -96,7 +96,7 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/filesystem_dispatcher.cc
diff --git a/security/sandbox/chromium/sandbox/win/src/filesystem_interception.cc b/security/sandbox/chromium/sandbox/win/src/filesystem_interception.cc
--- a/security/sandbox/chromium/sandbox/win/src/filesystem_interception.cc
+++ b/security/sandbox/chromium/sandbox/win/src/filesystem_interception.cc
@@ -227,19 +227,16 @@ TargetNtQueryAttributesFile(NtQueryAttri
@@ -223,19 +223,16 @@ NTSTATUS WINAPI TargetNtQueryAttributesF
sizeof(FILE_BASIC_INFORMATION));
uint32_t broker = BROKER_FALSE;
@ -105,18 +105,18 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/filesystem_interception.c
params[FileName::NAME] = ParamPickerMake(name_ptr);
params[FileName::BROKER] = ParamPickerMake(broker);
- if (!QueryBroker(IpcTag::NTQUERYATTRIBUTESFILE, params.GetBase()))
- if (!QueryBroker(IPC_NTQUERYATTRIBUTESFILE_TAG, params.GetBase()))
- break;
-
SharedMemIPCClient ipc(memory);
CrossCallReturn answer = {0};
ResultCode code = CrossCall(ipc, IpcTag::NTQUERYATTRIBUTESFILE, name.get(),
ResultCode code = CrossCall(ipc, IPC_NTQUERYATTRIBUTESFILE_TAG, name.get(),
attributes, file_info, &answer);
if (SBOX_ALL_OK != code)
break;
@@ -292,19 +289,16 @@ NTSTATUS WINAPI TargetNtQueryFullAttribu
@@ -290,19 +287,16 @@ NTSTATUS WINAPI TargetNtQueryFullAttribu
sizeof(FILE_NETWORK_OPEN_INFORMATION));
uint32_t broker = BROKER_FALSE;
@ -125,18 +125,18 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/filesystem_interception.c
params[FileName::NAME] = ParamPickerMake(name_ptr);
params[FileName::BROKER] = ParamPickerMake(broker);
- if (!QueryBroker(IpcTag::NTQUERYFULLATTRIBUTESFILE, params.GetBase()))
- if (!QueryBroker(IPC_NTQUERYFULLATTRIBUTESFILE_TAG, params.GetBase()))
- break;
-
SharedMemIPCClient ipc(memory);
CrossCallReturn answer = {0};
ResultCode code = CrossCall(ipc, IpcTag::NTQUERYFULLATTRIBUTESFILE,
ResultCode code = CrossCall(ipc, IPC_NTQUERYFULLATTRIBUTESFILE_TAG,
name.get(), attributes, file_info, &answer);
if (SBOX_ALL_OK != code)
break;
@@ -374,19 +368,16 @@ TargetNtSetInformationFile(NtSetInformat
@@ -369,19 +363,16 @@ NTSTATUS WINAPI TargetNtSetInformationFi
break;
uint32_t broker = BROKER_FALSE;
@ -145,7 +145,7 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/filesystem_interception.c
params[FileName::NAME] = ParamPickerMake(name_ptr);
params[FileName::BROKER] = ParamPickerMake(broker);
- if (!QueryBroker(IpcTag::NTSETINFO_RENAME, params.GetBase()))
- if (!QueryBroker(IPC_NTSETINFO_RENAME_TAG, params.GetBase()))
- break;
-
InOutCountedBuffer io_status_buffer(io_status, sizeof(IO_STATUS_BLOCK));

Просмотреть файл

@ -12,7 +12,7 @@ https://hg.mozilla.org/mozilla-central/rev/c70d06fa5302
diff --git a/security/sandbox/chromium/sandbox/win/src/win_utils.cc b/security/sandbox/chromium/sandbox/win/src/win_utils.cc
--- a/security/sandbox/chromium/sandbox/win/src/win_utils.cc
+++ b/security/sandbox/chromium/sandbox/win/src/win_utils.cc
@@ -194,61 +194,66 @@ bool ResolveRegistryName(std::wstring na
@@ -190,62 +190,67 @@ bool ResolveRegistryName(base::string16
return false;
}
@ -22,12 +22,12 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/win_utils.cc b/security/s
// \Device\HarddiskVolume0\some\foo\bar
// \??\HarddiskVolume0\some\foo\bar
+// \??\UNC\SERVER\Share\some\foo\bar
DWORD IsReparsePoint(const std::wstring& full_path) {
DWORD IsReparsePoint(const base::string16& full_path) {
// Check if it's a pipe. We can't query the attributes of a pipe.
if (IsPipe(full_path))
return ERROR_NOT_A_REPARSE_POINT;
std::wstring path;
base::string16 path;
bool nt_path = IsNTPath(full_path, &path);
bool has_drive = StartsWithDriveLetter(path);
bool is_device_path = IsDevicePath(path, &path);
@ -37,13 +37,13 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/win_utils.cc b/security/s
- bool added_implied_device = false;
if (!has_drive) {
- path = std::wstring(kNTDotPrefix) + path;
- path = base::string16(kNTDotPrefix) + path;
- added_implied_device = true;
+ // Add Win32 device namespace prefix, required for some Windows APIs.
+ path.insert(0, kNTDotPrefix);
}
- std::wstring::size_type last_pos = std::wstring::npos;
- base::string16::size_type last_pos = base::string16::npos;
- bool passed_once = false;
+ // Ensure that volume path matches start of path.
+ wchar_t vol_path[MAX_PATH];
@ -73,6 +73,7 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/win_utils.cc b/security/s
- (path.rfind(L'\\') == kNTDotPrefixLen - 1)) {
- break;
- }
NOTREACHED_NT();
return error;
}
} else if (FILE_ATTRIBUTE_REPARSE_POINT & attributes) {
@ -93,12 +94,12 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/win_utils.cc b/security/s
// we'll get from |handle| will be \device\harddiskvolume1\some\foo\bar.
bool SameObject(HANDLE handle, const wchar_t* full_path) {
// Check if it's a pipe.
@@ -258,63 +263,67 @@ bool SameObject(HANDLE handle, const wch
std::wstring actual_path;
@@ -256,63 +261,67 @@ bool SameObject(HANDLE handle, const wch
base::string16 actual_path;
if (!GetPathFromHandle(handle, &actual_path))
return false;
std::wstring path(full_path);
base::string16 path(full_path);
DCHECK_NT(!path.empty());
// This may end with a backslash.
@ -118,7 +119,7 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/win_utils.cc b/security/s
bool has_drive = StartsWithDriveLetter(path);
if (!has_drive && nt_path) {
std::wstring simple_actual_path;
base::string16 simple_actual_path;
- if (!IsDevicePath(actual_path, &simple_actual_path))
- return false;
-
@ -186,5 +187,5 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/win_utils.cc b/security/s
// Just make a best effort here. There are lots of corner cases that we're
// not expecting - and will fail to make long.
bool ConvertToLongPath(std::wstring* native_path,
const std::wstring* drive_letter) {
bool ConvertToLongPath(base::string16* native_path,
const base::string16* drive_letter) {

Просмотреть файл

@ -6,10 +6,32 @@
# Parent 5ef34aa8c8918649528048dd60907862a4355e29
Bug 1515088 Part 2: Set LoaderThreads to 1 in the RTL_USER_PROCESS_PARAMETERS structure on child process start-up. r=aklotz
diff --git a/security/sandbox/chromium/sandbox/win/src/nt_internals.h b/security/sandbox/chromium/sandbox/win/src/nt_internals.h
--- a/security/sandbox/chromium/sandbox/win/src/nt_internals.h
+++ b/security/sandbox/chromium/sandbox/win/src/nt_internals.h
@@ -312,16 +312,18 @@ typedef enum _PROCESSINFOCLASS {
// Partial definition only.
typedef struct _PEB {
BYTE InheritedAddressSpace;
BYTE ReadImageFileExecOptions;
BYTE BeingDebugged;
BYTE SpareBool;
PVOID Mutant;
PVOID ImageBaseAddress;
+ PVOID Ldr;
+ PVOID ProcessParameters;
} PEB, *PPEB;
typedef LONG KPRIORITY;
typedef struct _PROCESS_BASIC_INFORMATION {
union {
NTSTATUS ExitStatus;
PVOID padding_for_x64_0;
diff --git a/security/sandbox/chromium/sandbox/win/src/win_utils.cc b/security/sandbox/chromium/sandbox/win/src/win_utils.cc
--- a/security/sandbox/chromium/sandbox/win/src/win_utils.cc
+++ b/security/sandbox/chromium/sandbox/win/src/win_utils.cc
@@ -456,20 +456,21 @@ bool GetNtPathFromWin32Path(const std::w
@@ -453,20 +453,21 @@ bool GetNtPathFromWin32Path(const base::
bool rv = GetPathFromHandle(file, nt_path);
::CloseHandle(file);
return rv;
@ -33,7 +55,7 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/win_utils.cc b/security/s
::WriteProcessMemory(child_process, address, buffer, length, &written) &&
(length == written);
@@ -544,16 +545,40 @@ void* GetProcessBaseAddress(HANDLE proce
@@ -511,16 +512,40 @@ void* GetProcessBaseAddress(HANDLE proce
&bytes_read) ||
(sizeof(magic) != bytes_read)) {
return nullptr;
@ -51,7 +73,7 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/win_utils.cc b/security/s
+ // field so there is a, probably small, risk that it might change or move in
+ // the future. In order to slightly guard against that we only update if the
+ // value is currently 0.
+ auto processParameters = reinterpret_cast<uint8_t*>(peb.ProcessParameters);
+ uint8_t* processParameters = static_cast<uint8_t*>(peb.ProcessParameters);
+ const uint32_t loaderThreadsOffset = 0x40c;
+ uint32_t maxLoaderThreads = 0;
+ BOOL memoryRead = ::ReadProcessMemory(
@ -69,16 +91,16 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/win_utils.cc b/security/s
return base_address;
}
DWORD GetTokenInformation(HANDLE token,
TOKEN_INFORMATION_CLASS info_class,
std::unique_ptr<BYTE[]>* buffer) {
// Get the required buffer size.
DWORD size = 0;
}; // namespace sandbox
void ResolveNTFunctionPtr(const char* name, void* ptr) {
static volatile HMODULE ntdll = NULL;
diff --git a/security/sandbox/chromium/sandbox/win/src/win_utils.h b/security/sandbox/chromium/sandbox/win/src/win_utils.h
--- a/security/sandbox/chromium/sandbox/win/src/win_utils.h
+++ b/security/sandbox/chromium/sandbox/win/src/win_utils.h
@@ -111,17 +111,18 @@ HKEY GetReservedKeyFromName(const std::w
bool ResolveRegistryName(std::wstring name, std::wstring* resolved_name);
@@ -102,17 +102,18 @@ HKEY GetReservedKeyFromName(const base::
bool ResolveRegistryName(base::string16 name, base::string16* resolved_name);
// Writes |length| bytes from the provided |buffer| into the address space of
// |child_process|, at the specified |address|, preserving the original write
@ -90,10 +112,10 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/win_utils.h b/security/sa
+ size_t length,
+ DWORD writeProtection = PAGE_WRITECOPY);
// Allocates |buffer_bytes| in child (PAGE_READWRITE) and copies data
// from |local_buffer| in this process into |child|. |remote_buffer|
// contains the address in the chile. If a zero byte copy is
// requested |true| is returned and no allocation or copying is
// attempted. Returns false if allocation or copying fails. If
// copying fails, the allocation will be reversed.
bool CopyToChildMemory(HANDLE child,
// Returns true if the provided path points to a pipe.
bool IsPipe(const base::string16& path);
// Converts a NTSTATUS code to a Win32 error code.
DWORD GetLastErrorFromNtStatus(NTSTATUS status);
// Returns the address of the main exe module in memory taking in account

Просмотреть файл

@ -30,10 +30,10 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/filesystem_dispatcher.cc
FilesystemDispatcher::FilesystemDispatcher(PolicyBase* policy_base)
: policy_base_(policy_base) {
static const IPCCall create_params = {
{IpcTag::NTCREATEFILE,
{WCHAR_TYPE, UINT32_TYPE, UINT32_TYPE, UINT32_TYPE, UINT32_TYPE,
UINT32_TYPE, UINT32_TYPE}},
@@ -105,16 +107,26 @@ bool FilesystemDispatcher::NtCreateFile(
{IPC_NTCREATEFILE_TAG,
{WCHAR_TYPE,
UINT32_TYPE,
@@ -110,16 +112,26 @@ bool FilesystemDispatcher::NtCreateFile(
params[OpenFile::OPTIONS] = ParamPickerMake(create_options);
params[OpenFile::BROKER] = ParamPickerMake(broker);
@ -41,7 +41,7 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/filesystem_dispatcher.cc
// are just middlemen in the operation since is the FileSystemPolicy which
// knows what to do.
EvalResult result =
policy_base_->EvalPolicy(IpcTag::NTCREATEFILE, params.GetBase());
policy_base_->EvalPolicy(IPC_NTCREATEFILE_TAG, params.GetBase());
+
+ // If the policies forbid access (any result other than ASK_BROKER),
+ // then check for user-granted access to file.
@ -60,7 +60,7 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/filesystem_dispatcher.cc
file_attributes, share_access, create_disposition, create_options,
&handle, &nt_status, &io_information)) {
ipc->return_info.nt_status = STATUS_ACCESS_DENIED;
@@ -150,16 +162,26 @@ bool FilesystemDispatcher::NtOpenFile(IP
@@ -157,16 +169,26 @@ bool FilesystemDispatcher::NtOpenFile(IP
params[OpenFile::OPTIONS] = ParamPickerMake(open_options);
params[OpenFile::BROKER] = ParamPickerMake(broker);
@ -68,7 +68,7 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/filesystem_dispatcher.cc
// are just middlemen in the operation since is the FileSystemPolicy which
// knows what to do.
EvalResult result =
policy_base_->EvalPolicy(IpcTag::NTOPENFILE, params.GetBase());
policy_base_->EvalPolicy(IPC_NTOPENFILE_TAG, params.GetBase());
+
+ // If the policies forbid access (any result other than ASK_BROKER),
+ // then check for user-granted access to file.
@ -90,7 +90,7 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/filesystem_dispatcher.cc
diff --git a/security/sandbox/chromium/sandbox/win/src/filesystem_interception.cc b/security/sandbox/chromium/sandbox/win/src/filesystem_interception.cc
--- a/security/sandbox/chromium/sandbox/win/src/filesystem_interception.cc
+++ b/security/sandbox/chromium/sandbox/win/src/filesystem_interception.cc
@@ -75,19 +75,16 @@ NTSTATUS WINAPI TargetNtCreateFile(NtCre
@@ -70,19 +70,16 @@ NTSTATUS WINAPI TargetNtCreateFile(NtCre
CountedParameterSet<OpenFile> params;
const wchar_t* name_ptr = name.get();
params[OpenFile::NAME] = ParamPickerMake(name_ptr);
@ -99,7 +99,7 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/filesystem_interception.c
params[OpenFile::OPTIONS] = ParamPickerMake(options_uint32);
params[OpenFile::BROKER] = ParamPickerMake(broker);
- if (!QueryBroker(IpcTag::NTCREATEFILE, params.GetBase()))
- if (!QueryBroker(IPC_NTCREATEFILE_TAG, params.GetBase()))
- break;
-
SharedMemIPCClient ipc(memory);
@ -107,25 +107,25 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/filesystem_interception.c
// The following call must match in the parameters with
// FilesystemDispatcher::ProcessNtCreateFile.
ResultCode code =
CrossCall(ipc, IpcTag::NTCREATEFILE, name.get(), attributes,
CrossCall(ipc, IPC_NTCREATEFILE_TAG, name.get(), attributes,
desired_access_uint32, file_attributes, sharing, disposition,
options_uint32, &answer);
@@ -160,19 +157,16 @@ NTSTATUS WINAPI TargetNtOpenFile(NtOpenF
const wchar_t* name_ptr = name.get();
@@ -154,19 +151,16 @@ NTSTATUS WINAPI TargetNtOpenFile(NtOpenF
CountedParameterSet<OpenFile> params;
const wchar_t* name_ptr = name.get();
params[OpenFile::NAME] = ParamPickerMake(name_ptr);
params[OpenFile::ACCESS] = ParamPickerMake(desired_access_uint32);
params[OpenFile::DISPOSITION] = ParamPickerMake(disposition_uint32);
params[OpenFile::OPTIONS] = ParamPickerMake(options_uint32);
params[OpenFile::BROKER] = ParamPickerMake(broker);
- if (!QueryBroker(IpcTag::NTOPENFILE, params.GetBase()))
- if (!QueryBroker(IPC_NTOPENFILE_TAG, params.GetBase()))
- break;
-
SharedMemIPCClient ipc(memory);
CrossCallReturn answer = {0};
ResultCode code =
CrossCall(ipc, IpcTag::NTOPENFILE, name.get(), attributes,
CrossCall(ipc, IPC_NTOPENFILE_TAG, name.get(), attributes,
desired_access_uint32, sharing, options_uint32, &answer);
if (SBOX_ALL_OK != code)
break;

Просмотреть файл

@ -1,94 +0,0 @@
# HG changeset patch
# User Bob Owen <bobowencode@gmail.com>
# Date 1577387989 0
# Thu Dec 26 19:19:49 2019 +0000
# Node ID 32adf437117bdca54be4959813acbb604f65137f
# Parent 214214029beb6cca606e11ba519d11cc7dbb37af
Bug 1605867: Don't duplicate IPC shared memory when we might fail to launch the process correctly. r=handyman
Differential Revision: https://phabricator.services.mozilla.com/D58271
diff --git a/security/sandbox/chromium/sandbox/win/src/target_process.cc b/security/sandbox/chromium/sandbox/win/src/target_process.cc
--- a/security/sandbox/chromium/sandbox/win/src/target_process.cc
+++ b/security/sandbox/chromium/sandbox/win/src/target_process.cc
@@ -286,45 +286,28 @@ ResultCode TargetProcess::Init(Dispatche
shared_section_.Set(::CreateFileMappingW(INVALID_HANDLE_VALUE, nullptr,
PAGE_READWRITE | SEC_COMMIT, 0,
shared_mem_size, nullptr));
if (!shared_section_.IsValid()) {
*win_error = ::GetLastError();
return SBOX_ERROR_CREATE_FILE_MAPPING;
}
- DWORD access = FILE_MAP_READ | FILE_MAP_WRITE | SECTION_QUERY;
- HANDLE target_shared_section;
- if (!::DuplicateHandle(::GetCurrentProcess(), shared_section_.Get(),
- sandbox_process_info_.process_handle(),
- &target_shared_section, access, false, 0)) {
- *win_error = ::GetLastError();
- return SBOX_ERROR_DUPLICATE_SHARED_SECTION;
- }
-
void* shared_memory = ::MapViewOfFile(
shared_section_.Get(), FILE_MAP_WRITE | FILE_MAP_READ, 0, 0, 0);
if (!shared_memory) {
*win_error = ::GetLastError();
return SBOX_ERROR_MAP_VIEW_OF_SHARED_SECTION;
}
CopyPolicyToTarget(policy, shared_policy_size,
reinterpret_cast<char*>(shared_memory) + shared_IPC_size);
ResultCode ret;
// Set the global variables in the target. These are not used on the broker.
- g_shared_section = target_shared_section;
- ret = TransferVariable("g_shared_section", &g_shared_section,
- sizeof(g_shared_section));
- g_shared_section = nullptr;
- if (SBOX_ALL_OK != ret) {
- *win_error = ::GetLastError();
- return ret;
- }
g_shared_IPC_size = shared_IPC_size;
ret = TransferVariable("g_shared_IPC_size", &g_shared_IPC_size,
sizeof(g_shared_IPC_size));
g_shared_IPC_size = 0;
if (SBOX_ALL_OK != ret) {
*win_error = ::GetLastError();
return ret;
}
@@ -339,16 +322,34 @@ ResultCode TargetProcess::Init(Dispatche
ipc_server_.reset(new SharedMemIPCServer(
sandbox_process_info_.process_handle(),
sandbox_process_info_.process_id(), thread_pool_, ipc_dispatcher));
if (!ipc_server_->Init(shared_memory, shared_IPC_size, kIPCChannelSize))
return SBOX_ERROR_NO_SPACE;
+ DWORD access = FILE_MAP_READ | FILE_MAP_WRITE | SECTION_QUERY;
+ HANDLE target_shared_section;
+ if (!::DuplicateHandle(::GetCurrentProcess(), shared_section_.Get(),
+ sandbox_process_info_.process_handle(),
+ &target_shared_section, access, false, 0)) {
+ *win_error = ::GetLastError();
+ return SBOX_ERROR_DUPLICATE_SHARED_SECTION;
+ }
+
+ g_shared_section = target_shared_section;
+ ret = TransferVariable("g_shared_section", &g_shared_section,
+ sizeof(g_shared_section));
+ g_shared_section = nullptr;
+ if (SBOX_ALL_OK != ret) {
+ *win_error = ::GetLastError();
+ return ret;
+ }
+
// After this point we cannot use this handle anymore.
::CloseHandle(sandbox_process_info_.TakeThreadHandle());
return SBOX_ALL_OK;
}
void TargetProcess::Terminate() {
if (!sandbox_process_info_.IsValid())

Просмотреть файл

@ -5,4 +5,3 @@ consult_PermissionsService_for_file_access.patch
allow_flash_temporary_files.patch
arm64_set_LoaderThreads.patch
change_to_DCHECK_in_CloseHandleWrapper.patch
move_shared_memory_duplication_after_initialization.patch

Просмотреть файл

@ -17,11 +17,11 @@ Differential Revision: https://phabricator.services.mozilla.com/D29474
diff --git a/security/sandbox/chromium/sandbox/win/src/process_mitigations.cc b/security/sandbox/chromium/sandbox/win/src/process_mitigations.cc
--- a/security/sandbox/chromium/sandbox/win/src/process_mitigations.cc
+++ b/security/sandbox/chromium/sandbox/win/src/process_mitigations.cc
@@ -431,16 +431,21 @@ void ConvertProcessMitigationsToPolicy(M
@@ -400,16 +400,21 @@ void ConvertProcessMitigationsToPolicy(M
// Mitigations >= Win8.1:
//----------------------------------------------------------------------------
if (version >= base::win::Version::WIN8_1) {
if (version >= base::win::VERSION_WIN8_1) {
if (flags & MITIGATION_DYNAMIC_CODE_DISABLE) {
*policy_value_1 |=
PROCESS_CREATION_MITIGATION_POLICY_PROHIBIT_DYNAMIC_CODE_ALWAYS_ON;
@ -35,14 +35,14 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/process_mitigations.cc b/
// Mitigations >= Win10:
//----------------------------------------------------------------------------
if (version >= base::win::Version::WIN10) {
if (version >= base::win::VERSION_WIN10) {
if (flags & MITIGATION_NONSYSTEM_FONT_DISABLE) {
*policy_value_1 |=
PROCESS_CREATION_MITIGATION_POLICY_FONT_DISABLE_ALWAYS_ON;
diff --git a/security/sandbox/chromium/sandbox/win/src/security_level.h b/security/sandbox/chromium/sandbox/win/src/security_level.h
--- a/security/sandbox/chromium/sandbox/win/src/security_level.h
+++ b/security/sandbox/chromium/sandbox/win/src/security_level.h
@@ -282,11 +282,20 @@ const MitigationFlags MITIGATION_IMAGE_L
@@ -273,11 +273,20 @@ const MitigationFlags MITIGATION_IMAGE_L
const MitigationFlags MITIGATION_IMAGE_LOAD_PREFER_SYS32 = 0x00100000;
// Prevents hyperthreads from interfering with indirect branch predictions.

Просмотреть файл

@ -12,7 +12,7 @@ https://hg.mozilla.org/mozilla-central/rev/14374cd9497a
diff --git a/security/sandbox/chromium/sandbox/win/src/restricted_token_utils.cc b/security/sandbox/chromium/sandbox/win/src/restricted_token_utils.cc
--- a/security/sandbox/chromium/sandbox/win/src/restricted_token_utils.cc
+++ b/security/sandbox/chromium/sandbox/win/src/restricted_token_utils.cc
@@ -51,16 +51,17 @@ DWORD GetObjectSecurityDescriptor(HANDLE
@@ -51,16 +51,17 @@
} // namespace
@ -28,9 +28,9 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/restricted_token_utils.cc
if (lockdown_default_dacl)
restricted_token.SetLockdownDefaultDacl();
std::vector<std::wstring> privilege_exceptions;
std::vector<base::string16> privilege_exceptions;
std::vector<Sid> sid_exceptions;
@@ -73,19 +74,22 @@ DWORD CreateRestrictedToken(HANDLE effec
@@ -68,19 +69,22 @@ DWORD CreateRestrictedToken(TokenLevel s
deny_sids = false;
remove_privileges = false;
break;
@ -56,7 +56,7 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/restricted_token_utils.cc
sid_exceptions.push_back(WinWorldSid);
sid_exceptions.push_back(WinInteractiveSid);
sid_exceptions.push_back(WinAuthenticatedUserSid);
@@ -108,49 +112,57 @@ DWORD CreateRestrictedToken(HANDLE effec
@@ -93,49 +97,57 @@ DWORD CreateRestrictedToken(TokenLevel s
break;
}
case USER_INTERACTIVE: {
@ -133,7 +133,7 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/restricted_token_utils.cc
diff --git a/security/sandbox/chromium/sandbox/win/src/restricted_token_utils.h b/security/sandbox/chromium/sandbox/win/src/restricted_token_utils.h
--- a/security/sandbox/chromium/sandbox/win/src/restricted_token_utils.h
+++ b/security/sandbox/chromium/sandbox/win/src/restricted_token_utils.h
@@ -33,16 +33,17 @@ enum TokenType { IMPERSONATION = 0, PRIM
@@ -33,16 +33,17 @@ enum TokenType {
// If the function succeeds, the return value is ERROR_SUCCESS. If the
// function fails, the return value is the win32 error code corresponding to
// the error.
@ -154,7 +154,7 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/restricted_token_utils.h
diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_policy.h b/security/sandbox/chromium/sandbox/win/src/sandbox_policy.h
--- a/security/sandbox/chromium/sandbox/win/src/sandbox_policy.h
+++ b/security/sandbox/chromium/sandbox/win/src/sandbox_policy.h
@@ -101,16 +101,21 @@ class TargetPolicy {
@@ -95,16 +95,21 @@ class TargetPolicy {
virtual ResultCode SetTokenLevel(TokenLevel initial, TokenLevel lockdown) = 0;
// Returns the initial token level.
@ -179,7 +179,7 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_policy.h b/securi
diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc b/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc
--- a/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc
+++ b/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc
@@ -152,16 +152,20 @@ ResultCode PolicyBase::SetTokenLevel(Tok
@@ -149,16 +149,20 @@ ResultCode PolicyBase::SetTokenLevel(Tok
TokenLevel PolicyBase::GetInitialTokenLevel() const {
return initial_level_;
}
@ -200,7 +200,7 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc b/
ui_exceptions_ = ui_exceptions;
return SBOX_ALL_OK;
}
@@ -413,17 +417,18 @@ ResultCode PolicyBase::MakeJobObject(bas
@@ -402,17 +406,18 @@ ResultCode PolicyBase::MakeJobObject(bas
ResultCode PolicyBase::MakeTokens(base::win::ScopedHandle* initial,
base::win::ScopedHandle* lockdown,
@ -213,14 +213,14 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc b/
+ PRIMARY, lockdown_default_dacl_,
+ use_restricting_sids_, lockdown);
if (ERROR_SUCCESS != result)
return SBOX_ERROR_CANNOT_CREATE_RESTRICTED_TOKEN;
return SBOX_ERROR_GENERIC;
// If we're launching on the alternate desktop we need to make sure the
// integrity label on the object is no higher than the sandboxed process's
// integrity level. So, we lower the label on the desktop process if it's
// not already low enough for our process.
if (use_alternate_desktop_ && integrity_level_ != INTEGRITY_LEVEL_LAST) {
@@ -482,17 +487,18 @@ ResultCode PolicyBase::MakeTokens(base::
@@ -466,17 +471,18 @@ ResultCode PolicyBase::MakeTokens(base::
}
}
@ -233,7 +233,7 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc b/
+ IMPERSONATION, lockdown_default_dacl_,
+ use_restricting_sids_, initial);
if (ERROR_SUCCESS != result)
return SBOX_ERROR_CANNOT_CREATE_RESTRICTED_IMP_TOKEN;
return SBOX_ERROR_GENERIC;
return SBOX_ALL_OK;
}
@ -243,7 +243,7 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc b/
diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.h b/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.h
--- a/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.h
+++ b/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.h
@@ -41,16 +41,17 @@ class PolicyBase final : public TargetPo
@@ -37,16 +37,17 @@ class PolicyBase final : public TargetPo
PolicyBase();
// TargetPolicy:
@ -257,11 +257,11 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.h b/s
JobLevel GetJobLevel() const override;
ResultCode SetJobMemoryLimit(size_t memory_limit) override;
ResultCode SetAlternateDesktop(bool alternate_winstation) override;
std::wstring GetAlternateDesktop() const override;
base::string16 GetAlternateDesktop() const override;
ResultCode CreateAlternateDesktop(bool alternate_winstation) override;
void DestroyAlternateDesktop() override;
ResultCode SetIntegrityLevel(IntegrityLevel integrity_level) override;
@@ -134,16 +135,17 @@ class PolicyBase final : public TargetPo
@@ -122,16 +123,17 @@ class PolicyBase final : public TargetPo
// The policy takes ownership of them.
typedef std::list<TargetProcess*> TargetSet;
TargetSet targets_;

Просмотреть файл

@ -1,461 +0,0 @@
# HG changeset patch
# User Bob Owen <bobowencode@gmail.com>
# Date 1584045580 0
# Thu Mar 12 20:39:40 2020 +0000
# Node ID c996dbc3e3663fb372feb8e171562e86b09583b6
# Parent f96efa1d9f5c676c0ee8fd80044a494258eff3d3
Bug 1557282 Part 1: Take chromium commit c1ce57ea5d31208af589b4839390a44ab20b0c8f. r=handyman,gcp
This adds AddRestrictingRandomSid feature, which fixes our issues with
SetLockdownDefaultDacl, apart from when we are running from a network drive.
Differential Revision: https://phabricator.services.mozilla.com/D66610
diff --git a/security/sandbox/chromium/sandbox/win/src/restricted_token.cc b/security/sandbox/chromium/sandbox/win/src/restricted_token.cc
--- a/security/sandbox/chromium/sandbox/win/src/restricted_token.cc
+++ b/security/sandbox/chromium/sandbox/win/src/restricted_token.cc
@@ -141,16 +141,24 @@ DWORD RestrictedToken::GetRestrictedToke
} else {
// Modify the default dacl on the token to contain Restricted.
if (!AddSidToDefaultDacl(new_token.Get(), WinRestrictedCodeSid,
GRANT_ACCESS, GENERIC_ALL)) {
return ::GetLastError();
}
}
+ for (const auto& default_dacl_sid : sids_for_default_dacl_) {
+ if (!AddSidToDefaultDacl(new_token.Get(), std::get<0>(default_dacl_sid),
+ std::get<1>(default_dacl_sid),
+ std::get<2>(default_dacl_sid))) {
+ return ::GetLastError();
+ }
+ }
+
// Add user to default dacl.
if (!AddUserSidToDefaultDacl(new_token.Get(), GENERIC_ALL))
return ::GetLastError();
DWORD error = SetTokenIntegrityLevel(new_token.Get(), integrity_level_);
if (ERROR_SUCCESS != error)
return error;
@@ -405,9 +413,20 @@ DWORD RestrictedToken::SetIntegrityLevel
integrity_level_ = integrity_level;
return ERROR_SUCCESS;
}
void RestrictedToken::SetLockdownDefaultDacl() {
lockdown_default_dacl_ = true;
}
+DWORD RestrictedToken::AddDefaultDaclSid(const Sid& sid,
+ ACCESS_MODE access_mode,
+ ACCESS_MASK access) {
+ DCHECK(init_);
+ if (!init_)
+ return ERROR_NO_TOKEN;
+
+ sids_for_default_dacl_.push_back(std::make_tuple(sid, access_mode, access));
+ return ERROR_SUCCESS;
+}
+
} // namespace sandbox
diff --git a/security/sandbox/chromium/sandbox/win/src/restricted_token.h b/security/sandbox/chromium/sandbox/win/src/restricted_token.h
--- a/security/sandbox/chromium/sandbox/win/src/restricted_token.h
+++ b/security/sandbox/chromium/sandbox/win/src/restricted_token.h
@@ -2,16 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SANDBOX_SRC_RESTRICTED_TOKEN_H_
#define SANDBOX_SRC_RESTRICTED_TOKEN_H_
#include <windows.h>
+#include <tuple>
#include <vector>
#include <string>
#include "base/macros.h"
#include "base/win/scoped_handle.h"
#include "sandbox/win/src/restricted_token_utils.h"
#include "sandbox/win/src/security_level.h"
@@ -169,23 +170,31 @@ class RestrictedToken {
// Sets the token integrity level. This is only valid on Vista. The integrity
// level cannot be higher than your current integrity level.
DWORD SetIntegrityLevel(IntegrityLevel integrity_level);
// Set a flag which indicates the created token should have a locked down
// default DACL when created.
void SetLockdownDefaultDacl();
+ // Add a SID to the default DACL. These SIDs are added regardless of the
+ // SetLockdownDefaultDacl state.
+ DWORD AddDefaultDaclSid(const Sid& sid,
+ ACCESS_MODE access_mode,
+ ACCESS_MASK access);
+
private:
// The list of restricting sids in the restricted token.
std::vector<Sid> sids_to_restrict_;
// The list of privileges to remove in the restricted token.
std::vector<LUID> privileges_to_disable_;
// The list of sids to mark as Deny Only in the restricted token.
std::vector<Sid> sids_for_deny_only_;
+ // The list of sids to add to the default DACL of the restricted token.
+ std::vector<std::tuple<Sid, ACCESS_MODE, ACCESS_MASK>> sids_for_default_dacl_;
// The token to restrict. Can only be set in a constructor.
base::win::ScopedHandle effective_token_;
// The token integrity level. Only valid on Vista.
IntegrityLevel integrity_level_;
// Tells if the object is initialized or not (if Init() has been called)
bool init_;
// Lockdown the default DACL when creating new tokens.
bool lockdown_default_dacl_;
diff --git a/security/sandbox/chromium/sandbox/win/src/restricted_token_utils.cc b/security/sandbox/chromium/sandbox/win/src/restricted_token_utils.cc
--- a/security/sandbox/chromium/sandbox/win/src/restricted_token_utils.cc
+++ b/security/sandbox/chromium/sandbox/win/src/restricted_token_utils.cc
@@ -51,22 +51,29 @@ DWORD GetObjectSecurityDescriptor(HANDLE
} // namespace
DWORD CreateRestrictedToken(HANDLE effective_token,
TokenLevel security_level,
IntegrityLevel integrity_level,
TokenType token_type,
bool lockdown_default_dacl,
+ PSID unique_restricted_sid,
bool use_restricting_sids,
base::win::ScopedHandle* token) {
RestrictedToken restricted_token;
restricted_token.Init(effective_token);
if (lockdown_default_dacl)
restricted_token.SetLockdownDefaultDacl();
+ if (unique_restricted_sid) {
+ restricted_token.AddDefaultDaclSid(Sid(unique_restricted_sid), GRANT_ACCESS,
+ GENERIC_ALL);
+ restricted_token.AddDefaultDaclSid(Sid(WinCreatorOwnerRightsSid),
+ GRANT_ACCESS, READ_CONTROL);
+ }
std::vector<std::wstring> privilege_exceptions;
std::vector<Sid> sid_exceptions;
bool deny_sids = true;
bool remove_privileges = true;
switch (security_level) {
@@ -118,50 +125,60 @@ DWORD CreateRestrictedToken(HANDLE effec
sid_exceptions.push_back(WinAuthenticatedUserSid);
privilege_exceptions.push_back(SE_CHANGE_NOTIFY_NAME);
if (use_restricting_sids) {
restricted_token.AddRestrictingSid(WinBuiltinUsersSid);
restricted_token.AddRestrictingSid(WinWorldSid);
restricted_token.AddRestrictingSid(WinRestrictedCodeSid);
restricted_token.AddRestrictingSidCurrentUser();
restricted_token.AddRestrictingSidLogonSession();
+ if (unique_restricted_sid)
+ restricted_token.AddRestrictingSid(Sid(unique_restricted_sid));
}
break;
}
case USER_LIMITED: {
sid_exceptions.push_back(WinBuiltinUsersSid);
sid_exceptions.push_back(WinWorldSid);
sid_exceptions.push_back(WinInteractiveSid);
privilege_exceptions.push_back(SE_CHANGE_NOTIFY_NAME);
if (use_restricting_sids) {
restricted_token.AddRestrictingSid(WinBuiltinUsersSid);
restricted_token.AddRestrictingSid(WinWorldSid);
restricted_token.AddRestrictingSid(WinRestrictedCodeSid);
+ if (unique_restricted_sid)
+ restricted_token.AddRestrictingSid(Sid(unique_restricted_sid));
// This token has to be able to create objects in BNO.
// Unfortunately, on Vista+, it needs the current logon sid
// in the token to achieve this. You should also set the process to be
// low integrity level so it can't access object created by other
// processes.
restricted_token.AddRestrictingSidLogonSession();
+ } else {
+ restricted_token.AddUserSidForDenyOnly();
}
break;
}
case USER_RESTRICTED: {
privilege_exceptions.push_back(SE_CHANGE_NOTIFY_NAME);
restricted_token.AddUserSidForDenyOnly();
if (use_restricting_sids) {
restricted_token.AddRestrictingSid(WinRestrictedCodeSid);
+ if (unique_restricted_sid)
+ restricted_token.AddRestrictingSid(Sid(unique_restricted_sid));
}
break;
}
case USER_LOCKDOWN: {
restricted_token.AddUserSidForDenyOnly();
if (use_restricting_sids) {
restricted_token.AddRestrictingSid(WinNullSid);
+ if (unique_restricted_sid)
+ restricted_token.AddRestrictingSid(Sid(unique_restricted_sid));
}
break;
}
default: { return ERROR_BAD_ARGUMENTS; }
}
DWORD err_code = ERROR_SUCCESS;
if (deny_sids) {
diff --git a/security/sandbox/chromium/sandbox/win/src/restricted_token_utils.h b/security/sandbox/chromium/sandbox/win/src/restricted_token_utils.h
--- a/security/sandbox/chromium/sandbox/win/src/restricted_token_utils.h
+++ b/security/sandbox/chromium/sandbox/win/src/restricted_token_utils.h
@@ -33,16 +33,17 @@ enum TokenType { IMPERSONATION = 0, PRIM
// If the function succeeds, the return value is ERROR_SUCCESS. If the
// function fails, the return value is the win32 error code corresponding to
// the error.
DWORD CreateRestrictedToken(HANDLE effective_token,
TokenLevel security_level,
IntegrityLevel integrity_level,
TokenType token_type,
bool lockdown_default_dacl,
+ PSID unique_restricted_sid,
bool use_restricting_sids,
base::win::ScopedHandle* token);
// Sets the integrity label on a object handle.
DWORD SetObjectIntegrityLabel(HANDLE handle,
SE_OBJECT_TYPE type,
const wchar_t* ace_access,
const wchar_t* integrity_level_sid);
diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_policy.h b/security/sandbox/chromium/sandbox/win/src/sandbox_policy.h
--- a/security/sandbox/chromium/sandbox/win/src/sandbox_policy.h
+++ b/security/sandbox/chromium/sandbox/win/src/sandbox_policy.h
@@ -256,16 +256,20 @@ class TargetPolicy {
// ownership of the handle.
virtual void AddHandleToShare(HANDLE handle) = 0;
// Locks down the default DACL of the created lockdown and initial tokens
// to restrict what other processes are allowed to access a process' kernel
// resources.
virtual void SetLockdownDefaultDacl() = 0;
+ // Adds a restricting random SID to the restricted SIDs list as well as
+ // the default DACL.
+ virtual void AddRestrictingRandomSid() = 0;
+
// Enable OPM API redirection when in Win32k lockdown.
virtual void SetEnableOPMRedirection() = 0;
// Enable OPM API emulation when in Win32k lockdown.
virtual bool GetEnableOPMRedirection() = 0;
// Configure policy to use an AppContainer profile. |package_name| is the
// name of the profile to use. Specifying True for |create_profile| ensures
// the profile exists, if set to False process creation will fail if the
diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc b/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc
--- a/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc
+++ b/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc
@@ -105,16 +105,17 @@ PolicyBase::PolicyBase()
delayed_integrity_level_(INTEGRITY_LEVEL_LAST),
mitigations_(0),
delayed_mitigations_(0),
is_csrss_connected_(true),
policy_maker_(nullptr),
policy_(nullptr),
lowbox_sid_(nullptr),
lockdown_default_dacl_(false),
+ add_restricting_random_sid_(false),
enable_opm_redirection_(false),
effective_token_(nullptr) {
::InitializeCriticalSection(&lock_);
dispatcher_.reset(new TopLevelDispatcher(this));
}
PolicyBase::~PolicyBase() {
TargetSet::iterator it;
@@ -389,16 +390,20 @@ void PolicyBase::AddHandleToShare(HANDLE
handles_to_share_.push_back(handle);
}
void PolicyBase::SetLockdownDefaultDacl() {
lockdown_default_dacl_ = true;
}
+void PolicyBase::AddRestrictingRandomSid() {
+ add_restricting_random_sid_ = true;
+}
+
const base::HandlesToInheritVector& PolicyBase::GetHandlesBeingShared() {
return handles_to_share_;
}
ResultCode PolicyBase::MakeJobObject(base::win::ScopedHandle* job) {
if (job_level_ == JOB_NONE) {
job->Close();
return SBOX_ALL_OK;
@@ -413,22 +418,26 @@ ResultCode PolicyBase::MakeJobObject(bas
*job = job_obj.Take();
return SBOX_ALL_OK;
}
ResultCode PolicyBase::MakeTokens(base::win::ScopedHandle* initial,
base::win::ScopedHandle* lockdown,
base::win::ScopedHandle* lowbox) {
+ Sid random_sid = Sid::GenerateRandomSid();
+ PSID random_sid_ptr = nullptr;
+ if (add_restricting_random_sid_)
+ random_sid_ptr = random_sid.GetPSID();
+
// Create the 'naked' token. This will be the permanent token associated
// with the process and therefore with any thread that is not impersonating.
- DWORD result =
- CreateRestrictedToken(effective_token_, lockdown_level_, integrity_level_,
- PRIMARY, lockdown_default_dacl_,
- use_restricting_sids_, lockdown);
+ DWORD result = CreateRestrictedToken(
+ effective_token_, lockdown_level_, integrity_level_, PRIMARY,
+ lockdown_default_dacl_, random_sid_ptr, use_restricting_sids_, lockdown);
if (ERROR_SUCCESS != result)
return SBOX_ERROR_CANNOT_CREATE_RESTRICTED_TOKEN;
// If we're launching on the alternate desktop we need to make sure the
// integrity label on the object is no higher than the sandboxed process's
// integrity level. So, we lower the label on the desktop process if it's
// not already low enough for our process.
if (use_alternate_desktop_ && integrity_level_ != INTEGRITY_LEVEL_LAST) {
@@ -485,20 +494,19 @@ ResultCode PolicyBase::MakeTokens(base::
TOKEN_ALL_ACCESS)) {
return SBOX_ERROR_CANNOT_MODIFY_LOWBOX_TOKEN_DACL;
}
}
// Create the 'better' token. We use this token as the one that the main
// thread uses when booting up the process. It should contain most of
// what we need (before reaching main( ))
- result =
- CreateRestrictedToken(effective_token_, initial_level_, integrity_level_,
- IMPERSONATION, lockdown_default_dacl_,
- use_restricting_sids_, initial);
+ result = CreateRestrictedToken(
+ effective_token_, initial_level_, integrity_level_, IMPERSONATION,
+ lockdown_default_dacl_, random_sid_ptr, use_restricting_sids_, initial);
if (ERROR_SUCCESS != result)
return SBOX_ERROR_CANNOT_CREATE_RESTRICTED_IMP_TOKEN;
return SBOX_ALL_OK;
}
PSID PolicyBase::GetLowBoxSid() const {
return lowbox_sid_;
diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.h b/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.h
--- a/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.h
+++ b/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.h
@@ -69,16 +69,17 @@ class PolicyBase final : public TargetPo
ResultCode AddRule(SubSystem subsystem,
Semantics semantics,
const wchar_t* pattern) override;
ResultCode AddDllToUnload(const wchar_t* dll_name) override;
ResultCode AddKernelObjectToClose(const wchar_t* handle_type,
const wchar_t* handle_name) override;
void AddHandleToShare(HANDLE handle) override;
void SetLockdownDefaultDacl() override;
+ void AddRestrictingRandomSid() override;
void SetEnableOPMRedirection() override;
bool GetEnableOPMRedirection() override;
ResultCode AddAppContainerProfile(const wchar_t* package_name,
bool create_profile) override;
scoped_refptr<AppContainerProfile> GetAppContainerProfile() override;
void SetEffectiveToken(HANDLE token) override;
// Get the AppContainer profile as its internal type.
@@ -165,16 +166,17 @@ class PolicyBase final : public TargetPo
// This is a map of handle-types to names that we need to close in the
// target process. A null set means we need to close all handles of the
// given type.
HandleCloser handle_closer_;
PSID lowbox_sid_;
base::win::ScopedHandle lowbox_directory_;
std::unique_ptr<Dispatcher> dispatcher_;
bool lockdown_default_dacl_;
+ bool add_restricting_random_sid_;
static HDESK alternate_desktop_handle_;
static HWINSTA alternate_winstation_handle_;
static HDESK alternate_desktop_local_winstation_handle_;
static IntegrityLevel alternate_desktop_integrity_level_label_;
static IntegrityLevel
alternate_desktop_local_winstation_integrity_level_label_;
diff --git a/security/sandbox/chromium/sandbox/win/src/sid.cc b/security/sandbox/chromium/sandbox/win/src/sid.cc
--- a/security/sandbox/chromium/sandbox/win/src/sid.cc
+++ b/security/sandbox/chromium/sandbox/win/src/sid.cc
@@ -2,18 +2,20 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "sandbox/win/src/sid.h"
#include <memory>
#include <sddl.h>
+#include <stdlib.h>
#include "base/logging.h"
+#include "base/rand_util.h"
#include "base/win/windows_version.h"
#include "sandbox/win/src/win_utils.h"
namespace sandbox {
namespace {
DWORD WellKnownCapabilityToRid(WellKnownCapabilities capability) {
@@ -127,16 +129,24 @@ Sid Sid::FromSubAuthorities(PSID_IDENTIF
Sid Sid::AllRestrictedApplicationPackages() {
SID_IDENTIFIER_AUTHORITY package_authority = {SECURITY_APP_PACKAGE_AUTHORITY};
DWORD sub_authorities[] = {SECURITY_APP_PACKAGE_BASE_RID,
SECURITY_BUILTIN_PACKAGE_ANY_RESTRICTED_PACKAGE};
return FromSubAuthorities(&package_authority, 2, sub_authorities);
}
+Sid Sid::GenerateRandomSid() {
+ SID_IDENTIFIER_AUTHORITY package_authority = {SECURITY_NULL_SID_AUTHORITY};
+ DWORD sub_authorities[4] = {};
+ base::RandBytes(&sub_authorities, sizeof(sub_authorities));
+ return FromSubAuthorities(&package_authority, _countof(sub_authorities),
+ sub_authorities);
+}
+
PSID Sid::GetPSID() const {
return const_cast<BYTE*>(sid_);
}
bool Sid::IsValid() const {
return !!::IsValidSid(GetPSID());
}
diff --git a/security/sandbox/chromium/sandbox/win/src/sid.h b/security/sandbox/chromium/sandbox/win/src/sid.h
--- a/security/sandbox/chromium/sandbox/win/src/sid.h
+++ b/security/sandbox/chromium/sandbox/win/src/sid.h
@@ -47,16 +47,18 @@ class Sid {
// Create a Sid from a SDDL format string, such as S-1-1-0.
static Sid FromSddlString(const wchar_t* sddl_sid);
// Create a Sid from a set of sub authorities.
static Sid FromSubAuthorities(PSID_IDENTIFIER_AUTHORITY identifier_authority,
BYTE sub_authority_count,
PDWORD sub_authorities);
// Create the restricted all application packages sid.
static Sid AllRestrictedApplicationPackages();
+ // Generate a random SID value.
+ static Sid GenerateRandomSid();
// Returns sid_.
PSID GetPSID() const;
// Gets whether the sid is valid.
bool IsValid() const;
// Converts the SID to a SDDL format string.

Просмотреть файл

@ -9,7 +9,7 @@ Bug 1297740.
diff --git a/security/sandbox/chromium/sandbox/win/src/broker_services.cc b/security/sandbox/chromium/sandbox/win/src/broker_services.cc
--- a/security/sandbox/chromium/sandbox/win/src/broker_services.cc
+++ b/security/sandbox/chromium/sandbox/win/src/broker_services.cc
@@ -414,16 +414,17 @@ DWORD WINAPI BrokerServicesBase::TargetE
@@ -301,16 +301,17 @@ DWORD WINAPI BrokerServicesBase::TargetE
NOTREACHED();
return 0;
}
@ -27,7 +27,7 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/broker_services.cc b/secu
return SBOX_ERROR_BAD_PARAMS;
if (!policy)
@@ -609,17 +610,17 @@ ResultCode BrokerServicesBase::SpawnTarg
@@ -486,17 +487,17 @@ ResultCode BrokerServicesBase::SpawnTarg
// Brokerservices does not own the target object. It is owned by the Policy.
base::win::ScopedProcessInformation process_info;
TargetProcess* target = new TargetProcess(
@ -65,9 +65,9 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/broker_services.h b/secur
#include "sandbox/win/src/crosscall_server.h"
#include "sandbox/win/src/job.h"
#include "sandbox/win/src/sandbox.h"
#include "sandbox/win/src/sandbox_policy_base.h"
#include "sandbox/win/src/sharedmem_ipc_server.h"
@@ -39,16 +40,17 @@ class BrokerServicesBase final : public
#include "sandbox/win/src/win2k_threadpool.h"
@@ -45,16 +46,17 @@ class BrokerServicesBase final : public
~BrokerServicesBase();
@ -88,7 +88,7 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/broker_services.h b/secur
diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox.h b/security/sandbox/chromium/sandbox/win/src/sandbox.h
--- a/security/sandbox/chromium/sandbox/win/src/sandbox.h
+++ b/security/sandbox/chromium/sandbox/win/src/sandbox.h
@@ -84,16 +84,17 @@ class BrokerServices {
@@ -79,16 +79,17 @@ class BrokerServices {
// parameter will hold the last Win32 error value.
// target: returns the resulting target process information such as process
// handle and PID just as if CreateProcess() had been called. The caller is
@ -109,25 +109,7 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox.h b/security/sand
diff --git a/security/sandbox/chromium/sandbox/win/src/target_process.cc b/security/sandbox/chromium/sandbox/win/src/target_process.cc
--- a/security/sandbox/chromium/sandbox/win/src/target_process.cc
+++ b/security/sandbox/chromium/sandbox/win/src/target_process.cc
@@ -9,16 +9,17 @@
#include <memory>
#include <utility>
#include <vector>
#include "base/macros.h"
#include "base/memory/free_deleter.h"
#include "base/numerics/safe_conversions.h"
+#include "base/process/environment_internal.h"
#include "base/win/startup_information.h"
#include "base/win/windows_version.h"
#include "sandbox/win/src/crosscall_client.h"
#include "sandbox/win/src/crosscall_server.h"
#include "sandbox/win/src/policy_low_level.h"
#include "sandbox/win/src/restricted_token_utils.h"
#include "sandbox/win/src/sandbox_types.h"
#include "sandbox/win/src/security_capabilities.h"
@@ -137,16 +138,17 @@ TargetProcess::~TargetProcess() {
@@ -137,16 +137,17 @@ TargetProcess::~TargetProcess() {
// Creates the target (child) process suspended and assigns it to the job
// object.
ResultCode TargetProcess::Create(
@ -145,10 +127,10 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/target_process.cc b/secur
// Start the target process suspended.
DWORD flags =
@@ -156,22 +158,29 @@ ResultCode TargetProcess::Create(
@@ -156,22 +157,29 @@ ResultCode TargetProcess::Create(
flags |= EXTENDED_STARTUPINFO_PRESENT;
if (job_ && base::win::GetVersion() < base::win::Version::WIN8) {
if (job_ && base::win::GetVersion() < base::win::VERSION_WIN8) {
// Windows 8 implements nested jobs, but for older systems we need to
// break out of any job we're in to enforce our restrictions.
flags |= CREATE_BREAKAWAY_FROM_JOB;
@ -156,7 +138,7 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/target_process.cc b/secur
+ LPTCH original_environment = GetEnvironmentStrings();
+ base::NativeEnvironmentString new_environment =
+ base::internal::AlterEnvironment(original_environment, env_changes);
+ base::AlterEnvironment(original_environment, env_changes);
+ // Ignore return value? What can we do?
+ FreeEnvironmentStrings(original_environment);
+ LPVOID new_env_ptr = (void*)new_environment.data();

Просмотреть файл

@ -6,9 +6,7 @@
# Parent 96707276b26997ea2a8e9fd8fdacc0c863717e7b
Allow a special all paths rule in the Windows process sandbox when using semantics FILES_ALLOW_READONLY. r=jimm
This also changes the read only related status checks in filesystem_interception.cc
to include STATUS_NETWORK_OPEN_RESTRICTION (0xC0000201), which gets returned in
some cases and fails because we never ask the broker.
This also changes the read only related status checks in filesystem_interception.cc to include STATUS_NETWORK_OPEN_RESTRICTION (0xC0000201), which gets returned in some cases and fails because we never ask the broker.
diff --git a/security/sandbox/chromium/sandbox/win/src/filesystem_interception.cc b/security/sandbox/chromium/sandbox/win/src/filesystem_interception.cc
--- a/security/sandbox/chromium/sandbox/win/src/filesystem_interception.cc
@ -54,7 +52,7 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/filesystem_interception.c
do {
if (!ValidParameter(file, sizeof(HANDLE), WRITE))
@@ -106,17 +111,18 @@ NTSTATUS WINAPI TargetNtOpenFile(NtOpenF
@@ -106,17 +111,18 @@ NTSTATUS WINAPI TargetNtCreateFile(NtCre
ACCESS_MASK desired_access,
POBJECT_ATTRIBUTES object_attributes,
PIO_STATUS_BLOCK io_status,
@ -94,7 +92,7 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/filesystem_interception.c
do {
if (!ValidParameter(file_attributes, sizeof(FILE_BASIC_INFORMATION), WRITE))
@@ -232,17 +239,18 @@ TargetNtQueryAttributesFile(NtQueryAttri
@@ -232,17 +239,18 @@ NTSTATUS WINAPI TargetNtQueryAttributesF
NTSTATUS WINAPI TargetNtQueryFullAttributesFile(
NtQueryFullAttributesFileFunction orig_QueryFullAttributes,
@ -121,7 +119,7 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/filesystem_policy.cc b/se
bool FileSystemPolicy::GenerateRules(const wchar_t* name,
TargetPolicy::Semantics semantics,
LowLevelPolicy* policy) {
std::wstring mod_name(name);
base::string16 mod_name(name);
if (mod_name.empty()) {
return false;
}

Просмотреть файл

@ -0,0 +1,40 @@
# HG changeset patch
# User Bob Owen <bobowencode@gmail.com>
# Date 1549903491 0
# Mon Feb 11 16:44:51 2019 +0000
# Node ID 3bb3e5a6275db53530d50549b7b329cc1248d450
# Parent fc9d5e40028058abeb06f8bdc2f75fc868fbe14b
Fix incorrect int use in Kernel32BaseVersion in windows_version.cc. r=aklotz
diff --git a/security/sandbox/chromium/base/win/windows_version.cc b/security/sandbox/chromium/base/win/windows_version.cc
--- a/security/sandbox/chromium/base/win/windows_version.cc
+++ b/security/sandbox/chromium/base/win/windows_version.cc
@@ -236,23 +236,23 @@ Version OSInfo::Kernel32Version() const
// kernel32 will still be the "real" version.
base::Version OSInfo::Kernel32BaseVersion() const {
static const base::NoDestructor<base::Version> version([] {
std::unique_ptr<FileVersionInfoWin> file_version_info(
static_cast<FileVersionInfoWin*>(
FileVersionInfoWin::CreateFileVersionInfo(
base::FilePath(FILE_PATH_LITERAL("kernel32.dll")))));
DCHECK(file_version_info);
- const int major =
+ const uint32_t major =
HIWORD(file_version_info->fixed_file_info()->dwFileVersionMS);
- const int minor =
+ const uint32_t minor =
LOWORD(file_version_info->fixed_file_info()->dwFileVersionMS);
- const int build =
+ const uint32_t build =
HIWORD(file_version_info->fixed_file_info()->dwFileVersionLS);
- const int patch =
+ const uint32_t patch =
LOWORD(file_version_info->fixed_file_info()->dwFileVersionLS);
return base::Version(std::vector<uint32_t>{major, minor, build, patch});
}());
return *version;
}
std::string OSInfo::processor_model_name() {
if (processor_model_name_.empty()) {

Просмотреть файл

@ -46,7 +46,7 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/app_container_profile_bas
GetModuleHandle(L"userenv"), "GetAppContainerFolderPath"));
if (!get_app_container_folder_path)
return false;
std::wstring sddl_str;
base::string16 sddl_str;
if (!package_sid_.ToSddlString(&sddl_str))
return false;
base::win::ScopedCoMem<wchar_t> path_str;
@ -62,7 +62,7 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/app_container_profile_bas
+#if defined(MOZ_SANDBOX)
+ IMMEDIATE_CRASH();
+#else
std::wstring sddl_str;
base::string16 sddl_str;
if (!package_sid_.ToSddlString(&sddl_str))
return false;
*pipe_path = base::FilePath(base::StringPrintf(L"\\\\.\\pipe\\%ls\\%ls",

Просмотреть файл

@ -0,0 +1,52 @@
# HG changeset patch
# User Bob Owen <bobowencode@gmail.com>
# Date 1509027042 -3600
# Thu Oct 26 15:10:42 2017 +0100
# Node ID c4557696d42ef22c6eccfd178b3d739a265e2894
# Parent ec58d9068a540487e67c0eac2c60c53dea31d3c3
Don't compile sandbox::ApplyMitigationsToCurrentThread. r=aklotz
This brings in new dependencies via FilePath and we don't currently use it.
As far as I can tell Chromium doesn't use it either.
diff --git a/security/sandbox/chromium/sandbox/win/src/process_mitigations.cc b/security/sandbox/chromium/sandbox/win/src/process_mitigations.cc
--- a/security/sandbox/chromium/sandbox/win/src/process_mitigations.cc
+++ b/security/sandbox/chromium/sandbox/win/src/process_mitigations.cc
@@ -230,16 +230,19 @@ bool ApplyProcessMitigationsToCurrentPro
ERROR_ACCESS_DENIED != ::GetLastError()) {
return false;
}
}
return true;
}
+// This function isn't used yet and adds dependencies for FilePath and
+// ScopedNativeLibrary.
+#if !defined(MOZ_SANDBOX)
bool ApplyMitigationsToCurrentThread(MitigationFlags flags) {
if (!CanSetMitigationsPerThread(flags))
return false;
base::win::Version version = base::win::GetVersion();
if (version < base::win::VERSION_WIN10_RS1)
return true;
@@ -263,16 +266,17 @@ bool ApplyMitigationsToCurrentThread(Mit
if (!set_thread_info_function(::GetCurrentThread(), ThreadDynamicCodePolicy,
&thread_policy, sizeof(thread_policy))) {
return false;
}
}
return true;
}
+#endif
void ConvertProcessMitigationsToPolicy(MitigationFlags flags,
DWORD64* policy_flags,
size_t* size) {
base::win::Version version = base::win::GetVersion();
*policy_flags = 0;
#if defined(_WIN64)

Просмотреть файл

@ -14,10 +14,10 @@ https://hg.mozilla.org/mozilla-central/rev/477b991bf6fa7b4511768649c9bf37c7275d3
diff --git a/security/sandbox/chromium/base/time/time.cc b/security/sandbox/chromium/base/time/time.cc
--- a/security/sandbox/chromium/base/time/time.cc
+++ b/security/sandbox/chromium/base/time/time.cc
@@ -281,16 +281,17 @@ Time Time::Midnight(bool is_local) const
if (FromExploded(is_local, exploded, &out_time))
return out_time;
}
@@ -241,16 +241,17 @@ Time Time::LocalMidnight() const {
Time out_time;
if (FromLocalExploded(exploded, &out_time))
return out_time;
// This function must not fail.
NOTREACHED();
return Time();
@ -32,7 +32,7 @@ diff --git a/security/sandbox/chromium/base/time/time.cc b/security/sandbox/chro
if (time_string[0] == '\0')
return false;
@@ -301,16 +302,17 @@ bool Time::FromStringInternal(const char
@@ -261,16 +262,17 @@ bool Time::FromStringInternal(const char
&result_time);
if (PR_SUCCESS != result)
return false;

Просмотреть файл

@ -1,34 +0,0 @@
# HG changeset patch
# User Toshihito Kikuchi <tkikuchi@mozilla.com>
# Date 1588735588 25200
# Tue May 05 20:26:28 2020 -0700
# Node ID 8214c0253f550d73b5e79dfd825b09f5c1a06fbd
# Parent 2d5ee142bde533ba4f93afaae081a444eac0abe2
Lower SDK version requirement from 19H1 to RS4. r=bobowen
We still use 10.0.17134.0 SDK while Chromium requires 10.0.18362.0 or higher.
diff --git a/security/sandbox/chromium/base/win/windows_version.cc b/security/sandbox/chromium/base/win/windows_version.cc
--- a/security/sandbox/chromium/base/win/windows_version.cc
+++ b/security/sandbox/chromium/base/win/windows_version.cc
@@ -17,18 +17,18 @@
#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_19H1)
-#error Windows 10.0.18362.0 SDK or higher required.
+#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

Просмотреть файл

@ -0,0 +1,37 @@
# HG changeset patch
# User Tom Ritter <tom@mozilla.com>
# Date 1516824525 21600
# Wed Jan 24 14:08:45 2018 -0600
# Node ID b09622ad2731f02ed7f231295bc9421d76b083e6
# Parent 2b890d81a1e3ebc4872958022c8d425d5689b31d
Bug 1432790 Remove a stray \ to fix the MinGW build. r?bobowen
The GCC case includes a stray \ at the end of the line that gcc
complains about.
For reference purposes, this commit is a combination of Bug 1431621
and Bug 1432790 combined together so that it looks like I hadn't
screwed it up.
diff --git a/security/sandbox/chromium/base/win/scoped_handle.h b/security/sandbox/chromium/base/win/scoped_handle.h
--- a/security/sandbox/chromium/base/win/scoped_handle.h
+++ b/security/sandbox/chromium/base/win/scoped_handle.h
@@ -13,17 +13,17 @@
#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(\\
+#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

Просмотреть файл

@ -32,10 +32,10 @@ diff --git a/security/sandbox/chromium/base/win/pe_image.h b/security/sandbox/ch
--- a/security/sandbox/chromium/base/win/pe_image.h
+++ b/security/sandbox/chromium/base/win/pe_image.h
@@ -14,17 +14,17 @@
#include <windows.h>
#include <stdint.h>
#include <windows.h>
#if defined(_WIN32_WINNT_WIN8)
// The Windows 8 SDK defines FACILITY_VISUALCPP in winerror.h.
#undef FACILITY_VISUALCPP

Просмотреть файл

@ -20,14 +20,14 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/target_process.cc b/secur
#if SANDBOX_EXPORTS
HMODULE module = ::LoadLibrary(exe_name_.get());
if (!module)
return SBOX_ERROR_CANNOT_LOADLIBRARY_EXECUTABLE;
return SBOX_ERROR_GENERIC;
- child_var = ::GetProcAddress(module, name);
+ child_var = reinterpret_cast<void*>(::GetProcAddress(module, name));
::FreeLibrary(module);
if (!child_var)
return SBOX_ERROR_CANNOT_FIND_VARIABLE_ADDRESS;
return SBOX_ERROR_GENERIC;
size_t offset =
reinterpret_cast<char*>(child_var) - reinterpret_cast<char*>(module);

Просмотреть файл

@ -11,7 +11,7 @@ MozReview-Commit-ID: D7REZiAIMpN
diff --git a/security/sandbox/chromium/sandbox/win/src/crosscall_params.h b/security/sandbox/chromium/sandbox/win/src/crosscall_params.h
--- a/security/sandbox/chromium/sandbox/win/src/crosscall_params.h
+++ b/security/sandbox/chromium/sandbox/win/src/crosscall_params.h
@@ -78,16 +78,17 @@ union MultiType {
@@ -61,16 +61,17 @@ union MultiType {
ULONG_PTR ulong_ptr;
};
@ -29,9 +29,9 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/crosscall_params.h b/secu
uint32_t offset_;
uint32_t size_;
};
@@ -287,16 +288,18 @@ class ActualCallParams : public CrossCal
@@ -271,16 +272,18 @@ class ActualCallParams : public CrossCal
protected:
ActualCallParams() : CrossCallParams(IpcTag::UNUSED, NUMBER_PARAMS) {}
ActualCallParams() : CrossCallParams(0, NUMBER_PARAMS) { }
private:
ParamInfo param_info_[NUMBER_PARAMS + 1];
@ -167,7 +167,7 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/crosscall_server.cc b/sec
// Avoid compiler optimizations across this point. Any value stored in
// memory should be stored for real, and values previously read from memory
// should be actually read.
std::atomic_thread_fence(std::memory_order_seq_cst);
base::subtle::MemoryBarrier();
- min_declared_size =
- sizeof(CrossCallParams) + ((param_count + 1) * sizeof(ParamInfo));

Просмотреть файл

@ -0,0 +1,52 @@
# HG changeset patch
# User Bob Owen <bobowencode@gmail.com>
# Date 1558340081 -3600
# Mon May 20 09:14:41 2019 +0100
# Node ID ba49022852e0cd13ddb6afa501b61c1f603d60b7
# Parent 672e222dce87dd64c3e2a1381d16aec71b21aef6
Bug 1552160: always undefine MemoryBarrier in Windows sandbox on MinGW.
diff --git a/security/sandbox/chromium/base/atomicops.h b/security/sandbox/chromium/base/atomicops.h
--- a/security/sandbox/chromium/base/atomicops.h
+++ b/security/sandbox/chromium/base/atomicops.h
@@ -34,17 +34,17 @@
// identify the STL implementation.
// - libc++: captures __config for _LIBCPP_VERSION
// - libstdc++: captures bits/c++config.h for __GLIBCXX__
#include <cstddef>
#include "base/base_export.h"
#include "build/build_config.h"
-#if defined(OS_WIN) && defined(ARCH_CPU_64_BITS)
+#if defined(OS_WIN) && (defined(ARCH_CPU_64_BITS) || defined(__MINGW32__))
// windows.h #defines this (only on x64). This causes problems because the
// public API also uses MemoryBarrier at the public name for this fence. So, on
// X64, undef it, and call its documented
// (http://msdn.microsoft.com/en-us/library/windows/desktop/ms684208.aspx)
// implementation directly.
#undef MemoryBarrier
#endif
diff --git a/security/sandbox/chromium/base/atomicops_internals_x86_msvc.h b/security/sandbox/chromium/base/atomicops_internals_x86_msvc.h
--- a/security/sandbox/chromium/base/atomicops_internals_x86_msvc.h
+++ b/security/sandbox/chromium/base/atomicops_internals_x86_msvc.h
@@ -9,17 +9,17 @@
#include "base/win/windows_types.h"
#include <intrin.h>
#include "base/macros.h"
#include "build/build_config.h"
-#if defined(ARCH_CPU_64_BITS)
+#if defined(ARCH_CPU_64_BITS) || defined(__MINGW32__)
// windows.h #defines this (only on x64). This causes problems because the
// public API also uses MemoryBarrier at the public name for this fence. So, on
// X64, undef it, and call its documented
// (http://msdn.microsoft.com/en-us/library/windows/desktop/ms684208.aspx)
// implementation directly.
#undef MemoryBarrier
#endif

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,28 +1,28 @@
update_chromium_linux_x86_syscalls.patch
revert_remove_AddTargetPeer.patch
revert_remove_BrokerDuplicateHandle.patch
replace_ScopedNativeLibrary_in_ApplyMitigationsToCurrentThread.patch
ifdef_out_ApplyMitigationsToCurrentThread.patch
ifdef_out_FromStringInternal.patch
add_option_to_not_use_restricting_sids.patch
ifdef_out_SequenceChecker_code.patch
allow_read_only_all_paths_rule.patch
revert_TargetNtSetInformationThread_change.patch
mingw_base_win_get_caller.patch
mingw_copy_s.patch
mingw_operator_new.patch
mingw_cast_getprocaddress.patch
mingw_capitalization.patch
mingw_disable_one_try.patch
mingw_offsetof.patch
fix_incorrect_int_use_in_Kernel32BaseVersion.patch
revert_removal_of_AlterEnvironment_on_Windows.patch
allow_env_changes.patch
ifdef_out_AppContainerProfileBase_testing_functions.patch
mingw_missing_windows_types_defines.patch
mingw_undefine_MemoryBarrier.patch
add_return_in_QueryCancellationTraitsForNonCancellables_to_satisfy_build.patch
include_atomic_header_in_platform_thread.patch
aarch64_control_flow_guard.patch
revert_removal_of_app_dir_for_DLL_load.patch
more_chromium_linux_x86_x64_syscalls.patch
add_support_for_random_restricted_SID.patch
revert_Token_serialization_and_deserialization.patch
remove_unused_functions_from_StrtodTrimmed.patch
remove_extraneous_backslash_introduced_by_clang_tidy.patch
remove_include_delayimp_h_from_pe_image_cc.patch
lower_SDK_version_requirement.patch
public_siginfo_fields.patch

Просмотреть файл

@ -0,0 +1,52 @@
# HG changeset patch
# User Michael Forney <mforney@mforney.org>
# Date 1581009438 0
# Thu Feb 06 17:17:18 2020 +0000
# Node ID 3ec8c96f4d53916de5223b2eda5e8d66fb6ca227
# Parent 362056ef41086e1faf6ee088c1daef9c73e01370
Bug 1611565 - Cherry-pick upstream patch to use public siginfo_t fields r=gcp
Upstream patch:
https://chromium.googlesource.com/chromium/src.git/+/6bd491daaf28a8281136931133504c23a18f819f%5E%21/#F0
_sifields is a glibc-internal field, and is not available on musl
libc. Instead, use the public-facing fields si_call_addr, si_syscall,
and si_arch, if they are available.
Differential Revision: https://phabricator.services.mozilla.com/D61051
diff --git a/security/sandbox/chromium/sandbox/linux/seccomp-bpf/trap.cc b/security/sandbox/chromium/sandbox/linux/seccomp-bpf/trap.cc
--- a/security/sandbox/chromium/sandbox/linux/seccomp-bpf/trap.cc
+++ b/security/sandbox/chromium/sandbox/linux/seccomp-bpf/trap.cc
@@ -159,21 +159,28 @@ void Trap::SigSys(int nr, LinuxSigInfo*
// See crbug.com/178166.
// TODO(jln): add a DCHECK or move back to FATAL.
RAW_LOG(ERROR, "Unexpected SIGSYS received.");
errno = old_errno;
return;
}
- // Obtain the siginfo information that is specific to SIGSYS. Unfortunately,
- // most versions of glibc don't include this information in siginfo_t. So,
- // we need to explicitly copy it into a arch_sigsys structure.
+ // Obtain the siginfo information that is specific to SIGSYS.
struct arch_sigsys sigsys;
+#if defined(si_call_addr) && !defined(__native_client_nonsfi__)
+ sigsys.ip = info->si_call_addr;
+ sigsys.nr = info->si_syscall;
+ sigsys.arch = info->si_arch;
+#else
+ // If the version of glibc doesn't include this information in
+ // siginfo_t (older than 2.17), we need to explicitly copy it
+ // into an arch_sigsys structure.
memcpy(&sigsys, &info->_sifields, sizeof(sigsys));
+#endif
#if defined(__mips__)
// When indirect syscall (syscall(__NR_foo, ...)) is made on Mips, the
// number in register SECCOMP_SYSCALL(ctx) is always __NR_syscall and the
// real number of a syscall (__NR_foo) is in SECCOMP_PARM1(ctx)
bool sigsys_nr_is_bad = sigsys.nr != static_cast<int>(SECCOMP_SYSCALL(ctx)) &&
sigsys.nr != static_cast<int>(SECCOMP_PARM1(ctx));
#else

Просмотреть файл

@ -1,34 +0,0 @@
# HG changeset patch
# User Toshihito Kikuchi <tkikuchi@mozilla.com>
# Date 1588867789 25200
# Thu May 07 09:09:49 2020 -0700
# Node ID 29fbfefe6f5f533fb5aa4339015cea4746ad6493
# Parent 044c15e89ecca19afc1750c439f4e82879679462
Remove Extraneous Backslash Introduced by clang-tidy in ScopedHandle. r=bobowen
Need the following commit to compile with Mingw, which has not reached
the stable channel yet.
https://chromium.googlesource.com/chromium/src.git/+/1620fe70c299f1f18b2f2c652d16739f6e3c5f78
diff --git a/security/sandbox/chromium/base/win/scoped_handle.h b/security/sandbox/chromium/base/win/scoped_handle.h
--- a/security/sandbox/chromium/base/win/scoped_handle.h
+++ b/security/sandbox/chromium/base/win/scoped_handle.h
@@ -15,17 +15,17 @@
#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))
+ __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:

Просмотреть файл

@ -1,32 +0,0 @@
# HG changeset patch
# User Toshihito Kikuchi <tkikuchi@mozilla.com>
# Date 1588871424 25200
# Thu May 07 10:10:24 2020 -0700
# Node ID 2d5ee142bde533ba4f93afaae081a444eac0abe2
# Parent 29fbfefe6f5f533fb5aa4339015cea4746ad6493
Don't include delayimp.h twice from //base/win/pe_image.cc to compile with Mingw. r=bobowen
The second include was introduced by
https://chromium.googlesource.com/chromium/src.git/+/5c23d46846111ea16aaf2a9b45355cca5ddbf6d8
diff --git a/security/sandbox/chromium/base/win/pe_image.cc b/security/sandbox/chromium/base/win/pe_image.cc
--- a/security/sandbox/chromium/base/win/pe_image.cc
+++ b/security/sandbox/chromium/base/win/pe_image.cc
@@ -2,17 +2,16 @@
// 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 <delayimp.h>
#include <stddef.h>
#include <set>
#include <string>
#include "base/no_destructor.h"
#include "base/win/current_module.h"
namespace base {

Просмотреть файл

@ -1,48 +0,0 @@
# HG changeset patch
# User Toshihito Kikuchi <tkikuchi@mozilla.com>
# Date 1588733379 25200
# Tue May 05 19:49:39 2020 -0700
# Node ID 044c15e89ecca19afc1750c439f4e82879679462
# Parent a18431660425e41c26c716413aac0294987c985a
Remove unused functions from //base/third_party/double_conversion/double-conversion to compile. r=bobowen
diff --git a/security/sandbox/chromium/base/third_party/double_conversion/double-conversion/strtod.cc b/security/sandbox/chromium/base/third_party/double_conversion/double-conversion/strtod.cc
--- a/security/sandbox/chromium/base/third_party/double_conversion/double-conversion/strtod.cc
+++ b/security/sandbox/chromium/base/third_party/double_conversion/double-conversion/strtod.cc
@@ -445,36 +445,18 @@ static bool ComputeGuess(Vector<const ch
return true;
}
if (*guess == Double::Infinity()) {
return true;
}
return false;
}
-static bool IsDigit(const char d) {
- return ('0' <= d) && (d <= '9');
-}
-
-static bool IsNonZeroDigit(const char d) {
- return ('1' <= d) && (d <= '9');
-}
-
-static bool AssertTrimmedDigits(const Vector<const char>& buffer) {
- for(int i = 0; i < buffer.length(); ++i) {
- if(!IsDigit(buffer[i])) {
- return false;
- }
- }
- return (buffer.length() == 0) || (IsNonZeroDigit(buffer[0]) && IsNonZeroDigit(buffer[buffer.length()-1]));
-}
-
double StrtodTrimmed(Vector<const char> trimmed, int exponent) {
DOUBLE_CONVERSION_ASSERT(trimmed.length() <= kMaxSignificantDecimalDigits);
- DOUBLE_CONVERSION_ASSERT(AssertTrimmedDigits(trimmed));
double guess;
const bool is_correct = ComputeGuess(trimmed, exponent, &guess);
if (is_correct) {
return guess;
}
DiyFp upper_boundary = Double(guess).UpperBoundary();
int comparison = CompareBufferWithDiyFp(trimmed, exponent, upper_boundary);
if (comparison < 0) {

Просмотреть файл

@ -1,59 +0,0 @@
# HG changeset patch
# User Toshihito Kikuchi <tkikuchi@mozilla.com>
# Date 1589672273 25200
# Sat May 16 16:37:53 2020 -0700
# Node ID c14ef8304c36fdc2570b77b63b36114cff2d070d
# Parent 90b5f63770f52fab163adaed1d5812b2887b335a
Use GetModuleHandle/GetProcAddress in ApplyMitigationsToCurrentThread. r=bobowen
This patch removes the use of base::ScopedNativeLibrary from
sandbox::ApplyMitigationsToCurrentThread because to avoid
new dependencies.
diff --git a/security/sandbox/chromium/sandbox/win/src/process_mitigations.cc b/security/sandbox/chromium/sandbox/win/src/process_mitigations.cc
--- a/security/sandbox/chromium/sandbox/win/src/process_mitigations.cc
+++ b/security/sandbox/chromium/sandbox/win/src/process_mitigations.cc
@@ -5,18 +5,16 @@
#include "sandbox/win/src/process_mitigations.h"
#include <stddef.h>
#include <windows.h>
#include <wow64apiset.h>
#include <algorithm>
-#include "base/files/file_path.h"
-#include "base/scoped_native_library.h"
#include "base/win/windows_version.h"
#include "build/build_config.h"
#include "sandbox/win/src/nt_internals.h"
#include "sandbox/win/src/restricted_token_utils.h"
#include "sandbox/win/src/sandbox_rand.h"
#include "sandbox/win/src/win_utils.h"
namespace {
@@ -321,22 +319,19 @@ bool ApplyMitigationsToCurrentThread(Mit
return true;
// Enable dynamic code per-thread policies.
if (flags & MITIGATION_DYNAMIC_CODE_OPT_OUT_THIS_THREAD) {
DWORD thread_policy = THREAD_DYNAMIC_CODE_ALLOW;
// NOTE: SetThreadInformation API only exists on >= Win8. Dynamically
// get function handle.
- base::ScopedNativeLibrary dll(base::FilePath(L"kernel32.dll"));
- if (!dll.is_valid())
- return false;
SetThreadInformationFunction set_thread_info_function =
- reinterpret_cast<SetThreadInformationFunction>(
- dll.GetFunctionPointer("SetThreadInformation"));
+ reinterpret_cast<SetThreadInformationFunction>(::GetProcAddress(
+ ::GetModuleHandleA("kernel32.dll"), "SetThreadInformation"));
if (!set_thread_info_function)
return false;
// NOTE: Must use the pseudo-handle here, a thread HANDLE won't work.
if (!set_thread_info_function(::GetCurrentThread(), ThreadDynamicCodePolicy,
&thread_policy, sizeof(thread_policy))) {
return false;
}

Просмотреть файл

@ -1,100 +0,0 @@
# HG changeset patch
# User Toshihito Kikuchi <tkikuchi@mozilla.com>
# Date 1588530677 25200
# Sun May 03 11:31:17 2020 -0700
# Node ID a18431660425e41c26c716413aac0294987c985a
# Parent e149b1937231ccc3c1c07f45acf0e7e71117854f
Revert chromium's ffe1d0eb42d1d75f2b6a3b4145eff69f235a19ee. r=bobowen
Undoing the following commit as it brings more dependency but unused in our code.
https://chromium.googlesource.com/chromium/src.git/+/ffe1d0eb42d1d75f2b6a3b4145eff69f235a19ee
diff --git a/security/sandbox/chromium/base/token.cc b/security/sandbox/chromium/base/token.cc
--- a/security/sandbox/chromium/base/token.cc
+++ b/security/sandbox/chromium/base/token.cc
@@ -1,17 +1,16 @@
// 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/token.h"
#include <inttypes.h>
-#include "base/pickle.h"
#include "base/rand_util.h"
#include "base/strings/stringprintf.h"
namespace base {
// static
Token Token::CreateRandom() {
Token token;
@@ -21,26 +20,9 @@ Token Token::CreateRandom() {
base::RandBytes(&token, sizeof(token));
return token;
}
std::string Token::ToString() const {
return base::StringPrintf("%016" PRIX64 "%016" PRIX64, high_, low_);
}
-void WriteTokenToPickle(Pickle* pickle, const Token& token) {
- pickle->WriteUInt64(token.high());
- pickle->WriteUInt64(token.low());
-}
-
-Optional<Token> ReadTokenFromPickle(PickleIterator* pickle_iterator) {
- uint64_t high;
- if (!pickle_iterator->ReadUInt64(&high))
- return nullopt;
-
- uint64_t low;
- if (!pickle_iterator->ReadUInt64(&low))
- return nullopt;
-
- return Token(high, low);
-}
-
} // namespace base
diff --git a/security/sandbox/chromium/base/token.h b/security/sandbox/chromium/base/token.h
--- a/security/sandbox/chromium/base/token.h
+++ b/security/sandbox/chromium/base/token.h
@@ -7,17 +7,16 @@
#include <stdint.h>
#include <iosfwd>
#include <tuple>
#include "base/base_export.h"
#include "base/hash/hash.h"
-#include "base/optional.h"
namespace base {
// A Token is a randomly chosen 128-bit integer. This class supports generation
// from a cryptographically strong random source, or constexpr construction over
// fixed values (e.g. to store a pre-generated constant value). Tokens are
// similar in spirit and purpose to UUIDs, without many of the constraints and
// expectations (such as byte layout and string representation) clasically
@@ -63,19 +62,11 @@ class BASE_EXPORT Token {
// For use in std::unordered_map.
struct TokenHash {
size_t operator()(const base::Token& token) const {
return base::HashInts64(token.high(), token.low());
}
};
-class Pickle;
-class PickleIterator;
-
-// For serializing and deserializing Token values.
-BASE_EXPORT void WriteTokenToPickle(Pickle* pickle, const Token& token);
-BASE_EXPORT Optional<Token> ReadTokenFromPickle(
- PickleIterator* pickle_iterator);
-
} // namespace base
#endif // BASE_TOKEN_H_

Просмотреть файл

@ -0,0 +1,150 @@
# HG changeset patch
# User Bob Owen <bobowencode@gmail.com>
# Date 1560256605 -3600
# Tue Jun 11 13:36:45 2019 +0100
# Node ID 686d4b711b65b7cd8692e92e9a7ae152a942b69e
# Parent 213d707af158b3d276c8cce56aba2e3c27abda82
Bug 1552160: Revert removal of AlterEnvironment from chromium code on Windows. r=jld
diff --git a/security/sandbox/chromium/base/environment.cc b/security/sandbox/chromium/base/environment.cc
--- a/security/sandbox/chromium/base/environment.cc
+++ b/security/sandbox/chromium/base/environment.cc
@@ -96,34 +96,32 @@ class EnvironmentImpl : public Environme
return !!SetEnvironmentVariable(UTF8ToWide(variable_name).c_str(), nullptr);
#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
// On success, zero is returned.
return !unsetenv(variable_name.data());
#endif
}
};
-#if defined(OS_POSIX) || defined(OS_FUCHSIA)
// Parses a null-terminated input string of an environment block. The key is
// placed into the given string, and the total length of the line, including
// the terminating null, is returned.
size_t ParseEnvLine(const NativeEnvironmentString::value_type* input,
NativeEnvironmentString* key) {
// Skip to the equals or end of the string, this is the key.
size_t cur = 0;
while (input[cur] && input[cur] != '=')
cur++;
*key = NativeEnvironmentString(&input[0], cur);
// Now just skip to the end of the string.
while (input[cur])
cur++;
return cur + 1;
}
-#endif
} // namespace
namespace env_vars {
#if defined(OS_POSIX) || defined(OS_FUCHSIA)
// On Posix systems, this variable contains the location of the user's home
// directory. (e.g, /home/username/).
@@ -138,17 +136,57 @@ Environment::~Environment() = default;
std::unique_ptr<Environment> Environment::Create() {
return std::make_unique<EnvironmentImpl>();
}
bool Environment::HasVar(StringPiece variable_name) {
return GetVar(variable_name, nullptr);
}
-#if defined(OS_POSIX) || defined(OS_FUCHSIA)
+#if defined(OS_WIN)
+
+string16 AlterEnvironment(const wchar_t* env,
+ const EnvironmentMap& changes) {
+ string16 result;
+
+ // First copy all unmodified values to the output.
+ size_t cur_env = 0;
+ string16 key;
+ while (env[cur_env]) {
+ const wchar_t* line = &env[cur_env];
+ size_t line_length = ParseEnvLine(line, &key);
+
+ // Keep only values not specified in the change vector.
+ EnvironmentMap::const_iterator found_change = changes.find(key);
+ if (found_change == changes.end())
+ result.append(line, line_length);
+
+ cur_env += line_length;
+ }
+
+ // Now append all modified and new values.
+ for (EnvironmentMap::const_iterator i = changes.begin();
+ i != changes.end(); ++i) {
+ if (!i->second.empty()) {
+ result.append(i->first);
+ result.push_back('=');
+ result.append(i->second);
+ result.push_back(0);
+ }
+ }
+
+ // An additional null marks the end of the list. We always need a double-null
+ // in case nothing was added above.
+ if (result.empty())
+ result.push_back(0);
+ result.push_back(0);
+ return result;
+}
+
+#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
std::unique_ptr<char* []> AlterEnvironment(const char* const* const env,
const EnvironmentMap& changes) {
std::string value_storage; // Holds concatenated null-terminated strings.
std::vector<size_t> result_indices; // Line indices into value_storage.
// First build up all of the unchanged environment strings. These are
// null-terminated of the form "key=value".
diff --git a/security/sandbox/chromium/base/environment.h b/security/sandbox/chromium/base/environment.h
--- a/security/sandbox/chromium/base/environment.h
+++ b/security/sandbox/chromium/base/environment.h
@@ -48,27 +48,36 @@ class BASE_EXPORT Environment {
#if defined(OS_WIN)
typedef string16 NativeEnvironmentString;
typedef std::map<NativeEnvironmentString, NativeEnvironmentString>
EnvironmentMap;
+// Returns a modified environment vector constructed from the given environment
+// and the list of changes given in |changes|. Each key in the environment is
+// matched against the first element of the pairs. In the event of a match, the
+// value is replaced by the second of the pair, unless the second is empty, in
+// which case the key-value is removed.
+//
+// This Windows version takes and returns a Windows-style environment block
+// which is a concatenated list of null-terminated 16-bit strings. The end is
+// marked by a double-null terminator. The size of the returned string will
+// include the terminators.
+BASE_EXPORT string16 AlterEnvironment(const wchar_t* env,
+ const EnvironmentMap& changes);
+
#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
typedef std::string NativeEnvironmentString;
typedef std::map<NativeEnvironmentString, NativeEnvironmentString>
EnvironmentMap;
-// Returns a modified environment vector constructed from the given environment
-// and the list of changes given in |changes|. Each key in the environment is
-// matched against the first element of the pairs. In the event of a match, the
-// value is replaced by the second of the pair, unless the second is empty, in
-// which case the key-value is removed.
+// See general comments for the Windows version above.
//
// This Posix version takes and returns a Posix-style environment block, which
// is a null-terminated list of pointers to null-terminated strings. The
// returned array will have appended to it the storage for the array itself so
// there is only one pointer to manage, but this means that you can't copy the
// array without keeping the original around.
BASE_EXPORT std::unique_ptr<char* []> AlterEnvironment(
const char* const* env,

Просмотреть файл

@ -1,53 +1,88 @@
# HG changeset patch
# User Toshihito Kikuchi <tkikuchi@mozilla.com>
# Date 1589671259 25200
# Sat May 16 16:20:59 2020 -0700
# Node ID 0b5183a01df78cc85264f2eae2c4d8e407bb1112
# Parent d093cd9ccfcf06f4a1f0d7f1a4bd0f143ef92b4b
Add BrokerServicesBase::IsSafeDuplicationTarget. r=bobowen
# User Bob Owen <bobowencode@gmail.com>
# Date 1485985799 0
# Wed Feb 01 21:49:59 2017 +0000
# Node ID 8faee368c603dab03076d8900f01acfd776caaeb
# Parent dba4611d335189b9a3314f5dc57935f554c8b945
Reinstate sandbox::BrokerServices::AddTargetPeer r=aklotz
This patch adds BrokerServicesBase::IsSafeDuplicationTarget and
BrokerServicesBase::AddTargetPeer using the new ProcessTracker introduced by
https://chromium.googlesource.com/chromium/src.git/+/3d8382cf9dd44cf9c05e43e42c500f4825e1fed8
We need these methods for HandlePolicy which is added as a different patch.
Chromium used to have AddTargetPeer and IsActiveTarget, but removed by
the following commits because they were no longer used in Chromium.
https://chromium.googlesource.com/chromium/src.git/+/996b42db5296bd3d11b3d7fde1a4602bbcefed2c
https://chromium.googlesource.com/chromium/src.git/+/e615a1152ac6e10f1a91f0629fb8b5ca223ffbdc
This is basically a revert of chromium commit 996b42db5296bd3d11b3d7fde1a4602bbcefed2c.
diff --git a/security/sandbox/chromium/sandbox/win/src/broker_services.cc b/security/sandbox/chromium/sandbox/win/src/broker_services.cc
--- a/security/sandbox/chromium/sandbox/win/src/broker_services.cc
+++ b/security/sandbox/chromium/sandbox/win/src/broker_services.cc
@@ -154,16 +154,18 @@ namespace sandbox {
@@ -41,16 +41,17 @@ sandbox::ResultCode SpawnCleanup(sandbox
delete target;
return sandbox::SBOX_ERROR_GENERIC;
}
// the different commands that you can send to the worker thread that
// executes TargetEventsThread().
enum {
THREAD_CTRL_NONE,
+ THREAD_CTRL_REMOVE_PEER,
THREAD_CTRL_QUIT,
THREAD_CTRL_LAST,
};
// Helper structure that allows the Broker to associate a job notification
// with a job object and with a policy.
struct JobTracker {
JobTracker(base::win::ScopedHandle job,
@@ -77,16 +78,37 @@ void JobTracker::FreeResources() {
HANDLE stale_job_handle = job.Get();
job.Close();
// In OnJobEmpty() we don't actually use the job handle directly.
policy->OnJobEmpty(stale_job_handle);
policy = nullptr;
}
}
+
+// Helper structure that allows the broker to track peer processes
+struct PeerTracker {
+ PeerTracker(DWORD process_id, HANDLE broker_job_port)
+ : wait_object(NULL), id(process_id), job_port(broker_job_port) {
+ }
+
+ HANDLE wait_object;
+ base::win::ScopedHandle process;
+ DWORD id;
+ HANDLE job_port;
+};
+
+void DeregisterPeerTracker(PeerTracker* peer) {
+ // Deregistration shouldn't fail, but we leak rather than crash if it does.
+ if (::UnregisterWaitEx(peer->wait_object, INVALID_HANDLE_VALUE)) {
+ delete peer;
+ } else {
+ NOTREACHED();
+ }
+}
} // namespace
namespace sandbox {
BrokerServicesBase::BrokerServicesBase() {}
// The broker uses a dedicated worker thread that services the job completion
// port to perform policy notifications and associated cleanup tasks.
ResultCode BrokerServicesBase::Init() {
if (job_port_.IsValid() || thread_pool_)
return SBOX_ERROR_UNEXPECTED_CALL;
+ ::InitializeCriticalSection(&lock_);
+
job_port_.Set(::CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr, 0, 0));
if (!job_port_.IsValid())
return SBOX_ERROR_CANNOT_INIT_BROKERSERVICES;
no_targets_.Set(::CreateEventW(nullptr, true, false, nullptr));
job_thread_.Set(::CreateThread(nullptr, 0, // Default security and stack.
TargetEventsThread, this, 0, nullptr));
@@ -191,16 +193,17 @@ BrokerServicesBase::~BrokerServicesBase(
if (job_thread_.IsValid() &&
WAIT_TIMEOUT == ::WaitForSingleObject(job_thread_.Get(), 1000)) {
@@ -132,16 +154,22 @@ BrokerServicesBase::~BrokerServicesBase(
// Cannot clean broker services.
NOTREACHED();
return;
}
tracker_list_.clear();
thread_pool_.reset();
+ ::DeleteCriticalSection(&lock_);
+ // Cancel the wait events and delete remaining peer trackers.
+ for (PeerTrackerMap::iterator it = peer_map_.begin();
+ it != peer_map_.end(); ++it) {
+ DeregisterPeerTracker(it->second);
+ }
+
::DeleteCriticalSection(&lock_);
}
scoped_refptr<TargetPolicy> BrokerServicesBase::CreatePolicy() {
@ -55,99 +90,45 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/broker_services.cc b/secu
// change the downcast to it in SpawnTarget().
scoped_refptr<TargetPolicy> policy(new PolicyBase);
// PolicyBase starts with refcount 1.
policy->Release();
@@ -283,16 +286,21 @@ DWORD WINAPI BrokerServicesBase::TargetE
if (1 == target_counter) {
::ResetEvent(no_targets);
}
@@ -247,16 +275,23 @@ DWORD WINAPI BrokerServicesBase::TargetE
break;
}
case JOB_OBJECT_MSG_EXIT_PROCESS:
case JOB_OBJECT_MSG_ABNORMAL_EXIT_PROCESS: {
+ {
+ AutoLock lock(&broker->lock_);
+ broker->active_targets_.erase(
+ static_cast<DWORD>(reinterpret_cast<uintptr_t>(ovl)));
+ }
size_t erase_result = child_process_ids.erase(
static_cast<DWORD>(reinterpret_cast<uintptr_t>(ovl)));
if (erase_result != 1U) {
// The process was untracked e.g. a child process of the target.
--untracked_target_counter;
DCHECK(untracked_target_counter >= 0);
}
--target_counter;
@@ -348,27 +356,31 @@ DWORD WINAPI BrokerServicesBase::TargetE
tracker->wait_handle = INVALID_HANDLE_VALUE;
default: {
NOTREACHED();
break;
}
}
processes.push_back(std::move(tracker));
} else if (THREAD_CTRL_PROCESS_SIGNALLED == key) {
ProcessTracker* tracker =
static_cast<ProcessTracker*>(reinterpret_cast<void*>(ovl));
+ {
+ AutoLock lock(&broker->lock_);
+ broker->active_targets_.erase(tracker->process_id);
+ }
+
::UnregisterWait(tracker->wait_handle);
tracker->wait_handle = INVALID_HANDLE_VALUE;
// PID is unique until the process handle is closed in dtor.
processes.erase(std::remove_if(processes.begin(), processes.end(),
[&](auto&& p) -> bool {
return p->process_id ==
tracker->process_id;
}),
processes.end());
-
} else if (THREAD_CTRL_GET_POLICY_INFO == key) {
// Clone the policies for sandbox diagnostics.
std::unique_ptr<PolicyDiagnosticsReceiver> receiver;
receiver.reset(static_cast<PolicyDiagnosticsReceiver*>(
reinterpret_cast<void*>(ovl)));
// The PollicyInfo ctor copies essential information from the trackers.
auto policy_list = std::make_unique<PolicyDiagnosticList>();
for (auto&& process_tracker : processes) {
@@ -637,47 +649,79 @@ ResultCode BrokerServicesBase::SpawnTarg
// the tracker. The worker thread takes ownership of these objects.
CHECK(::PostQueuedCompletionStatus(
job_port_.Get(), 0, THREAD_CTRL_NEW_JOB_TRACKER,
reinterpret_cast<LPOVERLAPPED>(tracker)));
// There is no obvious recovery after failure here. Previous version with
// SpawnCleanup() caused deletion of TargetProcess twice. crbug.com/480639
CHECK(
AssociateCompletionPort(tracker->job.Get(), job_port_.Get(), tracker));
+
+ AutoLock lock(&lock_);
+ active_targets_.insert(process_info.process_id());
} else {
- // Duplicate the process handle to give the tracking machinery
- // something valid to wait on in the tracking thread.
- HANDLE tmp_process_handle = INVALID_HANDLE_VALUE;
- if (!::DuplicateHandle(::GetCurrentProcess(), process_info.process_handle(),
- ::GetCurrentProcess(), &tmp_process_handle,
- SYNCHRONIZE, false, 0 /*no options*/)) {
- *last_error = ::GetLastError();
+ result = AddTargetPeerInternal(process_info.process_handle(),
+ process_info.process_id(),
+ policy_base, last_error);
+ if (result != SBOX_ALL_OK) {
// This may fail in the same way as Job associated processes.
// crbug.com/480639.
SpawnCleanup(target);
- return SBOX_ERROR_CANNOT_DUPLICATE_PROCESS_HANDLE;
+ return result;
+ } else if (THREAD_CTRL_REMOVE_PEER == key) {
+ // Remove a process from our list of peers.
+ AutoLock lock(&broker->lock_);
+ PeerTrackerMap::iterator it = broker->peer_map_.find(
+ static_cast<DWORD>(reinterpret_cast<uintptr_t>(ovl)));
+ DeregisterPeerTracker(it->second);
+ broker->peer_map_.erase(it);
} else if (THREAD_CTRL_QUIT == key) {
// The broker object is being destroyed so the thread needs to exit.
return 0;
} else {
// We have not implemented more commands.
NOTREACHED();
}
- base::win::ScopedHandle dup_process_handle(tmp_process_handle);
- ProcessTracker* tracker = new ProcessTracker(
- policy_base, process_info.process_id(), std::move(dup_process_handle));
- // The tracker and policy will leak if this call fails.
- ::PostQueuedCompletionStatus(job_port_.Get(), 0,
- THREAD_CTRL_NEW_PROCESS_TRACKER,
- reinterpret_cast<LPOVERLAPPED>(tracker));
}
@@ -460,25 +495,70 @@ ResultCode BrokerServicesBase::SpawnTarg
// TODO(wfh): Find a way to make this have the correct lifetime.
policy_base->AddRef();
// We have to signal the event once here because the completion port will
// never get a message that this target is being terminated thus we should
// not block WaitForAllTargets until we have at least one target with job.
if (child_process_ids_.empty())
::SetEvent(no_targets_.Get());
+ // We can not track the life time of such processes and it is responsibility
+ // of the host application to make sure that spawned targets without jobs
+ // are terminated when the main application don't need them anymore.
+ // Sandbox policy engine needs to know that these processes are valid
+ // targets for e.g. BrokerDuplicateHandle so track them as peer processes.
+ AddTargetPeer(process_info.process_handle());
}
*target_info = process_info.Take();
@ -159,75 +140,74 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/broker_services.cc b/secu
return SBOX_ALL_OK;
}
+bool BrokerServicesBase::IsSafeDuplicationTarget(DWORD process_id) {
+ AutoLock lock(&lock_);
+ return active_targets_.find(process_id) != active_targets_.end();
bool BrokerServicesBase::IsActiveTarget(DWORD process_id) {
AutoLock lock(&lock_);
- return child_process_ids_.find(process_id) != child_process_ids_.end();
+ return child_process_ids_.find(process_id) != child_process_ids_.end() ||
+ peer_map_.find(process_id) != peer_map_.end();
+}
+
+ResultCode BrokerServicesBase::AddTargetPeerInternal(
+ HANDLE peer_process_handle,
+ DWORD peer_process_id,
+ scoped_refptr<PolicyBase> policy_base,
+ DWORD* last_error) {
+ // Duplicate the process handle to give the tracking machinery
+ // something valid to wait on in the tracking thread.
+ HANDLE tmp_process_handle = INVALID_HANDLE_VALUE;
+ if (!::DuplicateHandle(::GetCurrentProcess(), peer_process_handle,
+ ::GetCurrentProcess(), &tmp_process_handle,
+ SYNCHRONIZE, false, 0 /*no options*/)) {
+ *last_error = ::GetLastError();
+ return SBOX_ERROR_CANNOT_DUPLICATE_PROCESS_HANDLE;
+ }
+ base::win::ScopedHandle dup_process_handle(tmp_process_handle);
+ ProcessTracker* tracker = new ProcessTracker(
+ policy_base, peer_process_id, std::move(dup_process_handle));
+ // The tracker and policy will leak if this call fails.
+ ::PostQueuedCompletionStatus(job_port_.Get(), 0,
+ THREAD_CTRL_NEW_PROCESS_TRACKER,
+ reinterpret_cast<LPOVERLAPPED>(tracker));
+
+ AutoLock lock(&lock_);
+ active_targets_.insert(peer_process_id);
+
+ return SBOX_ALL_OK;
+VOID CALLBACK BrokerServicesBase::RemovePeer(PVOID parameter, BOOLEAN timeout) {
+ PeerTracker* peer = reinterpret_cast<PeerTracker*>(parameter);
+ // Don't check the return code because we this may fail (safely) at shutdown.
+ ::PostQueuedCompletionStatus(
+ peer->job_port, 0, THREAD_CTRL_REMOVE_PEER,
+ reinterpret_cast<LPOVERLAPPED>(static_cast<uintptr_t>(peer->id)));
+}
+
+ResultCode BrokerServicesBase::AddTargetPeer(HANDLE peer_process) {
+ DWORD last_error;
+ return AddTargetPeerInternal(peer_process, ::GetProcessId(peer_process),
+ nullptr, &last_error);
+}
+ std::unique_ptr<PeerTracker> peer(
+ new PeerTracker(::GetProcessId(peer_process), job_port_.Get()));
+ if (!peer->id)
+ return SBOX_ERROR_GENERIC;
+
ResultCode BrokerServicesBase::GetPolicyDiagnostics(
std::unique_ptr<PolicyDiagnosticsReceiver> receiver) {
CHECK(job_thread_.IsValid());
// Post to the job thread.
if (!::PostQueuedCompletionStatus(
job_port_.Get(), 0, THREAD_CTRL_GET_POLICY_INFO,
reinterpret_cast<LPOVERLAPPED>(receiver.get()))) {
receiver->OnError(SBOX_ERROR_GENERIC);
+ HANDLE process_handle;
+ if (!::DuplicateHandle(::GetCurrentProcess(), peer_process,
+ ::GetCurrentProcess(), &process_handle,
+ SYNCHRONIZE, FALSE, 0)) {
+ return SBOX_ERROR_GENERIC;
+ }
+ peer->process.Set(process_handle);
+
+ AutoLock lock(&lock_);
+ if (!peer_map_.insert(std::make_pair(peer->id, peer.get())).second)
+ return SBOX_ERROR_BAD_PARAMS;
+
+ if (!::RegisterWaitForSingleObject(
+ &peer->wait_object, peer->process.Get(), RemovePeer, peer.get(),
+ INFINITE, WT_EXECUTEONLYONCE | WT_EXECUTEINWAITTHREAD)) {
+ peer_map_.erase(peer->id);
+ return SBOX_ERROR_GENERIC;
+ }
+
+ // Release the pointer since it will be cleaned up by the callback.
+ ignore_result(peer.release());
+ return SBOX_ALL_OK;
}
} // namespace sandbox
diff --git a/security/sandbox/chromium/sandbox/win/src/broker_services.h b/security/sandbox/chromium/sandbox/win/src/broker_services.h
--- a/security/sandbox/chromium/sandbox/win/src/broker_services.h
+++ b/security/sandbox/chromium/sandbox/win/src/broker_services.h
@@ -13,16 +13,17 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/win/scoped_handle.h"
#include "sandbox/win/src/crosscall_server.h"
#include "sandbox/win/src/job.h"
@@ -19,16 +19,17 @@
#include "sandbox/win/src/sandbox.h"
+#include "sandbox/win/src/sandbox_policy_base.h"
#include "sandbox/win/src/sharedmem_ipc_server.h"
#include "sandbox/win/src/win2k_threadpool.h"
#include "sandbox/win/src/win_utils.h"
namespace {
struct JobTracker;
+struct PeerTracker;
} // namespace
namespace sandbox {
// BrokerServicesBase ---------------------------------------------------------
// Broker implementation version 0
@@ -43,16 +44,24 @@ class BrokerServicesBase final : public
//
@@ -48,28 +49,35 @@ class BrokerServicesBase final : public
scoped_refptr<TargetPolicy> CreatePolicy() override;
ResultCode SpawnTarget(const wchar_t* exe_path,
const wchar_t* command_line,
@ -237,53 +217,58 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/broker_services.h b/secur
PROCESS_INFORMATION* target) override;
ResultCode WaitForAllTargets() override;
+ ResultCode AddTargetPeer(HANDLE peer_process) override;
+
+ // Checks if the supplied process ID matches one of the broker's active
+ // target processes. We use this method for the specific purpose of
+ // checking if we can safely duplicate a handle to the supplied process
+ // in DuplicateHandleProxyAction.
+ bool IsSafeDuplicationTarget(DWORD process_id);
+
ResultCode GetPolicyDiagnostics(
std::unique_ptr<PolicyDiagnosticsReceiver> receiver) override;
// Checks if the supplied process ID matches one of the broker's active
// target processes
// Returns:
// true if there is an active target process for this ID, otherwise false.
bool IsActiveTarget(DWORD process_id);
private:
+ typedef std::list<JobTracker*> JobTrackerList;
+ typedef std::map<DWORD, PeerTracker*> PeerTrackerMap;
+
// The routine that the worker thread executes. It is in charge of
// notifications and cleanup-related tasks.
static DWORD WINAPI TargetEventsThread(PVOID param);
@@ -65,14 +74,27 @@ class BrokerServicesBase final : public
+ // Removes a target peer from the process list if it expires.
+ static VOID CALLBACK RemovePeer(PVOID parameter, BOOLEAN timeout);
+
// The completion port used by the job objects to communicate events to
// the worker thread.
base::win::ScopedHandle job_port_;
// Handle to a manual-reset event that is signaled when the total target
// process count reaches zero.
base::win::ScopedHandle no_targets_;
// Handle to the worker thread that reacts to job notifications.
base::win::ScopedHandle job_thread_;
@@ -81,16 +89,20 @@ class BrokerServicesBase final : public
CRITICAL_SECTION lock_;
// Provides a pool of threads that are used to wait on the IPC calls.
std::unique_ptr<ThreadProvider> thread_pool_;
+ // The set representing the broker's active target processes including
+ // both sandboxed and unsandboxed peer processes.
+ std::set<DWORD> active_targets_;
+
+ // Lock used to protect active_targets_ from being simultaneously accessed
+ // by multiple threads.
+ CRITICAL_SECTION lock_;
+
+ ResultCode AddTargetPeerInternal(HANDLE peer_process_handle,
+ DWORD peer_process_id,
+ scoped_refptr<PolicyBase> policy_base,
+ DWORD* last_error);
// List of the trackers for closing and cleanup purposes.
std::list<std::unique_ptr<JobTracker>> tracker_list_;
+ // Maps peer process IDs to the saved handle and wait event.
+ // Prevents peer callbacks from accessing the broker after destruction.
+ PeerTrackerMap peer_map_;
+
// Provides a fast lookup to identify sandboxed processes that belong to a
// job. Consult |jobless_process_handles_| for handles of processes without
// jobs.
std::set<DWORD> child_process_ids_;
DISALLOW_COPY_AND_ASSIGN(BrokerServicesBase);
};
} // namespace sandbox
#endif // SANDBOX_WIN_SRC_BROKER_SERVICES_H_
diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox.h b/security/sandbox/chromium/sandbox/win/src/sandbox.h
--- a/security/sandbox/chromium/sandbox/win/src/sandbox.h
+++ b/security/sandbox/chromium/sandbox/win/src/sandbox.h
@@ -96,16 +96,24 @@ class BrokerServices {
@@ -86,16 +86,24 @@ class BrokerServices {
PROCESS_INFORMATION* target) = 0;
// This call blocks (waits) for all the targets to terminate.
// Returns:
@ -291,7 +276,7 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox.h b/security/sand
// If the return is ERROR_GENERIC, you can call ::GetLastError() to get
// more information.
virtual ResultCode WaitForAllTargets() = 0;
+
+ // Adds an unsandboxed process as a peer for policy decisions (e.g.
+ // HANDLES_DUP_ANY policy).
+ // Returns:
@ -299,12 +284,11 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox.h b/security/sand
+ // If the return is ERROR_GENERIC, you can call ::GetLastError() to get
+ // more information.
+ virtual ResultCode AddTargetPeer(HANDLE peer_process) = 0;
+
// This call creates a snapshot of policies managed by the sandbox and
// returns them via a helper class.
// Parameters:
// receiver: The |PolicyDiagnosticsReceiver| implementation will be
// called to accept the results of the call.
// Returns:
// ALL_OK if the request was dispatched. All other return values
// imply failure, and the responder will not receive its completion
protected:
~BrokerServices() {}
};
// TargetServices models the current process from the perspective
// of a target process. To obtain a pointer to it use
// Sandbox::GetTargetServices(). Note that this call returns a non-null

Просмотреть файл

@ -1,22 +1,18 @@
# HG changeset patch
# User Toshihito Kikuchi <tkikuchi@mozilla.com>
# Date 1589671733 25200
# Sat May 16 16:28:53 2020 -0700
# Node ID 91bb5c3807cfe657cc24c9a3c217dd1f57db6d5c
# Parent 22eb0bf7180801edf775be44cf299a50e01eb7bf
Reinstate sandbox::TargetServices::BrokerDuplicateHandle. r=bobowen
# User Bob Owen <bobowencode@gmail.com>
# Date 1485985575 0
# Wed Feb 01 21:46:15 2017 +0000
# Node ID 9328428e5f863472f3702057b01d472b46b7b6a2
# Parent 4c1880ac25a66dec6455dc88ba693096d65df704
Reinstate sandbox::TargetServices::BrokerDuplicateHandle. r=aklotz
This patch reverts the commit removing sandbox::TargetServices::BrokerDuplicateHandle
and applies the new IpcTag type.
https://chromium.googlesource.com/chromium/src.git/+/569193665184525ca366e65d0735f5c851106e43
https://chromium.googlesource.com/chromium/src.git/+/c8cff7f9663ce6d1ef35e5c717f43c867c3906eb
This basically reverts chromium commit 569193665184525ca366e65d0735f5c851106e43.
diff --git a/security/sandbox/chromium/sandbox/win/src/handle_dispatcher.cc b/security/sandbox/chromium/sandbox/win/src/handle_dispatcher.cc
new file mode 100644
--- /dev/null
+++ b/security/sandbox/chromium/sandbox/win/src/handle_dispatcher.cc
@@ -0,0 +1,93 @@
@@ -0,0 +1,92 @@
+// 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.
@ -41,7 +37,7 @@ new file mode 100644
+HandleDispatcher::HandleDispatcher(PolicyBase* policy_base)
+ : policy_base_(policy_base) {
+ static const IPCCall duplicate_handle_proxy = {
+ {IpcTag::DUPLICATEHANDLEPROXY,
+ {IPC_DUPLICATEHANDLEPROXY_TAG,
+ {VOIDPTR_TYPE, UINT32_TYPE, UINT32_TYPE, UINT32_TYPE}},
+ reinterpret_cast<CallbackGeneric>(
+ &HandleDispatcher::DuplicateHandleProxy)};
@ -50,15 +46,14 @@ new file mode 100644
+}
+
+bool HandleDispatcher::SetupService(InterceptionManager* manager,
+ IpcTag service) {
+ int service) {
+ // We perform no interceptions for handles right now.
+ switch (service) {
+ case IpcTag::DUPLICATEHANDLEPROXY:
+ return true;
+
+ default:
+ return false;
+ case IPC_DUPLICATEHANDLEPROXY_TAG:
+ return true;
+ }
+
+ return false;
+}
+
+bool HandleDispatcher::DuplicateHandleProxy(IPCInfo* ipc,
@ -98,7 +93,7 @@ new file mode 100644
+ params[HandleTarget::NAME] = ParamPickerMake(type_info->Name.Buffer);
+ params[HandleTarget::TARGET] = ParamPickerMake(target_process_id);
+
+ EvalResult eval = policy_base_->EvalPolicy(IpcTag::DUPLICATEHANDLEPROXY,
+ EvalResult eval = policy_base_->EvalPolicy(IPC_DUPLICATEHANDLEPROXY_TAG,
+ params.GetBase());
+ ipc->return_info.win32_result =
+ HandlePolicy::DuplicateHandleProxyAction(eval, handle.Get(),
@ -137,7 +132,7 @@ new file mode 100644
+ ~HandleDispatcher() override {}
+
+ // Dispatcher interface.
+ bool SetupService(InterceptionManager* manager, IpcTag service) override;
+ bool SetupService(InterceptionManager* manager, int service) override;
+
+ private:
+ // Processes IPC requests coming from calls to
@ -189,7 +184,7 @@ new file mode 100644
+
+ SharedMemIPCClient ipc(memory);
+ CrossCallReturn answer = {0};
+ ResultCode code = CrossCall(ipc, IpcTag::DUPLICATEHANDLEPROXY,
+ ResultCode code = CrossCall(ipc, IPC_DUPLICATEHANDLEPROXY_TAG,
+ source_handle, target_process_id,
+ desired_access, options, &answer);
+ if (SBOX_ALL_OK != code)
@ -239,7 +234,7 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/handle_policy.cc b/securi
new file mode 100644
--- /dev/null
+++ b/security/sandbox/chromium/sandbox/win/src/handle_policy.cc
@@ -0,0 +1,93 @@
@@ -0,0 +1,92 @@
+// 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.
@ -287,7 +282,7 @@ new file mode 100644
+ CASE_INSENSITIVE)) {
+ return false;
+ }
+ if (!policy->AddRule(IpcTag::DUPLICATEHANDLEPROXY, &duplicate_rule)) {
+ if (!policy->AddRule(IPC_DUPLICATEHANDLEPROXY_TAG, &duplicate_rule)) {
+ return false;
+ }
+ return true;
@ -307,8 +302,7 @@ new file mode 100644
+ base::win::ScopedHandle remote_target_process;
+ if (target_process_id != ::GetCurrentProcessId()) {
+ // Sandboxed children are dynamic, so we check that manually.
+ if (!BrokerServicesBase::GetInstance()->IsSafeDuplicationTarget(
+ target_process_id)) {
+ if (!BrokerServicesBase::GetInstance()->IsActiveTarget(target_process_id)) {
+ return ERROR_ACCESS_DENIED;
+ }
+
@ -499,28 +493,29 @@ new file mode 100644
diff --git a/security/sandbox/chromium/sandbox/win/src/ipc_tags.h b/security/sandbox/chromium/sandbox/win/src/ipc_tags.h
--- a/security/sandbox/chromium/sandbox/win/src/ipc_tags.h
+++ b/security/sandbox/chromium/sandbox/win/src/ipc_tags.h
@@ -23,16 +23,17 @@ enum class IpcTag {
NTOPENPROCESS,
NTOPENPROCESSTOKEN,
NTOPENPROCESSTOKENEX,
CREATEPROCESSW,
CREATEEVENT,
OPENEVENT,
NTCREATEKEY,
NTOPENKEY,
+ DUPLICATEHANDLEPROXY,
GDI_GDIDLLINITIALIZE,
GDI_GETSTOCKOBJECT,
USER_REGISTERCLASSW,
CREATETHREAD,
USER_ENUMDISPLAYMONITORS,
USER_ENUMDISPLAYDEVICES,
USER_GETMONITORINFO,
GDI_CREATEOPMPROTECTEDOUTPUTS,
@@ -23,16 +23,17 @@ enum {
IPC_NTOPENPROCESS_TAG,
IPC_NTOPENPROCESSTOKEN_TAG,
IPC_NTOPENPROCESSTOKENEX_TAG,
IPC_CREATEPROCESSW_TAG,
IPC_CREATEEVENT_TAG,
IPC_OPENEVENT_TAG,
IPC_NTCREATEKEY_TAG,
IPC_NTOPENKEY_TAG,
+ IPC_DUPLICATEHANDLEPROXY_TAG,
IPC_GDI_GDIDLLINITIALIZE_TAG,
IPC_GDI_GETSTOCKOBJECT_TAG,
IPC_USER_REGISTERCLASSW_TAG,
IPC_CREATETHREAD_TAG,
IPC_USER_ENUMDISPLAYMONITORS_TAG,
IPC_USER_ENUMDISPLAYDEVICES_TAG,
IPC_USER_GETMONITORINFO_TAG,
IPC_GDI_CREATEOPMPROTECTEDOUTPUTS_TAG,
diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox.h b/security/sandbox/chromium/sandbox/win/src/sandbox.h
--- a/security/sandbox/chromium/sandbox/win/src/sandbox.h
+++ b/security/sandbox/chromium/sandbox/win/src/sandbox.h
@@ -161,16 +161,30 @@ class TargetServices {
@@ -136,16 +136,30 @@ class TargetServices {
// processing any untrusted data or running third-party code. If this call
// fails the current process could be terminated immediately.
virtual void LowerToken() = 0;
@ -528,7 +523,7 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox.h b/security/sand
// information about the current state of the process, such as whether
// LowerToken has been called or not.
virtual ProcessState* GetState() = 0;
+
+ // Requests the broker to duplicate the supplied handle into the target
+ // process. The target process must be an active sandbox child process
+ // and the source process must have a corresponding policy allowing
@ -542,30 +537,28 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox.h b/security/sand
+ HANDLE* target_handle,
+ DWORD desired_access,
+ DWORD options) = 0;
+
protected:
~TargetServices() {}
};
class PolicyInfo {
public:
// Returns a JSON representation of the policy snapshot.
// This pointer has the same lifetime as this PolicyInfo object.
} // namespace sandbox
diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_policy.h b/security/sandbox/chromium/sandbox/win/src/sandbox_policy.h
--- a/security/sandbox/chromium/sandbox/win/src/sandbox_policy.h
+++ b/security/sandbox/chromium/sandbox/win/src/sandbox_policy.h
@@ -25,28 +25,32 @@ class TargetPolicy {
@@ -24,27 +24,31 @@ class TargetPolicy {
// exactly like the CreateProcess API does. See the comment at the top of
// process_thread_dispatcher.cc for more details.
enum SubSystem {
SUBSYS_FILES, // Creation and opening of files and pipes.
SUBSYS_NAMED_PIPES, // Creation of named pipes.
SUBSYS_PROCESS, // Creation of child processes.
SUBSYS_REGISTRY, // Creation and opening of registry keys.
SUBSYS_SYNC, // Creation of named sync objects.
+ SUBSYS_HANDLES, // Duplication of handles to other processes.
SUBSYS_WIN32K_LOCKDOWN, // Win32K Lockdown related policy.
SUBSYS_SIGNED_BINARY // Signed binary policy.
SUBSYS_FILES, // Creation and opening of files and pipes.
SUBSYS_NAMED_PIPES, // Creation of named pipes.
SUBSYS_PROCESS, // Creation of child processes.
SUBSYS_REGISTRY, // Creation and opening of registry keys.
SUBSYS_SYNC, // Creation of named sync objects.
+ SUBSYS_HANDLES, // Duplication of handles to other processes.
SUBSYS_WIN32K_LOCKDOWN // Win32K Lockdown related policy.
};
// Allowable semantics when a rule is matched.
@ -590,14 +583,14 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_policy.h b/securi
diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc b/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc
--- a/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc
+++ b/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc
@@ -12,16 +12,17 @@
@@ -10,16 +10,17 @@
#include "base/callback.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "base/win/win_util.h"
#include "base/win/windows_version.h"
#include "sandbox/win/src/acl.h"
#include "sandbox/win/src/filesystem_policy.h"
+#include "sandbox/win/src/handle_policy.h"
#include "sandbox/win/src/interception.h"
@ -608,7 +601,7 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc b/
#include "sandbox/win/src/policy_low_level.h"
#include "sandbox/win/src/process_mitigations.h"
#include "sandbox/win/src/process_mitigations_win32k_policy.h"
@@ -754,16 +755,24 @@ ResultCode PolicyBase::AddRuleInternal(S
@@ -733,16 +734,24 @@ ResultCode PolicyBase::AddRuleInternal(S
}
case SUBSYS_REGISTRY: {
if (!RegistryPolicy::GenerateRules(pattern, semantics, policy_maker_)) {
@ -626,13 +619,13 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc b/
+ }
+
case SUBSYS_WIN32K_LOCKDOWN: {
// Win32k intercept rules only supported on Windows 8 and above. This must
// match the version checks in process_mitigations.cc for consistency.
if (base::win::GetVersion() >= base::win::Version::WIN8) {
DCHECK_EQ(MITIGATION_WIN32K_DISABLE,
mitigations_ & MITIGATION_WIN32K_DISABLE)
<< "Enable MITIGATION_WIN32K_DISABLE before adding win32k policy "
"rules.";
if (!ProcessMitigationsWin32KLockdownPolicy::GenerateRules(
pattern, semantics, policy_maker_)) {
NOTREACHED();
return SBOX_ERROR_BAD_PARAMS;
}
break;
}
diff --git a/security/sandbox/chromium/sandbox/win/src/target_services.cc b/security/sandbox/chromium/sandbox/win/src/target_services.cc
--- a/security/sandbox/chromium/sandbox/win/src/target_services.cc
+++ b/security/sandbox/chromium/sandbox/win/src/target_services.cc
@ -654,9 +647,9 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/target_services.cc b/secu
#include "sandbox/win/src/sandbox_nt_util.h"
#include "sandbox/win/src/sandbox_types.h"
#include "sandbox/win/src/sharedmem_ipc_client.h"
@@ -239,9 +240,19 @@ void ProcessState::SetRevertedToSelf() {
if (process_state_ < ProcessStateInternal::REVERTED_TO_SELF)
process_state_ = ProcessStateInternal::REVERTED_TO_SELF;
@@ -259,9 +260,19 @@ void ProcessState::SetRevertedToSelf() {
if (process_state_ < 3)
process_state_ = 3;
}
void ProcessState::SetCsrssConnected(bool csrss_connected) {
@ -677,7 +670,7 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/target_services.cc b/secu
diff --git a/security/sandbox/chromium/sandbox/win/src/target_services.h b/security/sandbox/chromium/sandbox/win/src/target_services.h
--- a/security/sandbox/chromium/sandbox/win/src/target_services.h
+++ b/security/sandbox/chromium/sandbox/win/src/target_services.h
@@ -40,16 +40,21 @@ class ProcessState {
@@ -41,16 +41,21 @@ class ProcessState {
class TargetServicesBase : public TargetServices {
public:
TargetServicesBase();
@ -720,24 +713,24 @@ diff --git a/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.cc b
#include "sandbox/win/src/process_thread_dispatcher.h"
#include "sandbox/win/src/registry_dispatcher.h"
#include "sandbox/win/src/sandbox_policy_base.h"
@@ -55,16 +56,20 @@ TopLevelDispatcher::TopLevelDispatcher(P
ipc_targets_[static_cast<size_t>(IpcTag::OPENEVENT)] = dispatcher;
@@ -53,16 +54,20 @@ TopLevelDispatcher::TopLevelDispatcher(P
ipc_targets_[IPC_OPENEVENT_TAG] = dispatcher;
sync_dispatcher_.reset(dispatcher);
dispatcher = new RegistryDispatcher(policy_);
ipc_targets_[static_cast<size_t>(IpcTag::NTCREATEKEY)] = dispatcher;
ipc_targets_[static_cast<size_t>(IpcTag::NTOPENKEY)] = dispatcher;
ipc_targets_[IPC_NTCREATEKEY_TAG] = dispatcher;
ipc_targets_[IPC_NTOPENKEY_TAG] = dispatcher;
registry_dispatcher_.reset(dispatcher);
+ dispatcher = new HandleDispatcher(policy_);
+ ipc_targets_[static_cast<size_t>(IpcTag::DUPLICATEHANDLEPROXY)] = dispatcher;
+ ipc_targets_[IPC_DUPLICATEHANDLEPROXY_TAG] = dispatcher;
+ handle_dispatcher_.reset(dispatcher);
+
dispatcher = new ProcessMitigationsWin32KDispatcher(policy_);
ipc_targets_[static_cast<size_t>(IpcTag::GDI_GDIDLLINITIALIZE)] = dispatcher;
ipc_targets_[static_cast<size_t>(IpcTag::GDI_GETSTOCKOBJECT)] = dispatcher;
ipc_targets_[static_cast<size_t>(IpcTag::USER_REGISTERCLASSW)] = dispatcher;
ipc_targets_[static_cast<size_t>(IpcTag::USER_ENUMDISPLAYMONITORS)] =
dispatcher;
ipc_targets_[static_cast<size_t>(IpcTag::USER_ENUMDISPLAYDEVICES)] =
dispatcher;
ipc_targets_[IPC_GDI_GDIDLLINITIALIZE_TAG] = dispatcher;
ipc_targets_[IPC_GDI_GETSTOCKOBJECT_TAG] = dispatcher;
ipc_targets_[IPC_USER_REGISTERCLASSW_TAG] = dispatcher;
ipc_targets_[IPC_USER_ENUMDISPLAYMONITORS_TAG] = dispatcher;
ipc_targets_[IPC_USER_ENUMDISPLAYDEVICES_TAG] = dispatcher;
ipc_targets_[IPC_USER_GETMONITORINFO_TAG] = dispatcher;
ipc_targets_[IPC_GDI_CREATEOPMPROTECTEDOUTPUTS_TAG] = dispatcher;

Просмотреть файл

@ -0,0 +1,93 @@
# HG changeset patch
# User Gian-Carlo Pascutto <gcp@mozilla.com>
# Date 1465410964 -7200
# Wed Jun 08 20:36:04 2016 +0200
# Node ID 37ac7119fe8df776c850624a9a95dd182ff469b0
# Parent 5d0dab9cddb8410f891f22a1bead1c1975adb5bd
Update chromium's list of linux-x86-32 syscalls. r=jld
Originally landed as changset:
https://hg.mozilla.org/mozilla-central/rev/adb1d2a92e0d
diff --git a/security/sandbox/chromium/sandbox/linux/system_headers/x86_32_linux_syscalls.h b/security/sandbox/chromium/sandbox/linux/system_headers/x86_32_linux_syscalls.h
--- a/security/sandbox/chromium/sandbox/linux/system_headers/x86_32_linux_syscalls.h
+++ b/security/sandbox/chromium/sandbox/linux/system_headers/x86_32_linux_syscalls.h
@@ -1417,10 +1417,78 @@
#if !defined(__NR_getrandom)
#define __NR_getrandom 355
#endif
#if !defined(__NR_memfd_create)
#define __NR_memfd_create 356
#endif
+#if !defined(__NR_bpf)
+#define __NR_bpf 357
+#endif
+
+#if !defined(__NR_execveat)
+#define __NR_execveat 358
+#endif
+
+#if !defined(__NR_socket)
+#define __NR_socket 359
+#endif
+
+#if !defined(__NR_socketpair)
+#define __NR_socketpair 360
+#endif
+
+#if !defined(__NR_bind)
+#define __NR_bind 361
+#endif
+
+#if !defined(__NR_connect)
+#define __NR_connect 362
+#endif
+
+#if !defined(__NR_listen)
+#define __NR_listen 363
+#endif
+
+#if !defined(__NR_accept4)
+#define __NR_accept4 364
+#endif
+
+#if !defined(__NR_getsockopt)
+#define __NR_getsockopt 365
+#endif
+
+#if !defined(__NR_setsockopt)
+#define __NR_setsockopt 366
+#endif
+
+#if !defined(__NR_getsockname)
+#define __NR_getsockname 367
+#endif
+
+#if !defined(__NR_getpeername)
+#define __NR_getpeername 368
+#endif
+
+#if !defined(__NR_sendto)
+#define __NR_sendto 369
+#endif
+
+#if !defined(__NR_sendmsg)
+#define __NR_sendmsg 370
+#endif
+
+#if !defined(__NR_recvfrom)
+#define __NR_recvfrom 371
+#endif
+
+#if !defined(__NR_recvmsg)
+#define __NR_recvmsg 372
+#endif
+
+#if !defined(__NR_shutdown)
+#define __NR_shutdown 373
+#endif
+
#endif // SANDBOX_LINUX_SYSTEM_HEADERS_X86_32_LINUX_SYSCALLS_H_

Просмотреть файл

@ -1,31 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// This is a partial implementation of Chromium's source file
// //sandbox/win/src/sandbox_policy_diagnostic.h
#ifndef SANDBOX_WIN_SRC_SANDBOX_POLICY_DIAGNOSTIC_H_
#define SANDBOX_WIN_SRC_SANDBOX_POLICY_DIAGNOSTIC_H_
#include "mozilla/Assertions.h"
namespace sandbox {
class PolicyBase;
class PolicyDiagnostic final : public PolicyInfo {
public:
PolicyDiagnostic(PolicyBase*) {}
~PolicyDiagnostic() override = default;
const char* JsonString() override { MOZ_CRASH(); }
private:
DISALLOW_COPY_AND_ASSIGN(PolicyDiagnostic);
};
} // namespace sandbox
#endif // SANDBOX_WIN_SRC_SANDBOX_POLICY_DIAGNOSTIC_H_

Просмотреть файл

@ -48,11 +48,11 @@ AtExitManager::~AtExitManager() {
// static
void AtExitManager::RegisterCallback(AtExitCallbackType func, void* param) {
DCHECK(func);
RegisterTask(base::BindOnce(func, param));
RegisterTask(base::Bind(func, param));
}
// static
void AtExitManager::RegisterTask(base::OnceClosure task) {
void AtExitManager::RegisterTask(base::Closure task) {
if (!g_top_manager) {
NOTREACHED() << "Tried to RegisterCallback without an AtExitManager";
return;
@ -75,7 +75,7 @@ void AtExitManager::ProcessCallbacksNow() {
// Callbacks may try to add new callbacks, so run them without holding
// |lock_|. This is an error and caught by the DCHECK in RegisterTask(), but
// handle it gracefully in release builds so we don't deadlock.
base::stack<base::OnceClosure> tasks;
base::stack<base::Closure> tasks;
{
AutoLock lock(g_top_manager->lock_);
tasks.swap(g_top_manager->stack_);
@ -89,7 +89,8 @@ void AtExitManager::ProcessCallbacksNow() {
ScopedAllowCrossThreadRefCountAccess allow_cross_thread_ref_count_access;
while (!tasks.empty()) {
std::move(tasks.top()).Run();
base::Closure task = tasks.top();
task.Run();
tasks.pop();
}

Просмотреть файл

@ -43,7 +43,7 @@ class BASE_EXPORT AtExitManager {
static void RegisterCallback(AtExitCallbackType func, void* param);
// Registers the specified task to be called at exit.
static void RegisterTask(base::OnceClosure task);
static void RegisterTask(base::Closure task);
// Calls the functions registered with RegisterCallback in LIFO order. It
// is possible to register new callbacks after calling this function.
@ -63,7 +63,7 @@ class BASE_EXPORT AtExitManager {
private:
base::Lock lock_;
base::stack<base::OnceClosure> stack_ GUARDED_BY(lock_);
base::stack<base::Closure> stack_ GUARDED_BY(lock_);
#if DCHECK_IS_ON()
bool processing_callbacks_ GUARDED_BY(lock_) = false;

Просмотреть файл

@ -39,6 +39,15 @@
#include "base/base_export.h"
#include "build/build_config.h"
#if defined(OS_WIN) && (defined(ARCH_CPU_64_BITS) || defined(__MINGW32__))
// windows.h #defines this (only on x64). This causes problems because the
// public API also uses MemoryBarrier at the public name for this fence. So, on
// X64, undef it, and call its documented
// (http://msdn.microsoft.com/en-us/library/windows/desktop/ms684208.aspx)
// implementation directly.
#undef MemoryBarrier
#endif
namespace base {
namespace subtle {
@ -91,7 +100,8 @@ Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
// ensure that no later memory access can be reordered ahead of the operation.
// "Release" operations ensure that no previous memory access can be reordered
// after the operation. "Barrier" operations have both "Acquire" and "Release"
// semantics.
// semantics. A MemoryBarrier() has "Barrier" semantics, but does no memory
// access.
Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value);
@ -99,6 +109,7 @@ Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value);
void MemoryBarrier();
void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value);
void Acquire_Store(volatile Atomic32* ptr, Atomic32 value);
void Release_Store(volatile Atomic32* ptr, Atomic32 value);

Просмотреть файл

@ -52,6 +52,16 @@ typedef volatile std::atomic<Atomic32>* AtomicLocation32;
static_assert(sizeof(*(AtomicLocation32) nullptr) == sizeof(Atomic32),
"incompatible 32-bit atomic layout");
inline void MemoryBarrier() {
#if defined(__GLIBCXX__)
// Work around libstdc++ bug 51038 where atomic_thread_fence was declared but
// not defined, leading to the linker complaining about undefined references.
__atomic_thread_fence(std::memory_order_seq_cst);
#else
std::atomic_thread_fence(std::memory_order_seq_cst);
#endif
}
inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
@ -109,7 +119,7 @@ inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
((AtomicLocation32)ptr)->store(value, std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_seq_cst);
MemoryBarrier();
}
inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
@ -125,7 +135,7 @@ inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
}
inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
std::atomic_thread_fence(std::memory_order_seq_cst);
MemoryBarrier();
return ((AtomicLocation32)ptr)->load(std::memory_order_relaxed);
}
@ -192,7 +202,7 @@ inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
((AtomicLocation64)ptr)->store(value, std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_seq_cst);
MemoryBarrier();
}
inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
@ -208,7 +218,7 @@ inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
}
inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
std::atomic_thread_fence(std::memory_order_seq_cst);
MemoryBarrier();
return ((AtomicLocation64)ptr)->load(std::memory_order_relaxed);
}

Просмотреть файл

@ -11,11 +11,18 @@
#include <intrin.h>
#include <atomic>
#include "base/macros.h"
#include "build/build_config.h"
#if defined(ARCH_CPU_64_BITS) || defined(__MINGW32__)
// windows.h #defines this (only on x64). This causes problems because the
// public API also uses MemoryBarrier at the public name for this fence. So, on
// X64, undef it, and call its documented
// (http://msdn.microsoft.com/en-us/library/windows/desktop/ms684208.aspx)
// implementation directly.
#undef MemoryBarrier
#endif
namespace base {
namespace subtle {
@ -49,6 +56,18 @@ inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
return Barrier_AtomicIncrement(ptr, increment);
}
inline void MemoryBarrier() {
#if defined(ARCH_CPU_64_BITS)
// See #undef and note at the top of this file.
__faststorefence();
#else
// We use the implementation of MemoryBarrier from WinNT.h
LONG barrier;
_InterlockedOr(&barrier, 0);
#endif
}
inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
@ -85,7 +104,7 @@ inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
}
inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
std::atomic_thread_fence(std::memory_order_seq_cst);
MemoryBarrier();
return *ptr;
}
@ -154,7 +173,7 @@ inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
}
inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
std::atomic_thread_fence(std::memory_order_seq_cst);
MemoryBarrier();
return *ptr;
}

Просмотреть файл

@ -7,7 +7,7 @@
namespace switches {
// Delays execution of TaskPriority::BEST_EFFORT tasks until shutdown.
// Delays execution of base::TaskPriority::BEST_EFFORT tasks until shutdown.
const char kDisableBestEffortTasks[] = "disable-best-effort-tasks";
// Disables the crash reporting.
@ -16,9 +16,6 @@ const char kDisableBreakpad[] = "disable-breakpad";
// Comma-separated list of feature names to disable. See also kEnableFeatures.
const char kDisableFeatures[] = "disable-features";
// Force disabling of low-end device mode when set.
const char kDisableLowEndDeviceMode[] = "disable-low-end-device-mode";
// Indicates that crash reporting should be enabled. On platforms where helper
// processes cannot access to files needed to make this decision, this flag is
// generated internally.
@ -27,9 +24,15 @@ const char kEnableCrashReporter[] = "enable-crash-reporter";
// Comma-separated list of feature names to enable. See also kDisableFeatures.
const char kEnableFeatures[] = "enable-features";
// Generates full memory crash dump.
const char kFullMemoryCrashReport[] = "full-memory-crash-report";
// Force low-end device mode when set.
const char kEnableLowEndDeviceMode[] = "enable-low-end-device-mode";
// Force disabling of low-end device mode when set.
const char kDisableLowEndDeviceMode[] = "disable-low-end-device-mode";
// This option can be used to force field trials when testing changes locally.
// The argument is a list of name and value pairs, separated by slashes. If a
// trial name is prefixed with an asterisk, that trial will start activated.
@ -40,19 +43,44 @@ const char kEnableLowEndDeviceMode[] = "enable-low-end-device-mode";
// FieldTrialList::CreateTrialsFromString() in field_trial.h for details.
const char kForceFieldTrials[] = "force-fieldtrials";
// Generates full memory crash dump.
const char kFullMemoryCrashReport[] = "full-memory-crash-report";
// Logs information about all tasks posted with TaskPriority::BEST_EFFORT. Use
// this to diagnose issues that are thought to be caused by
// TaskPriority::BEST_EFFORT execution fences. Note: Tasks posted to a
// non-BEST_EFFORT UpdateableSequencedTaskRunner whose priority is later lowered
// to BEST_EFFORT are not logged.
const char kLogBestEffortTasks[] = "log-best-effort-tasks";
// Suppresses all error dialogs when present.
const char kNoErrorDialogs[] = "noerrdialogs";
// When running certain tests that spawn child processes, this switch indicates
// to the test framework that the current process is a child process.
const char kTestChildProcess[] = "test-child-process";
// When running certain tests that spawn child processes, this switch indicates
// to the test framework that the current process should not initialize ICU to
// avoid creating any scoped handles too early in startup.
const char kTestDoNotInitializeIcu[] = "test-do-not-initialize-icu";
// Gives the default maximal active V-logging level; 0 is the default.
// Normally positive values are used for V-logging levels.
const char kV[] = "v";
// Gives the per-module maximal V-logging levels to override the value
// given by --v. E.g. "my_module=2,foo*=3" would change the logging
// level for all code in source files "my_module.*" and "foo*.*"
// ("-inl" suffixes are also disregarded for this matching).
//
// Any pattern containing a forward or backward slash will be tested
// against the whole pathname and not just the module. E.g.,
// "*/foo/bar/*=2" would change the logging level for all code in
// source files under a "foo/bar" directory.
const char kVModule[] = "vmodule";
// Will wait for 60 seconds for a debugger to come to attach to the process.
const char kWaitForDebugger[] = "wait-for-debugger";
// Sends trace events from these categories to a file.
// --trace-to-file on its own sends to default categories.
const char kTraceToFile[] = "trace-to-file";
// Specifies the file name for --trace-to-file. If unspecified, it will
// go to a default file name.
const char kTraceToFileName[] = "trace-to-file-name";
// Starts the sampling based profiler for the browser process at startup. This
// will only work if chrome has been built with the gn arg enable_profiling =
// true. The output will go to the value of kProfilingFile.
@ -74,45 +102,7 @@ const char kProfilingFile[] = "profiling-file";
// specified.
const char kProfilingFlush[] = "profiling-flush";
// When running certain tests that spawn child processes, this switch indicates
// to the test framework that the current process is a child process.
const char kTestChildProcess[] = "test-child-process";
// When running certain tests that spawn child processes, this switch indicates
// to the test framework that the current process should not initialize ICU to
// avoid creating any scoped handles too early in startup.
const char kTestDoNotInitializeIcu[] = "test-do-not-initialize-icu";
// Sends trace events from these categories to a file.
// --trace-to-file on its own sends to default categories.
const char kTraceToFile[] = "trace-to-file";
// Specifies the file name for --trace-to-file. If unspecified, it will
// go to a default file name.
const char kTraceToFileName[] = "trace-to-file-name";
// Gives the default maximal active V-logging level; 0 is the default.
// Normally positive values are used for V-logging levels.
const char kV[] = "v";
// Gives the per-module maximal V-logging levels to override the value
// given by --v. E.g. "my_module=2,foo*=3" would change the logging
// level for all code in source files "my_module.*" and "foo*.*"
// ("-inl" suffixes are also disregarded for this matching).
//
// Any pattern containing a forward or backward slash will be tested
// against the whole pathname and not just the module. E.g.,
// "*/foo/bar/*=2" would change the logging level for all code in
// source files under a "foo/bar" directory.
const char kVModule[] = "vmodule";
// Will wait for 60 seconds for a debugger to come to attach to the process.
const char kWaitForDebugger[] = "wait-for-debugger";
#if defined(OS_WIN)
// Disable high-resolution timer on Windows.
const char kDisableHighResTimer[] = "disable-highres-timer";
// Disables the USB keyboard detection for blocking the OSK on Win8+.
const char kDisableUsbKeyboardDetect[] = "disable-usb-keyboard-detect";
#endif
@ -136,14 +126,17 @@ const char kEnableCrashReporterForTesting[] =
// Enables the reached code profiler that samples all threads in all processes
// to determine which functions are almost never executed.
const char kEnableReachedCodeProfiler[] = "enable-reached-code-profiler";
#endif
#if defined(OS_LINUX)
// Controls whether or not retired instruction counts are surfaced for threads
// in trace events on Linux.
// Specifies optimization of memory layout of the native library using the
// orderfile symbols given in base/android/library_loader/anchor_functions.h,
// via madvise and changing the library prefetch behavior.
//
// This flag requires the BPF sandbox to be disabled.
const char kEnableThreadInstructionCount[] = "enable-thread-instruction-count";
// If this switch is not specified, an optimization may be done depending on a
// synthetic trial. If specified, its values may be 'on' or 'off'. These
// override the synthetic trial.
//
// This flag is only used on architectures with SUPPORTS_CODE_ORDERING defined.
const char kOrderfileMemoryOptimization[] = "orderfile-memory-optimization";
#endif
} // namespace switches

Просмотреть файл

@ -20,7 +20,6 @@ extern const char kEnableFeatures[];
extern const char kEnableLowEndDeviceMode[];
extern const char kForceFieldTrials[];
extern const char kFullMemoryCrashReport[];
extern const char kLogBestEffortTasks[];
extern const char kNoErrorDialogs[];
extern const char kProfilingAtStart[];
extern const char kProfilingFile[];
@ -34,7 +33,6 @@ extern const char kVModule[];
extern const char kWaitForDebugger[];
#if defined(OS_WIN)
extern const char kDisableHighResTimer[];
extern const char kDisableUsbKeyboardDetect[];
#endif
@ -51,10 +49,6 @@ extern const char kEnableReachedCodeProfiler[];
extern const char kOrderfileMemoryOptimization[];
#endif
#if defined(OS_LINUX)
extern const char kEnableThreadInstructionCount[];
#endif
} // namespace switches
#endif // BASE_BASE_SWITCHES_H_

Просмотреть файл

@ -7,7 +7,6 @@
#include <functional>
#include <memory>
#include <type_traits>
#include <utility>
#include "base/bind_internal.h"
@ -42,7 +41,7 @@
// class C : public base::RefCounted<C> { void F(); };
// auto instance = base::MakeRefCounted<C>();
// auto cb = base::BindOnce(&C::F, instance);
// std::move(cb).Run(); // Identical to instance->F()
// cb.Run(); // Identical to instance->F()
//
// base::Bind is currently a type alias for base::BindRepeating(). In the
// future, we expect to flip this to default to base::BindOnce().
@ -180,36 +179,26 @@ template <bool is_once, bool is_method, typename... Args>
using MakeUnwrappedTypeList =
typename MakeUnwrappedTypeListImpl<is_once, is_method, Args...>::Type;
// Used below in BindImpl to determine whether to use Invoker::Run or
// Invoker::RunOnce.
// Note: Simply using `kIsOnce ? &Invoker::RunOnce : &Invoker::Run` does not
// work, since the compiler needs to check whether both expressions are
// well-formed. Using `Invoker::Run` with a OnceCallback triggers a
// static_assert, which is why the ternary expression does not compile.
// TODO(crbug.com/752720): Remove this indirection once we have `if constexpr`.
template <typename Invoker>
constexpr auto GetInvokeFunc(std::true_type) {
return Invoker::RunOnce;
}
} // namespace internal
template <typename Invoker>
constexpr auto GetInvokeFunc(std::false_type) {
return Invoker::Run;
}
// Bind as OnceCallback.
template <typename Functor, typename... Args>
inline OnceCallback<MakeUnboundRunType<Functor, Args...>>
BindOnce(Functor&& functor, Args&&... args) {
static_assert(!internal::IsOnceCallback<std::decay_t<Functor>>() ||
(std::is_rvalue_reference<Functor&&>() &&
!std::is_const<std::remove_reference_t<Functor>>()),
"BindOnce requires non-const rvalue for OnceCallback binding."
" I.e.: base::BindOnce(std::move(callback)).");
template <template <typename> class CallbackT,
typename Functor,
typename... Args>
decltype(auto) BindImpl(Functor&& functor, Args&&... args) {
// This block checks if each |args| matches to the corresponding params of the
// target function. This check does not affect the behavior of Bind, but its
// error message should be more readable.
static constexpr bool kIsOnce = IsOnceCallback<CallbackT<void()>>::value;
using Helper = internal::BindTypeHelper<Functor, Args...>;
using FunctorTraits = typename Helper::FunctorTraits;
using BoundArgsList = typename Helper::BoundArgsList;
using UnwrappedArgsList =
internal::MakeUnwrappedTypeList<kIsOnce, FunctorTraits::is_method,
internal::MakeUnwrappedTypeList<true, FunctorTraits::is_method,
Args&&...>;
using BoundParamsList = typename Helper::BoundParamsList;
static_assert(internal::AssertBindArgsValidity<
@ -220,14 +209,13 @@ decltype(auto) BindImpl(Functor&& functor, Args&&... args) {
using BindState = internal::MakeBindStateType<Functor, Args...>;
using UnboundRunType = MakeUnboundRunType<Functor, Args...>;
using Invoker = internal::Invoker<BindState, UnboundRunType>;
using CallbackType = CallbackT<UnboundRunType>;
using CallbackType = OnceCallback<UnboundRunType>;
// Store the invoke func into PolymorphicInvoke before casting it to
// InvokeFuncStorage, so that we can ensure its type matches to
// PolymorphicInvoke, to which CallbackType will cast back.
using PolymorphicInvoke = typename CallbackType::PolymorphicInvoke;
PolymorphicInvoke invoke_func =
GetInvokeFunc<Invoker>(std::integral_constant<bool, kIsOnce>());
PolymorphicInvoke invoke_func = &Invoker::RunOnce;
using InvokeFuncStorage = internal::BindStateBase::InvokeFuncStorage;
return CallbackType(BindState::Create(
@ -235,23 +223,6 @@ decltype(auto) BindImpl(Functor&& functor, Args&&... args) {
std::forward<Functor>(functor), std::forward<Args>(args)...));
}
} // namespace internal
// Bind as OnceCallback.
template <typename Functor, typename... Args>
inline OnceCallback<MakeUnboundRunType<Functor, Args...>> BindOnce(
Functor&& functor,
Args&&... args) {
static_assert(!internal::IsOnceCallback<std::decay_t<Functor>>() ||
(std::is_rvalue_reference<Functor&&>() &&
!std::is_const<std::remove_reference_t<Functor>>()),
"BindOnce requires non-const rvalue for OnceCallback binding."
" I.e.: base::BindOnce(std::move(callback)).");
return internal::BindImpl<OnceCallback>(std::forward<Functor>(functor),
std::forward<Args>(args)...);
}
// Bind as RepeatingCallback.
template <typename Functor, typename... Args>
inline RepeatingCallback<MakeUnboundRunType<Functor, Args...>>
@ -260,8 +231,36 @@ BindRepeating(Functor&& functor, Args&&... args) {
!internal::IsOnceCallback<std::decay_t<Functor>>(),
"BindRepeating cannot bind OnceCallback. Use BindOnce with std::move().");
return internal::BindImpl<RepeatingCallback>(std::forward<Functor>(functor),
std::forward<Args>(args)...);
// This block checks if each |args| matches to the corresponding params of the
// target function. This check does not affect the behavior of Bind, but its
// error message should be more readable.
using Helper = internal::BindTypeHelper<Functor, Args...>;
using FunctorTraits = typename Helper::FunctorTraits;
using BoundArgsList = typename Helper::BoundArgsList;
using UnwrappedArgsList =
internal::MakeUnwrappedTypeList<false, FunctorTraits::is_method,
Args&&...>;
using BoundParamsList = typename Helper::BoundParamsList;
static_assert(internal::AssertBindArgsValidity<
std::make_index_sequence<Helper::num_bounds>, BoundArgsList,
UnwrappedArgsList, BoundParamsList>::ok,
"The bound args need to be convertible to the target params.");
using BindState = internal::MakeBindStateType<Functor, Args...>;
using UnboundRunType = MakeUnboundRunType<Functor, Args...>;
using Invoker = internal::Invoker<BindState, UnboundRunType>;
using CallbackType = RepeatingCallback<UnboundRunType>;
// Store the invoke func into PolymorphicInvoke before casting it to
// InvokeFuncStorage, so that we can ensure its type matches to
// PolymorphicInvoke, to which CallbackType will cast back.
using PolymorphicInvoke = typename CallbackType::PolymorphicInvoke;
PolymorphicInvoke invoke_func = &Invoker::Run;
using InvokeFuncStorage = internal::BindStateBase::InvokeFuncStorage;
return CallbackType(BindState::Create(
reinterpret_cast<InvokeFuncStorage>(invoke_func),
std::forward<Functor>(functor), std::forward<Args>(args)...));
}
// Unannotated Bind.
@ -276,27 +275,22 @@ Bind(Functor&& functor, Args&&... args) {
// Special cases for binding to a base::Callback without extra bound arguments.
template <typename Signature>
OnceCallback<Signature> BindOnce(OnceCallback<Signature> callback) {
return callback;
}
template <typename Signature>
OnceCallback<Signature> BindOnce(RepeatingCallback<Signature> callback) {
return callback;
OnceCallback<Signature> BindOnce(OnceCallback<Signature> closure) {
return closure;
}
template <typename Signature>
RepeatingCallback<Signature> BindRepeating(
RepeatingCallback<Signature> callback) {
return callback;
RepeatingCallback<Signature> closure) {
return closure;
}
template <typename Signature>
Callback<Signature> Bind(Callback<Signature> callback) {
return callback;
Callback<Signature> Bind(Callback<Signature> closure) {
return closure;
}
// Unretained() allows binding a non-refcounted class, and to disable
// Unretained() allows Bind() to bind a non-refcounted class, and to disable
// refcounting on arguments that are refcounted objects.
//
// EXAMPLE OF Unretained():
@ -308,9 +302,9 @@ Callback<Signature> Bind(Callback<Signature> callback) {
//
// // In some function somewhere.
// Foo foo;
// OnceClosure foo_callback =
// BindOnce(&Foo::func, Unretained(&foo));
// std::move(foo_callback).Run(); // Prints "Foo:f".
// Closure foo_callback =
// Bind(&Foo::func, Unretained(&foo));
// foo_callback.Run(); // Prints "Foo:f".
//
// Without the Unretained() wrapper on |&foo|, the above call would fail
// to compile because Foo does not support the AddRef() and Release() methods.
@ -327,13 +321,13 @@ static inline internal::UnretainedWrapper<T> Unretained(T* o) {
// void foo(RefCountedBytes* bytes) {}
//
// scoped_refptr<RefCountedBytes> bytes = ...;
// OnceClosure callback = BindOnce(&foo, base::RetainedRef(bytes));
// std::move(callback).Run();
// Closure callback = Bind(&foo, base::RetainedRef(bytes));
// callback.Run();
//
// Without RetainedRef, the scoped_refptr would try to implicitly convert to
// a raw pointer and fail compilation:
//
// OnceClosure callback = BindOnce(&foo, bytes); // ERROR!
// Closure callback = Bind(&foo, bytes); // ERROR!
template <typename T>
static inline internal::RetainedRefWrapper<T> RetainedRef(T* o) {
return internal::RetainedRefWrapper<T>(o);
@ -343,41 +337,40 @@ static inline internal::RetainedRefWrapper<T> RetainedRef(scoped_refptr<T> o) {
return internal::RetainedRefWrapper<T>(std::move(o));
}
// Owned() transfers ownership of an object to the callback resulting from
// bind; the object will be deleted when the callback is deleted.
// Owned() transfers ownership of an object to the Callback resulting from
// bind; the object will be deleted when the Callback is deleted.
//
// EXAMPLE OF Owned():
//
// void foo(int* arg) { cout << *arg << endl }
//
// int* pn = new int(1);
// RepeatingClosure foo_callback = BindRepeating(&foo, Owned(pn));
// Closure foo_callback = Bind(&foo, Owned(pn));
//
// foo_callback.Run(); // Prints "1"
// foo_callback.Run(); // Prints "1"
// *pn = 2;
// *n = 2;
// foo_callback.Run(); // Prints "2"
//
// foo_callback.Reset(); // |pn| is deleted. Also will happen when
// // |foo_callback| goes out of scope.
//
// Without Owned(), someone would have to know to delete |pn| when the last
// reference to the callback is deleted.
// reference to the Callback is deleted.
template <typename T>
static inline internal::OwnedWrapper<T> Owned(T* o) {
return internal::OwnedWrapper<T>(o);
}
template <typename T, typename Deleter>
static inline internal::OwnedWrapper<T, Deleter> Owned(
std::unique_ptr<T, Deleter>&& ptr) {
return internal::OwnedWrapper<T, Deleter>(std::move(ptr));
template <typename T>
static inline internal::OwnedWrapper<T> Owned(std::unique_ptr<T>&& ptr) {
return internal::OwnedWrapper<T>(std::move(ptr));
}
// Passed() is for transferring movable-but-not-copyable types (eg. unique_ptr)
// through a RepeatingCallback. Logically, this signifies a destructive transfer
// of the state of the argument into the target function. Invoking
// RepeatingCallback::Run() twice on a callback that was created with a Passed()
// through a Callback. Logically, this signifies a destructive transfer of
// the state of the argument into the target function. Invoking
// Callback::Run() twice on a Callback that was created with a Passed()
// argument will CHECK() because the first invocation would have already
// transferred ownership to the target function.
//
@ -394,22 +387,22 @@ static inline internal::OwnedWrapper<T, Deleter> Owned(
//
// // |cb| is given ownership of Foo(). |f| is now NULL.
// // You can use std::move(f) in place of &f, but it's more verbose.
// RepeatingClosure cb = BindRepeating(&TakesOwnership, Passed(&f));
// Closure cb = Bind(&TakesOwnership, Passed(&f));
//
// // Run was never called so |cb| still owns Foo() and deletes
// // it on Reset().
// cb.Reset();
//
// // |cb| is given a new Foo created by CreateFoo().
// cb = BindRepeating(&TakesOwnership, Passed(CreateFoo()));
// cb = Bind(&TakesOwnership, Passed(CreateFoo()));
//
// // |arg| in TakesOwnership() is given ownership of Foo(). |cb|
// // no longer owns Foo() and, if reset, would not delete Foo().
// cb.Run(); // Foo() is now transferred to |arg| and deleted.
// cb.Run(); // This CHECK()s since Foo() already been used once.
//
// We offer 2 syntaxes for calling Passed(). The first takes an rvalue and is
// best suited for use with the return value of a function or other temporary
// We offer 2 syntaxes for calling Passed(). The first takes an rvalue and
// is best suited for use with the return value of a function or other temporary
// rvalues. The second takes a pointer to the scoper and is just syntactic sugar
// to avoid having to write Passed(std::move(scoper)).
//
@ -425,21 +418,21 @@ static inline internal::PassedWrapper<T> Passed(T* scoper) {
return internal::PassedWrapper<T>(std::move(*scoper));
}
// IgnoreResult() is used to adapt a function or callback with a return type to
// IgnoreResult() is used to adapt a function or Callback with a return type to
// one with a void return. This is most useful if you have a function with,
// say, a pesky ignorable bool return that you want to use with PostTask or
// something else that expect a callback with a void return.
// something else that expect a Callback with a void return.
//
// EXAMPLE OF IgnoreResult():
//
// int DoSomething(int arg) { cout << arg << endl; }
//
// // Assign to a callback with a void return type.
// OnceCallback<void(int)> cb = BindOnce(IgnoreResult(&DoSomething));
// std::move(cb).Run(1); // Prints "1".
// // Assign to a Callback with a void return type.
// Callback<void(int)> cb = Bind(IgnoreResult(&DoSomething));
// cb->Run(1); // Prints "1".
//
// // Prints "2" on |ml|.
// ml->PostTask(FROM_HERE, BindOnce(IgnoreResult(&DoSomething), 2);
// // Prints "1" on |ml|.
// ml->PostTask(FROM_HERE, BindOnce(IgnoreResult(&DoSomething), 1);
template <typename T>
static inline internal::IgnoreResultHelper<T> IgnoreResult(T data) {
return internal::IgnoreResultHelper<T>(std::move(data));
@ -454,9 +447,8 @@ static inline internal::IgnoreResultHelper<T> IgnoreResult(T data) {
// EXAMPLE OF RetainBlock():
//
// // Wrap the block and bind it to a callback.
// OnceCallback<void(int)> cb =
// BindOnce(RetainBlock(^(int n) { NSLog(@"%d", n); }));
// std::move(cb).Run(1); // Logs "1".
// Callback<void(int)> cb = Bind(RetainBlock(^(int n) { NSLog(@"%d", n); }));
// cb.Run(1); // Logs "1".
template <typename R, typename... Args>
base::mac::ScopedBlock<R (^)(Args...)> RetainBlock(R (^block)(Args...)) {
return base::mac::ScopedBlock<R (^)(Args...)>(block,

Просмотреть файл

@ -16,7 +16,7 @@
#include "build/build_config.h"
// This defines a set of simple functions and utilities that people want when
// using {Once,Repeating}Callback<> and Bind{Once,Repeating}().
// using Callback<> and Bind().
namespace base {

Просмотреть файл

@ -104,16 +104,15 @@ struct IgnoreResultHelper {
T functor_;
};
template <typename T, typename Deleter = std::default_delete<T>>
template <typename T>
class OwnedWrapper {
public:
explicit OwnedWrapper(T* o) : ptr_(o) {}
explicit OwnedWrapper(std::unique_ptr<T, Deleter>&& ptr)
: ptr_(std::move(ptr)) {}
explicit OwnedWrapper(std::unique_ptr<T>&& ptr) : ptr_(std::move(ptr)) {}
T* get() const { return ptr_.get(); }
private:
std::unique_ptr<T, Deleter> ptr_;
std::unique_ptr<T> ptr_;
};
// PassedWrapper is a copyable adapter for a scoper that ignores const.
@ -355,9 +354,10 @@ template <typename Functor, typename SFINAE>
struct FunctorTraits;
// For empty callable types.
// This specialization is intended to allow binding captureless lambdas, based
// on the fact that captureless lambdas are empty while capturing lambdas are
// not. This also allows any functors as far as it's an empty class.
// This specialization is intended to allow binding captureless lambdas by
// base::Bind(), based on the fact that captureless lambdas are empty while
// capturing lambdas are not. This also allows any functors as far as it's an
// empty class.
// Example:
//
// // Captureless lambdas are allowed.
@ -791,10 +791,10 @@ BanUnconstructedRefCountedReceiver(const Receiver& receiver, Unused&&...) {
//
// scoped_refptr<Foo> oo = Foo::Create();
DCHECK(receiver->HasAtLeastOneRef())
<< "base::Bind{Once,Repeating}() refuses to create the first reference "
"to ref-counted objects. That typically happens around PostTask() in "
"their constructor, and such objects can be destroyed before `new` "
"returns if the task resolves fast enough.";
<< "base::Bind() refuses to create the first reference to ref-counted "
"objects. That is typically happens around PostTask() in their "
"constructor, and such objects can be destroyed before `new` returns "
"if the task resolves fast enough.";
}
// BindState<>
@ -917,7 +917,7 @@ using MakeBindStateType =
// };
//
// WeakPtr<Foo> oo = nullptr;
// base::BindOnce(&Foo::bar, oo).Run();
// base::Bind(&Foo::bar, oo).Run();
template <typename T>
struct IsWeakReceiver : std::false_type {};
@ -953,11 +953,9 @@ struct BindUnwrapTraits<internal::RetainedRefWrapper<T>> {
static T* Unwrap(const internal::RetainedRefWrapper<T>& o) { return o.get(); }
};
template <typename T, typename Deleter>
struct BindUnwrapTraits<internal::OwnedWrapper<T, Deleter>> {
static T* Unwrap(const internal::OwnedWrapper<T, Deleter>& o) {
return o.get();
}
template <typename T>
struct BindUnwrapTraits<internal::OwnedWrapper<T>> {
static T* Unwrap(const internal::OwnedWrapper<T>& o) { return o.get(); }
};
template <typename T>

Просмотреть файл

@ -1,209 +0,0 @@
// Copyright (c) 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.
// This file defines some bit utilities.
#ifndef BASE_BITS_H_
#define BASE_BITS_H_
#include <stddef.h>
#include <stdint.h>
#include <type_traits>
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "build/build_config.h"
#if defined(COMPILER_MSVC)
#include <intrin.h>
#endif
namespace base {
namespace bits {
// Returns true iff |value| is a power of 2.
template <typename T,
typename = typename std::enable_if<std::is_integral<T>::value>>
constexpr inline bool IsPowerOfTwo(T value) {
// From "Hacker's Delight": Section 2.1 Manipulating Rightmost Bits.
//
// Only positive integers with a single bit set are powers of two. If only one
// bit is set in x (e.g. 0b00000100000000) then |x-1| will have that bit set
// to zero and all bits to its right set to 1 (e.g. 0b00000011111111). Hence
// |x & (x-1)| is 0 iff x is a power of two.
return value > 0 && (value & (value - 1)) == 0;
}
// Round up |size| to a multiple of alignment, which must be a power of two.
inline size_t Align(size_t size, size_t alignment) {
DCHECK(IsPowerOfTwo(alignment));
return (size + alignment - 1) & ~(alignment - 1);
}
// Round down |size| to a multiple of alignment, which must be a power of two.
inline size_t AlignDown(size_t size, size_t alignment) {
DCHECK(IsPowerOfTwo(alignment));
return size & ~(alignment - 1);
}
// CountLeadingZeroBits(value) returns the number of zero bits following the
// most significant 1 bit in |value| if |value| is non-zero, otherwise it
// returns {sizeof(T) * 8}.
// Example: 00100010 -> 2
//
// CountTrailingZeroBits(value) returns the number of zero bits preceding the
// least significant 1 bit in |value| if |value| is non-zero, otherwise it
// returns {sizeof(T) * 8}.
// Example: 00100010 -> 1
//
// C does not have an operator to do this, but fortunately the various
// compilers have built-ins that map to fast underlying processor instructions.
#if defined(COMPILER_MSVC)
template <typename T, unsigned bits = sizeof(T) * 8>
ALWAYS_INLINE
typename std::enable_if<std::is_unsigned<T>::value && sizeof(T) <= 4,
unsigned>::type
CountLeadingZeroBits(T x) {
static_assert(bits > 0, "invalid instantiation");
unsigned long index;
return LIKELY(_BitScanReverse(&index, static_cast<uint32_t>(x)))
? (31 - index - (32 - bits))
: bits;
}
template <typename T, unsigned bits = sizeof(T) * 8>
ALWAYS_INLINE
typename std::enable_if<std::is_unsigned<T>::value && sizeof(T) == 8,
unsigned>::type
CountLeadingZeroBits(T x) {
static_assert(bits > 0, "invalid instantiation");
unsigned long index;
// MSVC only supplies _BitScanReverse64 when building for a 64-bit target.
#if defined(ARCH_CPU_64_BITS)
return LIKELY(_BitScanReverse64(&index, static_cast<uint64_t>(x)))
? (63 - index)
: 64;
#else
uint32_t left = static_cast<uint32_t>(x >> 32);
if (LIKELY(_BitScanReverse(&index, left)))
return 31 - index;
uint32_t right = static_cast<uint32_t>(x);
if (LIKELY(_BitScanReverse(&index, right)))
return 63 - index;
return 64;
#endif
}
template <typename T, unsigned bits = sizeof(T) * 8>
ALWAYS_INLINE
typename std::enable_if<std::is_unsigned<T>::value && sizeof(T) <= 4,
unsigned>::type
CountTrailingZeroBits(T x) {
static_assert(bits > 0, "invalid instantiation");
unsigned long index;
return LIKELY(_BitScanForward(&index, static_cast<uint32_t>(x))) ? index
: bits;
}
template <typename T, unsigned bits = sizeof(T) * 8>
ALWAYS_INLINE
typename std::enable_if<std::is_unsigned<T>::value && sizeof(T) == 8,
unsigned>::type
CountTrailingZeroBits(T x) {
static_assert(bits > 0, "invalid instantiation");
unsigned long index;
// MSVC only supplies _BitScanForward64 when building for a 64-bit target.
#if defined(ARCH_CPU_64_BITS)
return LIKELY(_BitScanForward64(&index, static_cast<uint64_t>(x))) ? index
: 64;
#else
uint32_t right = static_cast<uint32_t>(x);
if (LIKELY(_BitScanForward(&index, right)))
return index;
uint32_t left = static_cast<uint32_t>(x >> 32);
if (LIKELY(_BitScanForward(&index, left)))
return 32 + index;
return 64;
#endif
}
ALWAYS_INLINE uint32_t CountLeadingZeroBits32(uint32_t x) {
return CountLeadingZeroBits(x);
}
ALWAYS_INLINE uint64_t CountLeadingZeroBits64(uint64_t x) {
return CountLeadingZeroBits(x);
}
#elif defined(COMPILER_GCC)
// __builtin_clz has undefined behaviour for an input of 0, even though there's
// clearly a return value that makes sense, and even though some processor clz
// instructions have defined behaviour for 0. We could drop to raw __asm__ to
// do better, but we'll avoid doing that unless we see proof that we need to.
template <typename T, unsigned bits = sizeof(T) * 8>
ALWAYS_INLINE
typename std::enable_if<std::is_unsigned<T>::value && sizeof(T) <= 8,
unsigned>::type
CountLeadingZeroBits(T value) {
static_assert(bits > 0, "invalid instantiation");
return LIKELY(value)
? bits == 64
? __builtin_clzll(static_cast<uint64_t>(value))
: __builtin_clz(static_cast<uint32_t>(value)) - (32 - bits)
: bits;
}
template <typename T, unsigned bits = sizeof(T) * 8>
ALWAYS_INLINE
typename std::enable_if<std::is_unsigned<T>::value && sizeof(T) <= 8,
unsigned>::type
CountTrailingZeroBits(T value) {
return LIKELY(value) ? bits == 64
? __builtin_ctzll(static_cast<uint64_t>(value))
: __builtin_ctz(static_cast<uint32_t>(value))
: bits;
}
ALWAYS_INLINE uint32_t CountLeadingZeroBits32(uint32_t x) {
return CountLeadingZeroBits(x);
}
ALWAYS_INLINE uint64_t CountLeadingZeroBits64(uint64_t x) {
return CountLeadingZeroBits(x);
}
#endif
ALWAYS_INLINE size_t CountLeadingZeroBitsSizeT(size_t x) {
return CountLeadingZeroBits(x);
}
ALWAYS_INLINE size_t CountTrailingZeroBitsSizeT(size_t x) {
return CountTrailingZeroBits(x);
}
// Returns the integer i such as 2^i <= n < 2^(i+1)
inline int Log2Floor(uint32_t n) {
return 31 - CountLeadingZeroBits(n);
}
// Returns the integer i such as 2^(i-1) < n <= 2^i
inline int Log2Ceiling(uint32_t n) {
// When n == 0, we want the function to return -1.
// When n == 0, (n - 1) will underflow to 0xFFFFFFFF, which is
// why the statement below starts with (n ? 32 : -1).
return (n ? 32 : -1) - CountLeadingZeroBits(n - 1);
}
} // namespace bits
} // namespace base
#endif // BASE_BITS_H_

Просмотреть файл

@ -2,9 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// NOTE: Header files that do not require the full definition of
// base::{Once,Repeating}Callback or base::{Once,Repeating}Closure should
// #include "base/callback_forward.h" instead of this file.
// NOTE: Header files that do not require the full definition of Callback or
// Closure should #include "base/callback_forward.h" instead of this file.
#ifndef BASE_CALLBACK_H_
#define BASE_CALLBACK_H_
@ -43,7 +42,7 @@
//
// Callbacks also support cancellation. A common use is binding the receiver
// object as a WeakPtr<T>. If that weak pointer is invalidated, calling Run()
// will be a no-op. Note that |IsCancelled()| and |is_null()| are distinct:
// will be a no-op. Note that |is_cancelled()| and |is_null()| are distinct:
// simply cancelling a callback will not also make it null.
//
// base::Callback is currently a type alias for base::RepeatingCallback. In the
@ -118,14 +117,10 @@ class RepeatingCallback<R(Args...)> : public internal::CallbackBaseCopyable {
RepeatingCallback(RepeatingCallback&&) noexcept = default;
RepeatingCallback& operator=(RepeatingCallback&&) noexcept = default;
bool operator==(const RepeatingCallback& other) const {
bool Equals(const RepeatingCallback& other) const {
return EqualsInternal(other);
}
bool operator!=(const RepeatingCallback& other) const {
return !operator==(other);
}
R Run(Args... args) const & {
PolymorphicInvoke f =
reinterpret_cast<PolymorphicInvoke>(this->polymorphic_invoke());
@ -140,7 +135,7 @@ class RepeatingCallback<R(Args...)> : public internal::CallbackBaseCopyable {
RepeatingCallback cb = std::move(*this);
PolymorphicInvoke f =
reinterpret_cast<PolymorphicInvoke>(cb.polymorphic_invoke());
return f(std::move(cb).bind_state_.get(), std::forward<Args>(args)...);
return f(cb.bind_state_.get(), std::forward<Args>(args)...);
}
};

Просмотреть файл

@ -16,9 +16,8 @@ class RepeatingCallback;
template <typename Signature>
using Callback = RepeatingCallback<Signature>;
// Syntactic sugar to make OnceClosure<void()> and RepeatingClosure<void()>
// easier to declare since they will be used in a lot of APIs with delayed
// execution.
// Syntactic sugar to make Callback<void()> easier to declare since it
// will be used in a lot of APIs with delayed execution.
using OnceClosure = OnceCallback<void()>;
using RepeatingClosure = RepeatingCallback<void()>;
using Closure = Callback<void()>;

Просмотреть файл

@ -19,19 +19,14 @@ struct FakeBindState;
namespace internal {
class BindStateBase;
class FinallyExecutorCommon;
class ThenAndCatchExecutorCommon;
class CallbackBase;
class CallbackBaseCopyable;
template <typename ReturnType>
class PostTaskExecutor;
class BindStateBase;
template <typename Functor, typename... BoundArgs>
struct BindState;
class CallbackBase;
class CallbackBaseCopyable;
struct BindStateBaseRefCountTraits {
static void Destruct(const BindStateBase*);
};
@ -45,10 +40,11 @@ using PassingType = std::conditional_t<std::is_scalar<T>::value, T, T&&>;
// DoInvoke function to perform the function execution. This allows
// us to shield the Callback class from the types of the bound argument via
// "type erasure."
// At the base level, the only task is to add reference counting data. Avoid
// using or inheriting any virtual functions. Creating a vtable for every
// BindState template instantiation results in a lot of bloat. Its only task is
// to call the destructor which can be done with a function pointer.
// At the base level, the only task is to add reference counting data. Don't use
// RefCountedThreadSafe since it requires the destructor to be a virtual method.
// Creating a vtable for every BindState template instantiation results in a lot
// of bloat. Its only task is to call the destructor which can be done with a
// function pointer.
class BASE_EXPORT BindStateBase
: public RefCountedThreadSafe<BindStateBase, BindStateBaseRefCountTraits> {
public:
@ -139,12 +135,6 @@ class BASE_EXPORT CallbackBase {
void Reset();
protected:
friend class FinallyExecutorCommon;
friend class ThenAndCatchExecutorCommon;
template <typename ReturnType>
friend class PostTaskExecutor;
using InvokeFuncStorage = BindStateBase::InvokeFuncStorage;
// Returns true if this callback equals |other|. |other| may be null.

Просмотреть файл

@ -9,10 +9,6 @@
#if defined(COMPILER_MSVC)
#if !defined(__clang__)
#error "Only clang-cl is supported on Windows, see https://crbug.com/988071"
#endif
// Macros for suppressing and disabling warnings on MSVC.
//
// Warning numbers are enumerated at:
@ -26,8 +22,8 @@
// MSVC_PUSH_DISABLE_WARNING pushes |n| onto a stack of warnings to be disabled.
// The warning remains disabled until popped by MSVC_POP_WARNING.
#define MSVC_PUSH_DISABLE_WARNING(n) \
__pragma(warning(push)) __pragma(warning(disable : n))
#define MSVC_PUSH_DISABLE_WARNING(n) __pragma(warning(push)) \
__pragma(warning(disable:n))
// Pop effects of innermost MSVC_PUSH_* macro.
#define MSVC_POP_WARNING() __pragma(warning(pop))
@ -141,7 +137,7 @@
// For member functions, the implicit this parameter counts as index 1.
#if defined(COMPILER_GCC) || defined(__clang__)
#define PRINTF_FORMAT(format_param, dots_param) \
__attribute__((format(printf, format_param, dots_param)))
__attribute__((format(printf, format_param, dots_param)))
#else
#define PRINTF_FORMAT(format_param, dots_param)
#endif
@ -170,14 +166,14 @@
// Mark a memory region fully initialized.
// Use this to annotate code that deliberately reads uninitialized data, for
// example a GC scavenging root set pointers from the stack.
#define MSAN_UNPOISON(p, size) __msan_unpoison(p, size)
#define MSAN_UNPOISON(p, size) __msan_unpoison(p, size)
// Check a memory region for initializedness, as if it was being used here.
// If any bits are uninitialized, crash with an MSan report.
// Use this to sanitize data which MSan won't be able to track, e.g. before
// passing data to another process via shared memory.
#define MSAN_CHECK_MEM_IS_INITIALIZED(p, size) \
__msan_check_mem_is_initialized(p, size)
__msan_check_mem_is_initialized(p, size)
#else // MEMORY_SANITIZER
#define MSAN_UNPOISON(p, size)
#define MSAN_CHECK_MEM_IS_INITIALIZED(p, size)
@ -242,57 +238,4 @@
#define PRETTY_FUNCTION __func__
#endif
#if !defined(CPU_ARM_NEON)
#if defined(__arm__)
#if !defined(__ARMEB__) && !defined(__ARM_EABI__) && !defined(__EABI__) && \
!defined(__VFP_FP__) && !defined(_WIN32_WCE) && !defined(ANDROID)
#error Chromium does not support middle endian architecture
#endif
#if defined(__ARM_NEON__)
#define CPU_ARM_NEON 1
#endif
#endif // defined(__arm__)
#endif // !defined(CPU_ARM_NEON)
#if !defined(HAVE_MIPS_MSA_INTRINSICS)
#if defined(__mips_msa) && defined(__mips_isa_rev) && (__mips_isa_rev >= 5)
#define HAVE_MIPS_MSA_INTRINSICS 1
#endif
#endif
#if defined(__clang__) && __has_attribute(uninitialized)
// Attribute "uninitialized" disables -ftrivial-auto-var-init=pattern for
// the specified variable.
// Library-wide alternative is
// 'configs -= [ "//build/config/compiler:default_init_stack_vars" ]' in .gn
// file.
//
// See "init_stack_vars" in build/config/compiler/BUILD.gn and
// http://crbug.com/977230
// "init_stack_vars" is enabled for non-official builds and we hope to enable it
// in official build in 2020 as well. The flag writes fixed pattern into
// uninitialized parts of all local variables. In rare cases such initialization
// is undesirable and attribute can be used:
// 1. Degraded performance
// In most cases compiler is able to remove additional stores. E.g. if memory is
// never accessed or properly initialized later. Preserved stores mostly will
// not affect program performance. However if compiler failed on some
// performance critical code we can get a visible regression in a benchmark.
// 2. memset, memcpy calls
// Compiler may replaces some memory writes with memset or memcpy calls. This is
// not -ftrivial-auto-var-init specific, but it can happen more likely with the
// flag. It can be a problem if code is not linked with C run-time library.
//
// Note: The flag is security risk mitigation feature. So in future the
// attribute uses should be avoided when possible. However to enable this
// mitigation on the most of the code we need to be less strict now and minimize
// number of exceptions later. So if in doubt feel free to use attribute, but
// please document the problem for someone who is going to cleanup it later.
// E.g. platform, bot, benchmark or test name in patch description or next to
// the attribute.
#define STACK_UNINITIALIZED __attribute__((uninitialized))
#else
#define STACK_UNINITIALIZED
#endif
#endif // BASE_COMPILER_SPECIFIC_H_

Просмотреть файл

@ -1,145 +0,0 @@
// 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.
#ifndef BASE_CONTAINERS_BUFFER_ITERATOR_H_
#define BASE_CONTAINERS_BUFFER_ITERATOR_H_
#include <type_traits>
#include "base/bit_cast.h"
#include "base/containers/span.h"
#include "base/numerics/checked_math.h"
namespace base {
// BufferIterator is a bounds-checked container utility to access variable-
// length, heterogeneous structures contained within a buffer. If the data are
// homogeneous, use base::span<> instead.
//
// After being created with a weakly-owned buffer, BufferIterator returns
// pointers to structured data within the buffer. After each method call that
// returns data in the buffer, the iterator position is advanced by the byte
// size of the object (or span of objects) returned. If there are not enough
// bytes remaining in the buffer to return the requested object(s), a nullptr
// or empty span is returned.
//
// This class is similar to base::Pickle, which should be preferred for
// serializing to disk. Pickle versions its header and does not support writing
// structures, which are problematic for serialization due to struct padding and
// version shear concerns.
//
// Example usage:
//
// std::vector<uint8_t> buffer(4096);
// if (!ReadSomeData(&buffer, buffer.size())) {
// LOG(ERROR) << "Failed to read data.";
// return false;
// }
//
// BufferIterator<uint8_t> iterator(buffer);
// uint32_t* num_items = iterator.Object<uint32_t>();
// if (!num_items) {
// LOG(ERROR) << "No num_items field."
// return false;
// }
//
// base::span<const item_struct> items =
// iterator.Span<item_struct>(*num_items);
// if (items.size() != *num_items) {
// LOG(ERROR) << "Not enough items.";
// return false;
// }
//
// // ... validate the objects in |items|.
template <typename B>
class BufferIterator {
public:
static_assert(std::is_same<std::remove_const_t<B>, char>::value ||
std::is_same<std::remove_const_t<B>, unsigned char>::value,
"Underlying buffer type must be char-type.");
BufferIterator() {}
BufferIterator(B* data, size_t size)
: BufferIterator(make_span(data, size)) {}
explicit BufferIterator(span<B> buffer)
: buffer_(buffer), remaining_(buffer) {}
~BufferIterator() {}
// Returns a pointer to a mutable structure T in the buffer at the current
// position. On success, the iterator position is advanced by sizeof(T). If
// there are not sizeof(T) bytes remaining in the buffer, returns nullptr.
template <typename T,
typename =
typename std::enable_if_t<std::is_trivially_copyable<T>::value>>
T* MutableObject() {
size_t size = sizeof(T);
size_t next_position;
if (!CheckAdd(position(), size).AssignIfValid(&next_position))
return nullptr;
if (next_position > total_size())
return nullptr;
T* t = bit_cast<T*>(remaining_.data());
remaining_ = remaining_.subspan(size);
return t;
}
// Returns a const pointer to an object of type T in the buffer at the current
// position.
template <typename T,
typename =
typename std::enable_if_t<std::is_trivially_copyable<T>::value>>
const T* Object() {
return MutableObject<const T>();
}
// Returns a span of |count| T objects in the buffer at the current position.
// On success, the iterator position is advanced by |sizeof(T) * count|. If
// there are not enough bytes remaining in the buffer to fulfill the request,
// returns an empty span.
template <typename T,
typename =
typename std::enable_if_t<std::is_trivially_copyable<T>::value>>
span<T> MutableSpan(size_t count) {
size_t size;
if (!CheckMul(sizeof(T), count).AssignIfValid(&size))
return span<T>();
size_t next_position;
if (!CheckAdd(position(), size).AssignIfValid(&next_position))
return span<T>();
if (next_position > total_size())
return span<T>();
auto result = span<T>(bit_cast<T*>(remaining_.data()), count);
remaining_ = remaining_.subspan(size);
return result;
}
// Returns a span to |count| const objects of type T in the buffer at the
// current position.
template <typename T,
typename =
typename std::enable_if_t<std::is_trivially_copyable<T>::value>>
span<const T> Span(size_t count) {
return MutableSpan<const T>(count);
}
// Resets the iterator position to the absolute offset |to|.
void Seek(size_t to) { remaining_ = buffer_.subspan(to); }
// Returns the total size of the underlying buffer.
size_t total_size() { return buffer_.size(); }
// Returns the current position in the buffer.
size_t position() { return buffer_.size_bytes() - remaining_.size_bytes(); }
private:
// The original buffer that the iterator was constructed with.
const span<B> buffer_;
// A subspan of |buffer_| containing the remaining bytes to iterate over.
span<B> remaining_;
// Copy and assign allowed.
};
} // namespace base
#endif // BASE_CONTAINERS_BUFFER_ITERATOR_H_

Просмотреть файл

@ -1,205 +0,0 @@
// 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_CONTAINERS_CHECKED_ITERATORS_H_
#define BASE_CONTAINERS_CHECKED_ITERATORS_H_
#include <iterator>
#include <memory>
#include <type_traits>
#include "base/containers/util.h"
#include "base/logging.h"
namespace base {
template <typename T>
class CheckedContiguousIterator {
public:
using difference_type = std::ptrdiff_t;
using value_type = std::remove_cv_t<T>;
using pointer = T*;
using reference = T&;
using iterator_category = std::random_access_iterator_tag;
// Required for converting constructor below.
template <typename U>
friend class CheckedContiguousIterator;
constexpr CheckedContiguousIterator() = default;
constexpr CheckedContiguousIterator(T* start, const T* end)
: CheckedContiguousIterator(start, start, end) {}
constexpr CheckedContiguousIterator(const T* start, T* current, const T* end)
: start_(start), current_(current), end_(end) {
CHECK_LE(start, current);
CHECK_LE(current, end);
}
constexpr CheckedContiguousIterator(const CheckedContiguousIterator& other) =
default;
// Converting constructor allowing conversions like CCI<T> to CCI<const T>,
// but disallowing CCI<const T> to CCI<T> or CCI<Derived> to CCI<Base>, which
// are unsafe. Furthermore, this is the same condition as used by the
// converting constructors of std::span<T> and std::unique_ptr<T[]>.
// See https://wg21.link/n4042 for details.
template <
typename U,
std::enable_if_t<std::is_convertible<U (*)[], T (*)[]>::value>* = nullptr>
constexpr CheckedContiguousIterator(const CheckedContiguousIterator<U>& other)
: start_(other.start_), current_(other.current_), end_(other.end_) {
// We explicitly don't delegate to the 3-argument constructor here. Its
// CHECKs would be redundant, since we expect |other| to maintain its own
// invariant. However, DCHECKs never hurt anybody. Presumably.
DCHECK_LE(other.start_, other.current_);
DCHECK_LE(other.current_, other.end_);
}
~CheckedContiguousIterator() = default;
constexpr CheckedContiguousIterator& operator=(
const CheckedContiguousIterator& other) = default;
constexpr bool operator==(const CheckedContiguousIterator& other) const {
CheckComparable(other);
return current_ == other.current_;
}
constexpr bool operator!=(const CheckedContiguousIterator& other) const {
CheckComparable(other);
return current_ != other.current_;
}
constexpr bool operator<(const CheckedContiguousIterator& other) const {
CheckComparable(other);
return current_ < other.current_;
}
constexpr bool operator<=(const CheckedContiguousIterator& other) const {
CheckComparable(other);
return current_ <= other.current_;
}
constexpr bool operator>(const CheckedContiguousIterator& other) const {
CheckComparable(other);
return current_ > other.current_;
}
constexpr bool operator>=(const CheckedContiguousIterator& other) const {
CheckComparable(other);
return current_ >= other.current_;
}
constexpr CheckedContiguousIterator& operator++() {
CHECK_NE(current_, end_);
++current_;
return *this;
}
constexpr CheckedContiguousIterator operator++(int) {
CheckedContiguousIterator old = *this;
++*this;
return old;
}
constexpr CheckedContiguousIterator& operator--() {
CHECK_NE(current_, start_);
--current_;
return *this;
}
constexpr CheckedContiguousIterator operator--(int) {
CheckedContiguousIterator old = *this;
--*this;
return old;
}
constexpr CheckedContiguousIterator& operator+=(difference_type rhs) {
if (rhs > 0) {
CHECK_LE(rhs, end_ - current_);
} else {
CHECK_LE(-rhs, current_ - start_);
}
current_ += rhs;
return *this;
}
constexpr CheckedContiguousIterator operator+(difference_type rhs) const {
CheckedContiguousIterator it = *this;
it += rhs;
return it;
}
constexpr CheckedContiguousIterator& operator-=(difference_type rhs) {
if (rhs < 0) {
CHECK_LE(-rhs, end_ - current_);
} else {
CHECK_LE(rhs, current_ - start_);
}
current_ -= rhs;
return *this;
}
constexpr CheckedContiguousIterator operator-(difference_type rhs) const {
CheckedContiguousIterator it = *this;
it -= rhs;
return it;
}
constexpr friend difference_type operator-(
const CheckedContiguousIterator& lhs,
const CheckedContiguousIterator& rhs) {
CHECK_EQ(lhs.start_, rhs.start_);
CHECK_EQ(lhs.end_, rhs.end_);
return lhs.current_ - rhs.current_;
}
constexpr reference operator*() const {
CHECK_NE(current_, end_);
return *current_;
}
constexpr pointer operator->() const {
CHECK_NE(current_, end_);
return current_;
}
constexpr reference operator[](difference_type rhs) const {
CHECK_GE(rhs, 0);
CHECK_LT(rhs, end_ - current_);
return current_[rhs];
}
static bool IsRangeMoveSafe(const CheckedContiguousIterator& from_begin,
const CheckedContiguousIterator& from_end,
const CheckedContiguousIterator& to)
WARN_UNUSED_RESULT {
if (from_end < from_begin)
return false;
const auto from_begin_uintptr = get_uintptr(from_begin.current_);
const auto from_end_uintptr = get_uintptr(from_end.current_);
const auto to_begin_uintptr = get_uintptr(to.current_);
const auto to_end_uintptr =
get_uintptr((to + std::distance(from_begin, from_end)).current_);
return to_begin_uintptr >= from_end_uintptr ||
to_end_uintptr <= from_begin_uintptr;
}
private:
constexpr void CheckComparable(const CheckedContiguousIterator& other) const {
CHECK_EQ(start_, other.start_);
CHECK_EQ(end_, other.end_);
}
const T* start_ = nullptr;
T* current_ = nullptr;
const T* end_ = nullptr;
};
template <typename T>
using CheckedContiguousConstIterator = CheckedContiguousIterator<const T>;
} // namespace base
#endif // BASE_CONTAINERS_CHECKED_ITERATORS_H_

Просмотреть файл

@ -14,7 +14,6 @@
#include "base/containers/vector_buffer.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/stl_util.h"
#include "base/template_util.h"
// base::circular_deque is similar to std::deque. Unlike std::deque, the
@ -522,15 +521,15 @@ class circular_deque {
return buffer_[i - right_size];
}
value_type& at(size_type i) {
return const_cast<value_type&>(as_const(*this).at(i));
return const_cast<value_type&>(
const_cast<const circular_deque*>(this)->at(i));
}
value_type& operator[](size_type i) {
return const_cast<value_type&>(as_const(*this)[i]);
value_type& operator[](size_type i) { return at(i); }
const value_type& operator[](size_type i) const {
return const_cast<circular_deque*>(this)->at(i);
}
const value_type& operator[](size_type i) const { return at(i); }
value_type& front() {
DCHECK(!empty());
return buffer_[begin_];

Просмотреть файл

@ -1,530 +0,0 @@
// Copyright 2017 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_CONTAINERS_SPAN_H_
#define BASE_CONTAINERS_SPAN_H_
#include <stddef.h>
#include <algorithm>
#include <array>
#include <iterator>
#include <limits>
#include <type_traits>
#include <utility>
#include "base/containers/checked_iterators.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/stl_util.h"
namespace base {
// [views.constants]
constexpr size_t dynamic_extent = std::numeric_limits<size_t>::max();
template <typename T, size_t Extent = dynamic_extent>
class span;
namespace internal {
template <typename T>
struct ExtentImpl : std::integral_constant<size_t, dynamic_extent> {};
template <typename T, size_t N>
struct ExtentImpl<T[N]> : std::integral_constant<size_t, N> {};
template <typename T, size_t N>
struct ExtentImpl<std::array<T, N>> : std::integral_constant<size_t, N> {};
template <typename T, size_t N>
struct ExtentImpl<base::span<T, N>> : std::integral_constant<size_t, N> {};
template <typename T>
using Extent = ExtentImpl<std::remove_cv_t<std::remove_reference_t<T>>>;
template <typename T>
struct IsSpanImpl : std::false_type {};
template <typename T, size_t Extent>
struct IsSpanImpl<span<T, Extent>> : std::true_type {};
template <typename T>
using IsSpan = IsSpanImpl<std::decay_t<T>>;
template <typename T>
struct IsStdArrayImpl : std::false_type {};
template <typename T, size_t N>
struct IsStdArrayImpl<std::array<T, N>> : std::true_type {};
template <typename T>
using IsStdArray = IsStdArrayImpl<std::decay_t<T>>;
template <typename T>
using IsCArray = std::is_array<std::remove_reference_t<T>>;
template <typename From, typename To>
using IsLegalDataConversion = std::is_convertible<From (*)[], To (*)[]>;
template <typename Container, typename T>
using ContainerHasConvertibleData = IsLegalDataConversion<
std::remove_pointer_t<decltype(base::data(std::declval<Container>()))>,
T>;
template <typename Container>
using ContainerHasIntegralSize =
std::is_integral<decltype(base::size(std::declval<Container>()))>;
template <typename From, size_t FromExtent, typename To, size_t ToExtent>
using EnableIfLegalSpanConversion =
std::enable_if_t<(ToExtent == dynamic_extent || ToExtent == FromExtent) &&
IsLegalDataConversion<From, To>::value>;
// SFINAE check if Array can be converted to a span<T>.
template <typename Array, typename T, size_t Extent>
using EnableIfSpanCompatibleArray =
std::enable_if_t<(Extent == dynamic_extent ||
Extent == internal::Extent<Array>::value) &&
ContainerHasConvertibleData<Array, T>::value>;
// SFINAE check if Container can be converted to a span<T>.
template <typename Container, typename T>
using IsSpanCompatibleContainer =
std::conditional_t<!IsSpan<Container>::value &&
!IsStdArray<Container>::value &&
!IsCArray<Container>::value &&
ContainerHasConvertibleData<Container, T>::value &&
ContainerHasIntegralSize<Container>::value,
std::true_type,
std::false_type>;
template <typename Container, typename T>
using EnableIfSpanCompatibleContainer =
std::enable_if_t<IsSpanCompatibleContainer<Container, T>::value>;
template <typename Container, typename T, size_t Extent>
using EnableIfSpanCompatibleContainerAndSpanIsDynamic =
std::enable_if_t<IsSpanCompatibleContainer<Container, T>::value &&
Extent == dynamic_extent>;
// A helper template for storing the size of a span. Spans with static extents
// don't require additional storage, since the extent itself is specified in the
// template parameter.
template <size_t Extent>
class ExtentStorage {
public:
constexpr explicit ExtentStorage(size_t size) noexcept {}
constexpr size_t size() const noexcept { return Extent; }
};
// Specialization of ExtentStorage for dynamic extents, which do require
// explicit storage for the size.
template <>
struct ExtentStorage<dynamic_extent> {
constexpr explicit ExtentStorage(size_t size) noexcept : size_(size) {}
constexpr size_t size() const noexcept { return size_; }
private:
size_t size_;
};
} // namespace internal
// A span is a value type that represents an array of elements of type T. Since
// it only consists of a pointer to memory with an associated size, it is very
// light-weight. It is cheap to construct, copy, move and use spans, so that
// users are encouraged to use it as a pass-by-value parameter. A span does not
// own the underlying memory, so care must be taken to ensure that a span does
// not outlive the backing store.
//
// span is somewhat analogous to StringPiece, but with arbitrary element types,
// allowing mutation if T is non-const.
//
// span is implicitly convertible from C++ arrays, as well as most [1]
// container-like types that provide a data() and size() method (such as
// std::vector<T>). A mutable span<T> can also be implicitly converted to an
// immutable span<const T>.
//
// Consider using a span for functions that take a data pointer and size
// parameter: it allows the function to still act on an array-like type, while
// allowing the caller code to be a bit more concise.
//
// For read-only data access pass a span<const T>: the caller can supply either
// a span<const T> or a span<T>, while the callee will have a read-only view.
// For read-write access a mutable span<T> is required.
//
// Without span:
// Read-Only:
// // std::string HexEncode(const uint8_t* data, size_t size);
// std::vector<uint8_t> data_buffer = GenerateData();
// std::string r = HexEncode(data_buffer.data(), data_buffer.size());
//
// Mutable:
// // ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt, Args...);
// char str_buffer[100];
// SafeSNPrintf(str_buffer, sizeof(str_buffer), "Pi ~= %lf", 3.14);
//
// With span:
// Read-Only:
// // std::string HexEncode(base::span<const uint8_t> data);
// std::vector<uint8_t> data_buffer = GenerateData();
// std::string r = HexEncode(data_buffer);
//
// Mutable:
// // ssize_t SafeSNPrintf(base::span<char>, const char* fmt, Args...);
// char str_buffer[100];
// SafeSNPrintf(str_buffer, "Pi ~= %lf", 3.14);
//
// Spans with "const" and pointers
// -------------------------------
//
// Const and pointers can get confusing. Here are vectors of pointers and their
// corresponding spans:
//
// const std::vector<int*> => base::span<int* const>
// std::vector<const int*> => base::span<const int*>
// const std::vector<const int*> => base::span<const int* const>
//
// Differences from the C++20 draft
// --------------------------------
//
// http://eel.is/c++draft/views contains the latest C++20 draft of std::span.
// Chromium tries to follow the draft as close as possible. Differences between
// the draft and the implementation are documented in subsections below.
//
// Differences from [span.objectrep]:
// - as_bytes() and as_writable_bytes() return spans of uint8_t instead of
// std::byte (std::byte is a C++17 feature)
//
// Differences from [span.cons]:
// - Constructing a static span (i.e. Extent != dynamic_extent) from a dynamic
// sized container (e.g. std::vector) requires an explicit conversion (in the
// C++20 draft this is simply UB)
//
// Differences from [span.obs]:
// - empty() is marked with WARN_UNUSED_RESULT instead of [[nodiscard]]
// ([[nodiscard]] is a C++17 feature)
//
// Furthermore, all constructors and methods are marked noexcept due to the lack
// of exceptions in Chromium.
//
// Due to the lack of class template argument deduction guides in C++14
// appropriate make_span() utility functions are provided.
// [span], class template span
template <typename T, size_t Extent>
class span : public internal::ExtentStorage<Extent> {
private:
using ExtentStorage = internal::ExtentStorage<Extent>;
public:
using element_type = T;
using value_type = std::remove_cv_t<T>;
using size_type = size_t;
using difference_type = ptrdiff_t;
using pointer = T*;
using reference = T&;
using iterator = CheckedContiguousIterator<T>;
using const_iterator = CheckedContiguousConstIterator<T>;
using reverse_iterator = std::reverse_iterator<iterator>;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
static constexpr size_t extent = Extent;
// [span.cons], span constructors, copy, assignment, and destructor
constexpr span() noexcept : ExtentStorage(0), data_(nullptr) {
static_assert(Extent == dynamic_extent || Extent == 0, "Invalid Extent");
}
constexpr span(T* data, size_t size) noexcept
: ExtentStorage(size), data_(data) {
CHECK(Extent == dynamic_extent || Extent == size);
}
// Artificially templatized to break ambiguity for span(ptr, 0).
template <typename = void>
constexpr span(T* begin, T* end) noexcept : span(begin, end - begin) {
// Note: CHECK_LE is not constexpr, hence regular CHECK must be used.
CHECK(begin <= end);
}
template <
size_t N,
typename = internal::EnableIfSpanCompatibleArray<T (&)[N], T, Extent>>
constexpr span(T (&array)[N]) noexcept : span(base::data(array), N) {}
template <
size_t N,
typename = internal::
EnableIfSpanCompatibleArray<std::array<value_type, N>&, T, Extent>>
constexpr span(std::array<value_type, N>& array) noexcept
: span(base::data(array), N) {}
template <size_t N,
typename = internal::EnableIfSpanCompatibleArray<
const std::array<value_type, N>&,
T,
Extent>>
constexpr span(const std::array<value_type, N>& array) noexcept
: span(base::data(array), N) {}
// Conversion from a container that has compatible base::data() and integral
// base::size().
template <
typename Container,
typename =
internal::EnableIfSpanCompatibleContainerAndSpanIsDynamic<Container&,
T,
Extent>>
constexpr span(Container& container) noexcept
: span(base::data(container), base::size(container)) {}
template <
typename Container,
typename = internal::EnableIfSpanCompatibleContainerAndSpanIsDynamic<
const Container&,
T,
Extent>>
constexpr span(const Container& container) noexcept
: span(base::data(container), base::size(container)) {}
constexpr span(const span& other) noexcept = default;
// Conversions from spans of compatible types and extents: this allows a
// span<T> to be seamlessly used as a span<const T>, but not the other way
// around. If extent is not dynamic, OtherExtent has to be equal to Extent.
template <
typename U,
size_t OtherExtent,
typename =
internal::EnableIfLegalSpanConversion<U, OtherExtent, T, Extent>>
constexpr span(const span<U, OtherExtent>& other)
: span(other.data(), other.size()) {}
constexpr span& operator=(const span& other) noexcept = default;
~span() noexcept = default;
// [span.sub], span subviews
template <size_t Count>
constexpr span<T, Count> first() const noexcept {
static_assert(Extent == dynamic_extent || Count <= Extent,
"Count must not exceed Extent");
CHECK(Extent != dynamic_extent || Count <= size());
return {data(), Count};
}
template <size_t Count>
constexpr span<T, Count> last() const noexcept {
static_assert(Extent == dynamic_extent || Count <= Extent,
"Count must not exceed Extent");
CHECK(Extent != dynamic_extent || Count <= size());
return {data() + (size() - Count), Count};
}
template <size_t Offset, size_t Count = dynamic_extent>
constexpr span<T,
(Count != dynamic_extent
? Count
: (Extent != dynamic_extent ? Extent - Offset
: dynamic_extent))>
subspan() const noexcept {
static_assert(Extent == dynamic_extent || Offset <= Extent,
"Offset must not exceed Extent");
static_assert(Extent == dynamic_extent || Count == dynamic_extent ||
Count <= Extent - Offset,
"Count must not exceed Extent - Offset");
CHECK(Extent != dynamic_extent || Offset <= size());
CHECK(Extent != dynamic_extent || Count == dynamic_extent ||
Count <= size() - Offset);
return {data() + Offset, Count != dynamic_extent ? Count : size() - Offset};
}
constexpr span<T, dynamic_extent> first(size_t count) const noexcept {
// Note: CHECK_LE is not constexpr, hence regular CHECK must be used.
CHECK(count <= size());
return {data(), count};
}
constexpr span<T, dynamic_extent> last(size_t count) const noexcept {
// Note: CHECK_LE is not constexpr, hence regular CHECK must be used.
CHECK(count <= size());
return {data() + (size() - count), count};
}
constexpr span<T, dynamic_extent> subspan(size_t offset,
size_t count = dynamic_extent) const
noexcept {
// Note: CHECK_LE is not constexpr, hence regular CHECK must be used.
CHECK(offset <= size());
CHECK(count == dynamic_extent || count <= size() - offset);
return {data() + offset, count != dynamic_extent ? count : size() - offset};
}
// [span.obs], span observers
constexpr size_t size() const noexcept { return ExtentStorage::size(); }
constexpr size_t size_bytes() const noexcept { return size() * sizeof(T); }
constexpr bool empty() const noexcept WARN_UNUSED_RESULT {
return size() == 0;
}
// [span.elem], span element access
constexpr T& operator[](size_t idx) const noexcept {
// Note: CHECK_LT is not constexpr, hence regular CHECK must be used.
CHECK(idx < size());
return *(data() + idx);
}
constexpr T& front() const noexcept {
static_assert(Extent == dynamic_extent || Extent > 0,
"Extent must not be 0");
CHECK(Extent != dynamic_extent || !empty());
return *data();
}
constexpr T& back() const noexcept {
static_assert(Extent == dynamic_extent || Extent > 0,
"Extent must not be 0");
CHECK(Extent != dynamic_extent || !empty());
return *(data() + size() - 1);
}
constexpr T* data() const noexcept { return data_; }
// [span.iter], span iterator support
constexpr iterator begin() const noexcept {
return iterator(data_, data_ + size());
}
constexpr iterator end() const noexcept {
return iterator(data_, data_ + size(), data_ + size());
}
constexpr const_iterator cbegin() const noexcept { return begin(); }
constexpr const_iterator cend() const noexcept { return end(); }
constexpr reverse_iterator rbegin() const noexcept {
return reverse_iterator(end());
}
constexpr reverse_iterator rend() const noexcept {
return reverse_iterator(begin());
}
constexpr const_reverse_iterator crbegin() const noexcept {
return const_reverse_iterator(cend());
}
constexpr const_reverse_iterator crend() const noexcept {
return const_reverse_iterator(cbegin());
}
private:
T* data_;
};
// span<T, Extent>::extent can not be declared inline prior to C++17, hence this
// definition is required.
template <class T, size_t Extent>
constexpr size_t span<T, Extent>::extent;
// [span.objectrep], views of object representation
template <typename T, size_t X>
span<const uint8_t, (X == dynamic_extent ? dynamic_extent : sizeof(T) * X)>
as_bytes(span<T, X> s) noexcept {
return {reinterpret_cast<const uint8_t*>(s.data()), s.size_bytes()};
}
template <typename T,
size_t X,
typename = std::enable_if_t<!std::is_const<T>::value>>
span<uint8_t, (X == dynamic_extent ? dynamic_extent : sizeof(T) * X)>
as_writable_bytes(span<T, X> s) noexcept {
return {reinterpret_cast<uint8_t*>(s.data()), s.size_bytes()};
}
// Type-deducing helpers for constructing a span.
template <int&... ExplicitArgumentBarrier, typename T>
constexpr span<T> make_span(T* data, size_t size) noexcept {
return {data, size};
}
template <int&... ExplicitArgumentBarrier, typename T>
constexpr span<T> make_span(T* begin, T* end) noexcept {
return {begin, end};
}
// make_span utility function that deduces both the span's value_type and extent
// from the passed in argument.
//
// Usage: auto span = base::make_span(...);
template <int&... ExplicitArgumentBarrier, typename Container>
constexpr auto make_span(Container&& container) noexcept {
using T =
std::remove_pointer_t<decltype(base::data(std::declval<Container>()))>;
using Extent = internal::Extent<Container>;
return span<T, Extent::value>(std::forward<Container>(container));
}
// make_span utility function that allows callers to explicit specify the span's
// extent, the value_type is deduced automatically. This is useful when passing
// a dynamically sized container to a method expecting static spans, when the
// container is known to have the correct size.
//
// Note: This will CHECK that N indeed matches size(container).
//
// Usage: auto static_span = base::make_span<N>(...);
template <size_t N, int&... ExplicitArgumentBarrier, typename Container>
constexpr auto make_span(Container&& container) noexcept {
using T =
std::remove_pointer_t<decltype(base::data(std::declval<Container>()))>;
return span<T, N>(base::data(container), base::size(container));
}
} // namespace base
// Note: std::tuple_size, std::tuple_element and std::get are specialized for
// static spans, so that they can be used in C++17's structured bindings. While
// we don't support C++17 yet, there is no harm in providing these
// specializations already.
namespace std {
// [span.tuple], tuple interface
#if defined(__clang__)
// Due to https://llvm.org/PR39871 and https://llvm.org/PR41331 and their
// respective fixes different versions of libc++ declare std::tuple_size and
// std::tuple_element either as classes or structs. In order to be able to
// specialize std::tuple_size and std::tuple_element for custom base types we
// thus need to disable -Wmismatched-tags in order to support all build
// configurations. Note that this is blessed by the standard in
// https://timsong-cpp.github.io/cppwp/n4140/dcl.type.elab#3.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wmismatched-tags"
#endif
template <typename T, size_t X>
struct tuple_size<base::span<T, X>> : public integral_constant<size_t, X> {};
template <typename T>
struct tuple_size<base::span<T, base::dynamic_extent>>; // not defined
template <size_t I, typename T, size_t X>
struct tuple_element<I, base::span<T, X>> {
static_assert(
base::dynamic_extent != X,
"std::tuple_element<> not supported for base::span<T, dynamic_extent>");
static_assert(I < X,
"Index out of bounds in std::tuple_element<> (base::span)");
using type = T;
};
#if defined(__clang__)
#pragma clang diagnostic pop // -Wmismatched-tags
#endif
template <size_t I, typename T, size_t X>
constexpr T& get(base::span<T, X> s) noexcept {
static_assert(base::dynamic_extent != X,
"std::get<> not supported for base::span<T, dynamic_extent>");
static_assert(I < X, "Index out of bounds in std::get<> (base::span)");
return s[I];
}
} // namespace std
#endif // BASE_CONTAINERS_SPAN_H_

Просмотреть файл

@ -13,6 +13,7 @@
#include <utility>
#include "base/stl_util.h"
#include "build/build_config.h"
#if defined(ARCH_CPU_ARM_FAMILY) && (defined(OS_ANDROID) || defined(OS_LINUX))
#include "base/files/file_util.h"
@ -27,44 +28,6 @@
namespace base {
#if defined(ARCH_CPU_X86_FAMILY)
namespace internal {
std::tuple<int, int, int, int> ComputeX86FamilyAndModel(
const std::string& vendor,
int signature) {
int family = (signature >> 8) & 0xf;
int model = (signature >> 4) & 0xf;
int ext_family = 0;
int ext_model = 0;
// The "Intel 64 and IA-32 Architectures Developer's Manual: Vol. 2A"
// specifies the Extended Model is defined only when the Base Family is
// 06h or 0Fh.
// The "AMD CPUID Specification" specifies that the Extended Model is
// defined only when Base Family is 0Fh.
// Both manuals define the display model as
// {ExtendedModel[3:0],BaseModel[3:0]} in that case.
if (family == 0xf || (family == 0x6 && vendor == "GenuineIntel")) {
ext_model = (signature >> 16) & 0xf;
model += ext_model << 4;
}
// Both the "Intel 64 and IA-32 Architectures Developer's Manual: Vol. 2A"
// and the "AMD CPUID Specification" specify that the Extended Family is
// defined only when the Base Family is 0Fh.
// Both manuals define the display family as {0000b,BaseFamily[3:0]} +
// ExtendedFamily[7:0] in that case.
if (family == 0xf) {
ext_family = (signature >> 20) & 0xff;
family += ext_family;
}
return {family, model, ext_family, ext_model};
}
} // namespace internal
#endif // defined(ARCH_CPU_X86_FAMILY)
CPU::CPU()
: signature_(0),
type_(0),
@ -85,7 +48,6 @@ CPU::CPU()
has_avx2_(false),
has_aesni_(false),
has_non_stop_time_stamp_counter_(false),
is_running_in_vm_(false),
cpu_vendor_("unknown") {
Initialize();
}
@ -194,6 +156,7 @@ void CPU::Initialize() {
memcpy(cpu_string, &cpu_info[1], kVendorNameSize);
cpu_string[kVendorNameSize] = '\0';
cpu_vendor_ = cpu_string;
bool hypervisor = false;
// Interpret CPU feature information.
if (num_ids > 0) {
@ -204,9 +167,11 @@ void CPU::Initialize() {
}
signature_ = cpu_info[0];
stepping_ = cpu_info[0] & 0xf;
model_ = ((cpu_info[0] >> 4) & 0xf) + ((cpu_info[0] >> 12) & 0xf0);
family_ = (cpu_info[0] >> 8) & 0xf;
type_ = (cpu_info[0] >> 12) & 0x3;
std::tie(family_, model_, ext_family_, ext_model_) =
internal::ComputeX86FamilyAndModel(cpu_vendor_, signature_);
ext_model_ = (cpu_info[0] >> 16) & 0xf;
ext_family_ = (cpu_info[0] >> 20) & 0xff;
has_mmx_ = (cpu_info[3] & 0x00800000) != 0;
has_sse_ = (cpu_info[3] & 0x02000000) != 0;
has_sse2_ = (cpu_info[3] & 0x04000000) != 0;
@ -221,7 +186,7 @@ void CPU::Initialize() {
// This is checking for any hypervisor. Hypervisors may choose not to
// announce themselves. Hypervisors trap CPUID and sometimes return
// different results to underlying hardware.
is_running_in_vm_ = (cpu_info[2] & 0x80000000) != 0;
hypervisor = (cpu_info[2] & 0x80000000) != 0;
// AVX instructions will generate an illegal instruction exception unless
// a) they are supported by the CPU,
@ -270,7 +235,7 @@ void CPU::Initialize() {
has_non_stop_time_stamp_counter_ = (cpu_info[3] & (1 << 8)) != 0;
}
if (!has_non_stop_time_stamp_counter_ && is_running_in_vm_) {
if (!has_non_stop_time_stamp_counter_ && hypervisor) {
int cpu_info_hv[4] = {};
__cpuid(cpu_info_hv, 0x40000000);
if (cpu_info_hv[1] == 0x7263694D && // Micr
@ -286,14 +251,8 @@ void CPU::Initialize() {
has_non_stop_time_stamp_counter_ = true;
}
}
#elif defined(ARCH_CPU_ARM_FAMILY)
#if (defined(OS_ANDROID) || defined(OS_LINUX))
#elif defined(ARCH_CPU_ARM_FAMILY) && (defined(OS_ANDROID) || defined(OS_LINUX))
cpu_brand_ = *CpuInfoBrand();
#elif defined(OS_WIN)
// Windows makes high-resolution thread timing information available in
// user-space.
has_non_stop_time_stamp_counter_ = true;
#endif
#endif
}

Просмотреть файл

@ -6,25 +6,11 @@
#define BASE_CPU_H_
#include <string>
#include <tuple>
#include "base/base_export.h"
#include "build/build_config.h"
namespace base {
#if defined(ARCH_CPU_X86_FAMILY)
namespace internal {
// Compute the CPU family and model based on the vendor and CPUID signature.
// Returns in order: family, model, extended family, extended model.
BASE_EXPORT std::tuple<int, int, int, int> ComputeX86FamilyAndModel(
const std::string& vendor,
int signature);
} // namespace internal
#endif // defined(ARCH_CPU_X86_FAMILY)
// Query information about the processor.
class BASE_EXPORT CPU final {
public:
@ -66,7 +52,6 @@ class BASE_EXPORT CPU final {
bool has_non_stop_time_stamp_counter() const {
return has_non_stop_time_stamp_counter_;
}
bool is_running_in_vm() const { return is_running_in_vm_; }
IntelMicroArchitecture GetIntelMicroArchitecture() const;
const std::string& cpu_brand() const { return cpu_brand_; }
@ -94,7 +79,6 @@ class BASE_EXPORT CPU final {
bool has_avx2_;
bool has_aesni_;
bool has_non_stop_time_stamp_counter_;
bool is_running_in_vm_;
std::string cpu_vendor_;
std::string cpu_brand_;
};

Просмотреть файл

@ -1,104 +0,0 @@
// 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_DEBUG_CRASH_LOGGING_H_
#define BASE_DEBUG_CRASH_LOGGING_H_
#include <stddef.h>
#include <memory>
#include "base/base_export.h"
#include "base/macros.h"
#include "base/strings/string_piece.h"
namespace base {
namespace debug {
// A crash key is an annotation that is carried along with a crash report, to
// provide additional debugging information beyond a stack trace. Crash keys
// have a name and a string value.
//
// The preferred API is //components/crash/core/common:crash_key, however not
// all clients can hold a direct dependency on that target. The API provided
// in this file indirects the dependency.
//
// Example usage:
// static CrashKeyString* crash_key =
// AllocateCrashKeyString("name", CrashKeySize::Size32);
// SetCrashKeyString(crash_key, "value");
// ClearCrashKeyString(crash_key);
// The maximum length for a crash key's value must be one of the following
// pre-determined values.
enum class CrashKeySize {
Size32 = 32,
Size64 = 64,
Size256 = 256,
};
struct CrashKeyString;
// Allocates a new crash key with the specified |name| with storage for a
// value up to length |size|. This will return null if the crash key system is
// not initialized.
BASE_EXPORT CrashKeyString* AllocateCrashKeyString(const char name[],
CrashKeySize size);
// Stores |value| into the specified |crash_key|. The |crash_key| may be null
// if AllocateCrashKeyString() returned null. If |value| is longer than the
// size with which the key was allocated, it will be truncated.
BASE_EXPORT void SetCrashKeyString(CrashKeyString* crash_key,
base::StringPiece value);
// Clears any value that was stored in |crash_key|. The |crash_key| may be
// null.
BASE_EXPORT void ClearCrashKeyString(CrashKeyString* crash_key);
// A scoper that sets the specified key to value for the lifetime of the
// object, and clears it on destruction.
class BASE_EXPORT ScopedCrashKeyString {
public:
ScopedCrashKeyString(CrashKeyString* crash_key, base::StringPiece value);
~ScopedCrashKeyString();
private:
CrashKeyString* const crash_key_;
DISALLOW_COPY_AND_ASSIGN(ScopedCrashKeyString);
};
////////////////////////////////////////////////////////////////////////////////
// The following declarations are used to initialize the crash key system
// in //base by providing implementations for the above functions.
// The virtual interface that provides the implementation for the crash key
// API. This is implemented by a higher-layer component, and the instance is
// set using the function below.
class CrashKeyImplementation {
public:
virtual ~CrashKeyImplementation() = default;
virtual CrashKeyString* Allocate(const char name[], CrashKeySize size) = 0;
virtual void Set(CrashKeyString* crash_key, base::StringPiece value) = 0;
virtual void Clear(CrashKeyString* crash_key) = 0;
};
// Initializes the crash key system in base by replacing the existing
// implementation, if it exists, with |impl|. The |impl| is copied into base.
BASE_EXPORT void SetCrashKeyImplementation(
std::unique_ptr<CrashKeyImplementation> impl);
// The base structure for a crash key, storing the allocation metadata.
struct CrashKeyString {
constexpr CrashKeyString(const char name[], CrashKeySize size)
: name(name), size(size) {}
const char* const name;
const CrashKeySize size;
};
} // namespace debug
} // namespace base
#endif // BASE_DEBUG_CRASH_LOGGING_H_

Просмотреть файл

@ -38,12 +38,6 @@ BASE_EXPORT void BreakDebugger();
BASE_EXPORT void SetSuppressDebugUI(bool suppress);
BASE_EXPORT bool IsDebugUISuppressed();
// If a debugger is present, verifies that it is properly set up, and DCHECK()s
// if misconfigured. Currently only verifies that //tools/gdb/gdbinit has been
// sourced when using gdb on Linux and //tools/lldb/lldbinit.py has been sourced
// when using lldb on macOS.
BASE_EXPORT void VerifyDebugger();
} // namespace debug
} // namespace base

Просмотреть файл

@ -19,23 +19,29 @@
#endif // defined(OS_WIN)
// TODO(peria): Enable profiling on Windows.
#if BUILDFLAG(ENABLE_PROFILING) && BUILDFLAG(USE_TCMALLOC) && !defined(OS_WIN)
#if BUILDFLAG(ENABLE_PROFILING) && !defined(NO_TCMALLOC) && !defined(OS_WIN)
#if BUILDFLAG(USE_NEW_TCMALLOC)
#include "third_party/tcmalloc/chromium/src/gperftools/profiler.h"
#else
#include "third_party/tcmalloc/gperftools-2.0/chromium/src/gperftools/profiler.h"
#endif
#endif
namespace base {
namespace debug {
// TODO(peria): Enable profiling on Windows.
#if BUILDFLAG(ENABLE_PROFILING) && BUILDFLAG(USE_TCMALLOC) && !defined(OS_WIN)
#if BUILDFLAG(ENABLE_PROFILING) && !defined(NO_TCMALLOC) && !defined(OS_WIN)
static int profile_count = 0;
void StartProfiling(const std::string& name) {
++profile_count;
std::string full_name(name);
std::string pid = NumberToString(GetCurrentProcId());
std::string count = NumberToString(profile_count);
std::string pid = IntToString(GetCurrentProcId());
std::string count = IntToString(profile_count);
ReplaceSubstringsAfterOffset(&full_name, 0, "{pid}", pid);
ReplaceSubstringsAfterOffset(&full_name, 0, "{count}", count);
ProfilerStart(full_name.c_str());
@ -152,7 +158,7 @@ FunctionType FindFunctionInImports(const char* function_name) {
base::win::PEImage image(CURRENT_MODULE());
FunctionSearchContext ctx = { function_name, NULL };
image.EnumImportChunks(FindResolutionFunctionInImports, &ctx, nullptr);
image.EnumImportChunks(FindResolutionFunctionInImports, &ctx);
return reinterpret_cast<FunctionType>(ctx.function);
}

Просмотреть файл

@ -4,6 +4,10 @@
#include "base/environment.h"
#include <stddef.h>
#include <vector>
#include "base/memory/ptr_util.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
@ -97,6 +101,23 @@ class EnvironmentImpl : public Environment {
}
};
// Parses a null-terminated input string of an environment block. The key is
// placed into the given string, and the total length of the line, including
// the terminating null, is returned.
size_t ParseEnvLine(const NativeEnvironmentString::value_type* input,
NativeEnvironmentString* key) {
// Skip to the equals or end of the string, this is the key.
size_t cur = 0;
while (input[cur] && input[cur] != '=')
cur++;
*key = NativeEnvironmentString(&input[0], cur);
// Now just skip to the end of the string.
while (input[cur])
cur++;
return cur + 1;
}
} // namespace
namespace env_vars {
@ -120,4 +141,97 @@ bool Environment::HasVar(StringPiece variable_name) {
return GetVar(variable_name, nullptr);
}
#if defined(OS_WIN)
string16 AlterEnvironment(const wchar_t* env,
const EnvironmentMap& changes) {
string16 result;
// First copy all unmodified values to the output.
size_t cur_env = 0;
string16 key;
while (env[cur_env]) {
const wchar_t* line = &env[cur_env];
size_t line_length = ParseEnvLine(line, &key);
// Keep only values not specified in the change vector.
EnvironmentMap::const_iterator found_change = changes.find(key);
if (found_change == changes.end())
result.append(line, line_length);
cur_env += line_length;
}
// Now append all modified and new values.
for (EnvironmentMap::const_iterator i = changes.begin();
i != changes.end(); ++i) {
if (!i->second.empty()) {
result.append(i->first);
result.push_back('=');
result.append(i->second);
result.push_back(0);
}
}
// An additional null marks the end of the list. We always need a double-null
// in case nothing was added above.
if (result.empty())
result.push_back(0);
result.push_back(0);
return result;
}
#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
std::unique_ptr<char* []> AlterEnvironment(const char* const* const env,
const EnvironmentMap& changes) {
std::string value_storage; // Holds concatenated null-terminated strings.
std::vector<size_t> result_indices; // Line indices into value_storage.
// First build up all of the unchanged environment strings. These are
// null-terminated of the form "key=value".
std::string key;
for (size_t i = 0; env[i]; i++) {
size_t line_length = ParseEnvLine(env[i], &key);
// Keep only values not specified in the change vector.
auto found_change = changes.find(key);
if (found_change == changes.end()) {
result_indices.push_back(value_storage.size());
value_storage.append(env[i], line_length);
}
}
// Now append all modified and new values.
for (const auto& i : changes) {
if (!i.second.empty()) {
result_indices.push_back(value_storage.size());
value_storage.append(i.first);
value_storage.push_back('=');
value_storage.append(i.second);
value_storage.push_back(0);
}
}
size_t pointer_count_required =
result_indices.size() + 1 + // Null-terminated array of pointers.
(value_storage.size() + sizeof(char*) - 1) / sizeof(char*); // Buffer.
std::unique_ptr<char* []> result(new char*[pointer_count_required]);
// The string storage goes after the array of pointers.
char* storage_data = reinterpret_cast<char*>(
&result.get()[result_indices.size() + 1]);
if (!value_storage.empty())
memcpy(storage_data, value_storage.data(), value_storage.size());
// Fill array of pointers at the beginning of the result.
for (size_t i = 0; i < result_indices.size(); i++)
result[i] = &storage_data[result_indices[i]];
result[result_indices.size()] = 0; // Null terminator.
return result;
}
#endif // OS_POSIX || OS_FUCHSIA
} // namespace base

Просмотреть файл

@ -38,23 +38,52 @@ class BASE_EXPORT Environment {
// Syntactic sugar for GetVar(variable_name, nullptr);
virtual bool HasVar(StringPiece variable_name);
// Returns true on success, otherwise returns false. This method should not
// be called in a multi-threaded process.
// Returns true on success, otherwise returns false.
virtual bool SetVar(StringPiece variable_name,
const std::string& new_value) = 0;
// Returns true on success, otherwise returns false. This method should not
// be called in a multi-threaded process.
// Returns true on success, otherwise returns false.
virtual bool UnSetVar(StringPiece variable_name) = 0;
};
#if defined(OS_WIN)
using NativeEnvironmentString = std::wstring;
typedef string16 NativeEnvironmentString;
typedef std::map<NativeEnvironmentString, NativeEnvironmentString>
EnvironmentMap;
// Returns a modified environment vector constructed from the given environment
// and the list of changes given in |changes|. Each key in the environment is
// matched against the first element of the pairs. In the event of a match, the
// value is replaced by the second of the pair, unless the second is empty, in
// which case the key-value is removed.
//
// This Windows version takes and returns a Windows-style environment block
// which is a concatenated list of null-terminated 16-bit strings. The end is
// marked by a double-null terminator. The size of the returned string will
// include the terminators.
BASE_EXPORT string16 AlterEnvironment(const wchar_t* env,
const EnvironmentMap& changes);
#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
using NativeEnvironmentString = std::string;
typedef std::string NativeEnvironmentString;
typedef std::map<NativeEnvironmentString, NativeEnvironmentString>
EnvironmentMap;
// See general comments for the Windows version above.
//
// This Posix version takes and returns a Posix-style environment block, which
// is a null-terminated list of pointers to null-terminated strings. The
// returned array will have appended to it the storage for the array itself so
// there is only one pointer to manage, but this means that you can't copy the
// array without keeping the original around.
BASE_EXPORT std::unique_ptr<char* []> AlterEnvironment(
const char* const* env,
const EnvironmentMap& changes);
#endif
using EnvironmentMap =
std::map<NativeEnvironmentString, NativeEnvironmentString>;
} // namespace base

Просмотреть файл

@ -104,7 +104,6 @@
#include <stddef.h>
#include <functional>
#include <iosfwd>
#include <string>
#include <vector>
@ -153,7 +152,7 @@ class BASE_EXPORT FilePath {
#if defined(OS_WIN)
// On Windows, for Unicode-aware applications, native pathnames are wchar_t
// arrays encoded in UTF-16.
typedef std::wstring StringType;
typedef base::string16 StringType;
#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
// On most platforms, native pathnames are char arrays, and the encoding
// may or may not be specified. On Mac OS X, native pathnames are encoded

Просмотреть файл

@ -1,25 +0,0 @@
// 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 <stddef.h>
#include "base/files/file_path.h"
#include "base/stl_util.h"
namespace base {
#if defined(FILE_PATH_USES_WIN_SEPARATORS)
const FilePath::CharType FilePath::kSeparators[] = FILE_PATH_LITERAL("\\/");
#else // FILE_PATH_USES_WIN_SEPARATORS
const FilePath::CharType FilePath::kSeparators[] = FILE_PATH_LITERAL("/");
#endif // FILE_PATH_USES_WIN_SEPARATORS
const size_t FilePath::kSeparatorsLength = base::size(kSeparators);
const FilePath::CharType FilePath::kCurrentDirectory[] = FILE_PATH_LITERAL(".");
const FilePath::CharType FilePath::kParentDirectory[] = FILE_PATH_LITERAL("..");
const FilePath::CharType FilePath::kExtensionSeparator = FILE_PATH_LITERAL('.');
} // namespace base

Просмотреть файл

@ -2,11 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/hash/hash.h"
#include "base/rand_util.h"
#include "base/third_party/cityhash/city.h"
#include "build/build_config.h"
#include "base/hash.h"
// Definition in base/third_party/superfasthash/superfasthash.c. (Third-party
// code did not come with its own header file, so declaring the function here.)
@ -15,18 +11,34 @@ extern "C" uint32_t SuperFastHash(const char* data, int len);
namespace base {
namespace {
uint32_t Hash(const void* data, size_t length) {
// Currently our in-memory hash is the same as the persistent hash. The
// split between in-memory and persistent hash functions is maintained to
// allow the in-memory hash function to be updated in the future.
return PersistentHash(data, length);
}
size_t FastHashImpl(base::span<const uint8_t> data) {
// We use the updated CityHash within our namespace (not the deprecated
// version from third_party/smhasher).
#if defined(ARCH_CPU_64_BITS)
return base::internal::cityhash_v111::CityHash64(
reinterpret_cast<const char*>(data.data()), data.size());
#else
return base::internal::cityhash_v111::CityHash32(
reinterpret_cast<const char*>(data.data()), data.size());
#endif
uint32_t Hash(const std::string& str) {
return PersistentHash(str.data(), str.size());
}
uint32_t Hash(const string16& str) {
return PersistentHash(str.data(), str.size() * sizeof(char16));
}
uint32_t PersistentHash(const void* data, size_t length) {
// This hash function must not change, since it is designed to be persistable
// to disk.
if (length > static_cast<size_t>(std::numeric_limits<int>::max())) {
NOTREACHED();
return 0;
}
return ::SuperFastHash(reinterpret_cast<const char*>(data),
static_cast<int>(length));
}
uint32_t PersistentHash(const std::string& str) {
return PersistentHash(str.data(), str.size());
}
// Implement hashing for pairs of at-most 32 bit integer values.
@ -38,7 +50,7 @@ size_t FastHashImpl(base::span<const uint8_t> data) {
// h32(x32, y32) = (h64(x32, y32) * rand_odd64 + rand16 * 2^16) % 2^64 / 2^32
//
// Contact danakj@chromium.org for any questions.
size_t HashInts32Impl(uint32_t value1, uint32_t value2) {
size_t HashInts32(uint32_t value1, uint32_t value2) {
uint64_t value1_64 = value1;
uint64_t hash64 = (value1_64 << 32) | value2;
@ -59,7 +71,7 @@ size_t HashInts32Impl(uint32_t value1, uint32_t value2) {
// breaking the two 64-bit inputs into 4 32-bit values:
// http://opendatastructures.org/versions/edition-0.1d/ods-java/node33.html#SECTION00832000000000000000
// Then we reduce our result to 32 bits if required, similar to above.
size_t HashInts64Impl(uint64_t value1, uint64_t value2) {
size_t HashInts64(uint64_t value1, uint64_t value2) {
uint32_t short_random1 = 842304669U;
uint32_t short_random2 = 619063811U;
uint32_t short_random3 = 937041849U;
@ -89,79 +101,4 @@ size_t HashInts64Impl(uint64_t value1, uint64_t value2) {
return high_bits;
}
// The random seed is used to perturb the output of base::FastHash() and
// base::HashInts() so that it is only deterministic within the lifetime of a
// process. This prevents inadvertent dependencies on the underlying
// implementation, e.g. anything that persists the hash value and expects it to
// be unchanging will break.
//
// Note: this is the same trick absl uses to generate a random seed. This is
// more robust than using base::RandBytes(), which can fail inside a sandboxed
// environment. Note that without ASLR, the seed won't be quite as random...
#if DCHECK_IS_ON()
constexpr const void* kSeed = &kSeed;
#endif
template <typename T>
T Scramble(T input) {
#if DCHECK_IS_ON()
return HashInts64Impl(input, reinterpret_cast<uintptr_t>(kSeed));
#else
return input;
#endif
}
} // namespace
size_t FastHash(base::span<const uint8_t> data) {
return Scramble(FastHashImpl(data));
}
uint32_t Hash(const void* data, size_t length) {
// Currently our in-memory hash is the same as the persistent hash. The
// split between in-memory and persistent hash functions is maintained to
// allow the in-memory hash function to be updated in the future.
return PersistentHash(data, length);
}
uint32_t Hash(const std::string& str) {
return PersistentHash(as_bytes(make_span(str)));
}
uint32_t Hash(const string16& str) {
return PersistentHash(as_bytes(make_span(str)));
}
uint32_t PersistentHash(span<const uint8_t> data) {
// This hash function must not change, since it is designed to be persistable
// to disk.
if (data.size() > static_cast<size_t>(std::numeric_limits<int>::max())) {
NOTREACHED();
return 0;
}
return ::SuperFastHash(reinterpret_cast<const char*>(data.data()),
static_cast<int>(data.size()));
}
uint32_t PersistentHash(const void* data, size_t length) {
return PersistentHash(make_span(static_cast<const uint8_t*>(data), length));
}
uint32_t PersistentHash(const std::string& str) {
return PersistentHash(str.data(), str.size());
}
size_t HashInts32(uint32_t value1, uint32_t value2) {
return Scramble(HashInts32Impl(value1, value2));
}
// Implement hashing for pairs of up-to 64-bit integer values.
// We use the compound integer hash method to produce a 64-bit hash code, by
// breaking the two 64-bit inputs into 4 32-bit values:
// http://opendatastructures.org/versions/edition-0.1d/ods-java/node33.html#SECTION00832000000000000000
// Then we reduce our result to 32 bits if required, similar to above.
size_t HashInts64(uint64_t value1, uint64_t value2) {
return Scramble(HashInts64Impl(value1, value2));
}
} // namespace base

Просмотреть файл

@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_HASH_HASH_H_
#define BASE_HASH_HASH_H_
#ifndef BASE_HASH_H_
#define BASE_HASH_H_
#include <stddef.h>
#include <stdint.h>
@ -13,42 +13,26 @@
#include <utility>
#include "base/base_export.h"
#include "base/containers/span.h"
#include "base/logging.h"
#include "base/strings/string16.h"
#include "base/strings/string_piece.h"
namespace base {
// WARNING: This hash functions should not be used for any cryptographic
// purpose.
// Deprecated: Computes a hash of a memory buffer, use FastHash() instead.
// If you need to persist a change on disk or between computers, use
// PersistentHash().
// TODO(https://crbug.com/1025358): Migrate client code to new hash function.
// Computes a hash of a memory buffer. This hash function is subject to change
// in the future, so use only for temporary in-memory structures. If you need
// to persist a change on disk or between computers, use PersistentHash().
//
// WARNING: This hash function should not be used for any cryptographic purpose.
BASE_EXPORT uint32_t Hash(const void* data, size_t length);
BASE_EXPORT uint32_t Hash(const std::string& str);
BASE_EXPORT uint32_t Hash(const string16& str);
// Really *fast* and high quality hash.
// Recommended hash function for general use, we pick the best performant
// hash for each build target.
// It is prone to be updated whenever a newer/faster hash function is
// publicly available.
// May changed without warning, do not expect stability of outputs.
BASE_EXPORT size_t FastHash(base::span<const uint8_t> data);
inline size_t FastHash(StringPiece str) {
return FastHash(as_bytes(make_span(str)));
}
// Computes a hash of a memory buffer. This hash function must not change so
// that code can use the hashed values for persistent storage purposes or
// sending across the network. If a new persistent hash function is desired, a
// new version will have to be added in addition.
//
// WARNING: This hash function should not be used for any cryptographic purpose.
BASE_EXPORT uint32_t PersistentHash(base::span<const uint8_t> data);
BASE_EXPORT uint32_t PersistentHash(const void* data, size_t length);
BASE_EXPORT uint32_t PersistentHash(const std::string& str);
@ -83,4 +67,4 @@ struct IntPairHash<std::pair<Type1, Type2>> {
} // namespace base
#endif // BASE_HASH_HASH_H_
#endif // BASE_HASH_H_

Просмотреть файл

@ -1,168 +0,0 @@
// 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.
#ifndef BASE_IMMEDIATE_CRASH_H_
#define BASE_IMMEDIATE_CRASH_H_
#include "build/build_config.h"
// Crashes in the fastest possible way with no attempt at logging.
// There are several constraints; see http://crbug.com/664209 for more context.
//
// - TRAP_SEQUENCE_() must be fatal. It should not be possible to ignore the
// resulting exception or simply hit 'continue' to skip over it in a debugger.
// - Different instances of TRAP_SEQUENCE_() must not be folded together, to
// ensure crash reports are debuggable. Unlike __builtin_trap(), asm volatile
// blocks will not be folded together.
// Note: TRAP_SEQUENCE_() previously required an instruction with a unique
// nonce since unlike clang, GCC folds together identical asm volatile
// blocks.
// - TRAP_SEQUENCE_() must produce a signal that is distinct from an invalid
// memory access.
// - TRAP_SEQUENCE_() must be treated as a set of noreturn instructions.
// __builtin_unreachable() is used to provide that hint here. clang also uses
// this as a heuristic to pack the instructions in the function epilogue to
// improve code density.
//
// Additional properties that are nice to have:
// - TRAP_SEQUENCE_() should be as compact as possible.
// - The first instruction of TRAP_SEQUENCE_() should not change, to avoid
// shifting crash reporting clusters. As a consequence of this, explicit
// assembly is preferred over intrinsics.
// Note: this last bullet point may no longer be true, and may be removed in
// the future.
// Note: TRAP_SEQUENCE Is currently split into two macro helpers due to the fact
// that clang emits an actual instruction for __builtin_unreachable() on certain
// platforms (see https://crbug.com/958675). In addition, the int3/bkpt/brk will
// be removed in followups, so splitting it up like this now makes it easy to
// land the followups.
#if defined(COMPILER_GCC)
#if defined(OS_NACL)
// Crash report accuracy is not guaranteed on NaCl.
#define TRAP_SEQUENCE1_() __builtin_trap()
#define TRAP_SEQUENCE2_() asm volatile("")
#elif defined(ARCH_CPU_X86_FAMILY)
// TODO(https://crbug.com/958675): In theory, it should be possible to use just
// int3. However, there are a number of crashes with SIGILL as the exception
// code, so it seems likely that there's a signal handler that allows execution
// to continue after SIGTRAP.
#define TRAP_SEQUENCE1_() asm volatile("int3")
#if defined(OS_MACOSX)
// Intentionally empty: __builtin_unreachable() is always part of the sequence
// (see IMMEDIATE_CRASH below) and already emits a ud2 on Mac.
#define TRAP_SEQUENCE2_() asm volatile("")
#else
#define TRAP_SEQUENCE2_() asm volatile("ud2")
#endif // defined(OS_MACOSX)
#elif defined(ARCH_CPU_ARMEL)
// bkpt will generate a SIGBUS when running on armv7 and a SIGTRAP when running
// as a 32 bit userspace app on arm64. There doesn't seem to be any way to
// cause a SIGTRAP from userspace without using a syscall (which would be a
// problem for sandboxing).
// TODO(https://crbug.com/958675): Remove bkpt from this sequence.
#define TRAP_SEQUENCE1_() asm volatile("bkpt #0")
#define TRAP_SEQUENCE2_() asm volatile("udf #0")
#elif defined(ARCH_CPU_ARM64)
// This will always generate a SIGTRAP on arm64.
// TODO(https://crbug.com/958675): Remove brk from this sequence.
#define TRAP_SEQUENCE1_() asm volatile("brk #0")
#define TRAP_SEQUENCE2_() asm volatile("hlt #0")
#else
// Crash report accuracy will not be guaranteed on other architectures, but at
// least this will crash as expected.
#define TRAP_SEQUENCE1_() __builtin_trap()
#define TRAP_SEQUENCE2_() asm volatile("")
#endif // ARCH_CPU_*
#elif defined(COMPILER_MSVC)
#if !defined(__clang__)
// MSVC x64 doesn't support inline asm, so use the MSVC intrinsic.
#define TRAP_SEQUENCE1_() __debugbreak()
#define TRAP_SEQUENCE2_()
#elif defined(ARCH_CPU_ARM64)
// Windows ARM64 uses "BRK #F000" as its breakpoint instruction, and
// __debugbreak() generates that in both VC++ and clang.
#define TRAP_SEQUENCE1_() __debugbreak()
// Intentionally empty: __builtin_unreachable() is always part of the sequence
// (see IMMEDIATE_CRASH below) and already emits a ud2 on Win64,
// https://crbug.com/958373
#define TRAP_SEQUENCE2_() __asm volatile("")
#else
#define TRAP_SEQUENCE1_() asm volatile("int3")
#define TRAP_SEQUENCE2_() asm volatile("ud2")
#endif // __clang__
#else
#error No supported trap sequence!
#endif // COMPILER_GCC
#define TRAP_SEQUENCE_() \
do { \
TRAP_SEQUENCE1_(); \
TRAP_SEQUENCE2_(); \
} while (false)
// CHECK() and the trap sequence can be invoked from a constexpr function.
// This could make compilation fail on GCC, as it forbids directly using inline
// asm inside a constexpr function. However, it allows calling a lambda
// expression including the same asm.
// The side effect is that the top of the stacktrace will not point to the
// calling function, but to this anonymous lambda. This is still useful as the
// full name of the lambda will typically include the name of the function that
// calls CHECK() and the debugger will still break at the right line of code.
#if !defined(COMPILER_GCC)
#define WRAPPED_TRAP_SEQUENCE_() TRAP_SEQUENCE_()
#else
#define WRAPPED_TRAP_SEQUENCE_() \
do { \
[] { TRAP_SEQUENCE_(); }(); \
} while (false)
#endif // !defined(COMPILER_GCC)
#if defined(__clang__) || defined(COMPILER_GCC)
// __builtin_unreachable() hints to the compiler that this is noreturn and can
// be packed in the function epilogue.
#define IMMEDIATE_CRASH() \
({ \
WRAPPED_TRAP_SEQUENCE_(); \
__builtin_unreachable(); \
})
#else
// This is supporting non-chromium user of logging.h to build with MSVC, like
// pdfium. On MSVC there is no __builtin_unreachable().
#define IMMEDIATE_CRASH() WRAPPED_TRAP_SEQUENCE_()
#endif // defined(__clang__) || defined(COMPILER_GCC)
#endif // BASE_IMMEDIATE_CRASH_H_

Просмотреть файл

@ -43,7 +43,7 @@ Location::Location(const char* function_name,
std::string Location::ToString() const {
if (has_source_info()) {
return std::string(function_name_) + "@" + file_name_ + ":" +
NumberToString(line_number_);
IntToString(line_number_);
}
return StringPrintf("pc:%p", program_counter_);
}
@ -69,25 +69,6 @@ NOINLINE Location Location::CreateFromHere(const char* function_name,
return Location(function_name, file_name, line_number, RETURN_ADDRESS());
}
#if SUPPORTS_LOCATION_BUILTINS && BUILDFLAG(ENABLE_LOCATION_SOURCE)
// static
NOINLINE Location Location::Current(const char* function_name,
const char* file_name,
int line_number) {
return Location(function_name, file_name, line_number, RETURN_ADDRESS());
}
#elif SUPPORTS_LOCATION_BUILTINS
// static
NOINLINE Location Location::Current(const char* file_name) {
return Location(file_name, RETURN_ADDRESS());
}
#else
// static
NOINLINE Location Location::Current() {
return Location(nullptr, RETURN_ADDRESS());
}
#endif
//------------------------------------------------------------------------------
NOINLINE const void* GetProgramCounter() {
return RETURN_ADDRESS();

Просмотреть файл

@ -8,29 +8,14 @@
#include <stddef.h>
#include <cassert>
#include <functional>
#include <string>
#include "base/base_export.h"
#include "base/debug/debugging_buildflags.h"
#include "base/hash/hash.h"
#include "build/build_config.h"
#include "base/hash.h"
namespace base {
#if defined(__has_builtin)
// Clang allows detection of these builtins.
#define SUPPORTS_LOCATION_BUILTINS \
(__has_builtin(__builtin_FUNCTION) && __has_builtin(__builtin_FILE) && \
__has_builtin(__builtin_LINE))
#elif defined(COMPILER_GCC) && __GNUC__ >= 7
// GCC has supported these for a long time, but they point at the function
// declaration in the case of default arguments, rather than at the call site.
#define SUPPORTS_LOCATION_BUILTINS 1
#else
#define SUPPORTS_LOCATION_BUILTINS 0
#endif
// Location provides basic info where of an object was constructed, or was
// significantly brought to life.
class BASE_EXPORT Location {
@ -88,16 +73,6 @@ class BASE_EXPORT Location {
const char* file_name,
int line_number);
#if SUPPORTS_LOCATION_BUILTINS && BUILDFLAG(ENABLE_LOCATION_SOURCE)
static Location Current(const char* function_name = __builtin_FUNCTION(),
const char* file_name = __builtin_FILE(),
int line_number = __builtin_LINE());
#elif SUPPORTS_LOCATION_BUILTINS
static Location Current(const char* file_name = __builtin_FILE());
#else
static Location Current();
#endif
private:
const char* function_name_ = nullptr;
const char* file_name_ = nullptr;
@ -133,7 +108,7 @@ template <>
struct hash<::base::Location> {
std::size_t operator()(const ::base::Location& loc) const {
const void* program_counter = loc.program_counter();
return base::FastHash(base::as_bytes(base::make_span(&program_counter, 1)));
return base::Hash(&program_counter, sizeof(void*));
}
};

Просмотреть файл

@ -8,7 +8,6 @@
#include <stddef.h>
#include <cassert>
#include <cstdint>
#include <cstring>
#include <sstream>
#include <string>
@ -18,18 +17,13 @@
#include "base/base_export.h"
#include "base/callback_forward.h"
#include "base/compiler_specific.h"
#include "base/immediate_crash.h"
#include "base/logging_buildflags.h"
#include "base/debug/debugger.h"
#include "base/macros.h"
#include "base/scoped_clear_last_error.h"
#include "base/strings/string_piece_forward.h"
#include "base/template_util.h"
#include "build/build_config.h"
#if defined(OS_CHROMEOS)
#include <cstdio>
#endif
//
// Optional message capabilities
// -----------------------------
@ -168,35 +162,27 @@ namespace logging {
// TODO(avi): do we want to do a unification of character types here?
#if defined(OS_WIN)
typedef wchar_t PathChar;
typedef base::char16 PathChar;
#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
typedef char PathChar;
#endif
// A bitmask of potential logging destinations.
using LoggingDestination = uint32_t;
// Specifies where logs will be written. Multiple destinations can be specified
// with bitwise OR.
// Unless destination is LOG_NONE, all logs with severity ERROR and above will
// be written to stderr in addition to the specified destination.
enum : uint32_t {
// Where to record logging output? A flat file and/or system debug log
// via OutputDebugString.
enum LoggingDestination {
LOG_NONE = 0,
LOG_TO_FILE = 1 << 0,
LOG_TO_SYSTEM_DEBUG_LOG = 1 << 1,
LOG_TO_STDERR = 1 << 2,
LOG_TO_ALL = LOG_TO_FILE | LOG_TO_SYSTEM_DEBUG_LOG | LOG_TO_STDERR,
LOG_TO_ALL = LOG_TO_FILE | LOG_TO_SYSTEM_DEBUG_LOG,
// On Windows, use a file next to the exe.
// On POSIX platforms, where it may not even be possible to locate the
// executable on disk, use stderr.
// On Fuchsia, use the Fuchsia logging service.
#if defined(OS_FUCHSIA) || defined(OS_NACL)
LOG_DEFAULT = LOG_TO_SYSTEM_DEBUG_LOG,
#elif defined(OS_WIN)
// On Windows, use a file next to the exe; on POSIX platforms, where
// it may not even be possible to locate the executable on disk, use
// stderr.
#if defined(OS_WIN)
LOG_DEFAULT = LOG_TO_FILE,
#elif defined(OS_POSIX)
LOG_DEFAULT = LOG_TO_SYSTEM_DEBUG_LOG | LOG_TO_STDERR,
#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
LOG_DEFAULT = LOG_TO_SYSTEM_DEBUG_LOG,
#endif
};
@ -214,22 +200,21 @@ enum LogLockingState { LOCK_LOG_FILE, DONT_LOCK_LOG_FILE };
enum OldFileDeletionState { DELETE_OLD_LOG_FILE, APPEND_TO_OLD_LOG_FILE };
struct BASE_EXPORT LoggingSettings {
// Equivalent to logging destination enum, but allows for multiple
// destinations.
uint32_t logging_dest = LOG_DEFAULT;
// The defaults values are:
//
// logging_dest: LOG_DEFAULT
// log_file: NULL
// lock_log: LOCK_LOG_FILE
// delete_old: APPEND_TO_OLD_LOG_FILE
LoggingSettings();
// The four settings below have an effect only when LOG_TO_FILE is
LoggingDestination logging_dest;
// The three settings below have an effect only when LOG_TO_FILE is
// set in |logging_dest|.
const PathChar* log_file_path = nullptr;
LogLockingState lock_log = LOCK_LOG_FILE;
OldFileDeletionState delete_old = APPEND_TO_OLD_LOG_FILE;
#if defined(OS_CHROMEOS)
// Contains an optional file that logs should be written to. If present,
// |log_file_path| will be ignored, and the logging system will take ownership
// of the FILE. If there's an error writing to this file, no fallback paths
// will be opened.
FILE* log_file = nullptr;
#endif
const PathChar* log_file;
LogLockingState lock_log;
OldFileDeletionState delete_old;
};
// Define different names for the BaseInitLoggingImpl() function depending on
@ -315,10 +300,10 @@ BASE_EXPORT void SetShowErrorDialogs(bool enable_dialogs);
// however clients can use this function to override with their own handling
// (e.g. a silent one for Unit Tests)
using LogAssertHandlerFunction =
base::RepeatingCallback<void(const char* file,
int line,
const base::StringPiece message,
const base::StringPiece stack_trace)>;
base::Callback<void(const char* file,
int line,
const base::StringPiece message,
const base::StringPiece stack_trace)>;
class BASE_EXPORT ScopedLogAssertHandler {
public:
@ -530,9 +515,9 @@ BASE_EXPORT extern std::ostream* g_swallow_stream;
class CheckOpResult {
public:
// |message| must be non-null if and only if the check failed.
constexpr CheckOpResult(std::string* message) : message_(message) {}
CheckOpResult(std::string* message) : message_(message) {}
// Returns true if the check succeeded.
constexpr operator bool() const { return !message_; }
operator bool() const { return !message_; }
// Returns the message.
std::string* message() { return message_; }
@ -540,6 +525,110 @@ class CheckOpResult {
std::string* message_;
};
// Crashes in the fastest possible way with no attempt at logging.
// There are different constraints to satisfy here, see http://crbug.com/664209
// for more context:
// - The trap instructions, and hence the PC value at crash time, have to be
// distinct and not get folded into the same opcode by the compiler.
// On Linux/Android this is tricky because GCC still folds identical
// asm volatile blocks. The workaround is generating distinct opcodes for
// each CHECK using the __COUNTER__ macro.
// - The debug info for the trap instruction has to be attributed to the source
// line that has the CHECK(), to make crash reports actionable. This rules
// out the ability of using a inline function, at least as long as clang
// doesn't support attribute(artificial).
// - Failed CHECKs should produce a signal that is distinguishable from an
// invalid memory access, to improve the actionability of crash reports.
// - The compiler should treat the CHECK as no-return instructions, so that the
// trap code can be efficiently packed in the prologue of the function and
// doesn't interfere with the main execution flow.
// - When debugging, developers shouldn't be able to accidentally step over a
// CHECK. This is achieved by putting opcodes that will cause a non
// continuable exception after the actual trap instruction.
// - Don't cause too much binary bloat.
#if defined(COMPILER_GCC)
#if defined(ARCH_CPU_X86_FAMILY) && !defined(OS_NACL)
// int 3 will generate a SIGTRAP.
#define TRAP_SEQUENCE() \
asm volatile( \
"int3; ud2; push %0;" ::"i"(static_cast<unsigned char>(__COUNTER__)))
#elif defined(ARCH_CPU_ARMEL) && !defined(OS_NACL)
// bkpt will generate a SIGBUS when running on armv7 and a SIGTRAP when running
// as a 32 bit userspace app on arm64. There doesn't seem to be any way to
// cause a SIGTRAP from userspace without using a syscall (which would be a
// problem for sandboxing).
#define TRAP_SEQUENCE() \
asm volatile("bkpt #0; udf %0;" ::"i"(__COUNTER__ % 256))
#elif defined(ARCH_CPU_ARM64) && !defined(OS_NACL)
// This will always generate a SIGTRAP on arm64.
#define TRAP_SEQUENCE() \
asm volatile("brk #0; hlt %0;" ::"i"(__COUNTER__ % 65536))
#else
// Crash report accuracy will not be guaranteed on other architectures, but at
// least this will crash as expected.
#define TRAP_SEQUENCE() __builtin_trap()
#endif // ARCH_CPU_*
#elif defined(COMPILER_MSVC)
// Clang is cleverer about coalescing int3s, so we need to add a unique-ish
// instruction following the __debugbreak() to have it emit distinct locations
// for CHECKs rather than collapsing them all together. It would be nice to use
// a short intrinsic to do this (and perhaps have only one implementation for
// both clang and MSVC), however clang-cl currently does not support intrinsics.
// On the flip side, MSVC x64 doesn't support inline asm. So, we have to have
// two implementations. Normally clang-cl's version will be 5 bytes (1 for
// `int3`, 2 for `ud2`, 2 for `push byte imm`, however, TODO(scottmg):
// https://crbug.com/694670 clang-cl doesn't currently support %'ing
// __COUNTER__, so eventually it will emit the dword form of push.
// TODO(scottmg): Reinvestigate a short sequence that will work on both
// compilers once clang supports more intrinsics. See https://crbug.com/693713.
#if !defined(__clang__)
#define TRAP_SEQUENCE() __debugbreak()
#elif defined(ARCH_CPU_ARM64)
#define TRAP_SEQUENCE() \
__asm volatile("brk #0\n hlt %0\n" ::"i"(__COUNTER__ % 65536));
#else
#define TRAP_SEQUENCE() ({ {__asm int 3 __asm ud2 __asm push __COUNTER__}; })
#endif // __clang__
#else
#error Port
#endif // COMPILER_GCC
// CHECK() and the trap sequence can be invoked from a constexpr function.
// This could make compilation fail on GCC, as it forbids directly using inline
// asm inside a constexpr function. However, it allows calling a lambda
// expression including the same asm.
// The side effect is that the top of the stacktrace will not point to the
// calling function, but to this anonymous lambda. This is still useful as the
// full name of the lambda will typically include the name of the function that
// calls CHECK() and the debugger will still break at the right line of code.
#if !defined(COMPILER_GCC)
#define WRAPPED_TRAP_SEQUENCE() TRAP_SEQUENCE()
#else
#define WRAPPED_TRAP_SEQUENCE() \
do { \
[] { TRAP_SEQUENCE(); }(); \
} while (false)
#endif
#if defined(__clang__) || defined(COMPILER_GCC)
#define IMMEDIATE_CRASH() \
({ \
WRAPPED_TRAP_SEQUENCE(); \
__builtin_unreachable(); \
})
#else
// This is supporting non-chromium user of logging.h to build with MSVC, like
// pdfium. On MSVC there is no __builtin_unreachable().
#define IMMEDIATE_CRASH() WRAPPED_TRAP_SEQUENCE()
#endif
// CHECK dies with a fatal error if condition is not true. It is *not*
// controlled by NDEBUG, so the check will be executed regardless of
// compilation mode.
@ -570,6 +659,26 @@ class CheckOpResult {
#else // !(OFFICIAL_BUILD && NDEBUG)
#if defined(_PREFAST_) && defined(OS_WIN)
// Use __analysis_assume to tell the VC++ static analysis engine that
// assert conditions are true, to suppress warnings. The LAZY_STREAM
// parameter doesn't reference 'condition' in /analyze builds because
// this evaluation confuses /analyze. The !! before condition is because
// __analysis_assume gets confused on some conditions:
// http://randomascii.wordpress.com/2011/09/13/analyze-for-visual-studio-the-ugly-part-5/
#define CHECK(condition) \
__analysis_assume(!!(condition)), \
LAZY_STREAM(LOG_STREAM(FATAL), false) \
<< "Check failed: " #condition ". "
#define PCHECK(condition) \
__analysis_assume(!!(condition)), \
LAZY_STREAM(PLOG_STREAM(FATAL), false) \
<< "Check failed: " #condition ". "
#else // _PREFAST_
// Do as much work as possible out of line to reduce inline code size.
#define CHECK(condition) \
LAZY_STREAM(::logging::LogMessage(__FILE__, __LINE__, #condition).stream(), \
@ -579,6 +688,8 @@ class CheckOpResult {
LAZY_STREAM(PLOG_STREAM(FATAL), !ANALYZER_ASSUME_TRUE(condition)) \
<< "Check failed: " #condition ". "
#endif // _PREFAST_
// Helper macro for binary operators.
// Don't use this macro directly in your code, use CHECK_EQ et al below.
// The 'switch' is used to prevent the 'else' from being ambiguous when the
@ -607,16 +718,6 @@ MakeCheckOpValueString(std::ostream* os, const T& v) {
(*os) << v;
}
// Overload for types that no operator<< but do have .ToString() defined.
template <typename T>
inline typename std::enable_if<
!base::internal::SupportsOstreamOperator<const T&>::value &&
base::internal::SupportsToString<const T&>::value,
void>::type
MakeCheckOpValueString(std::ostream* os, const T& v) {
(*os) << v.ToString();
}
// Provide an overload for functions and function pointers. Function pointers
// don't implicitly convert to void* but do implicitly convert to bool, so
// without this function pointers are always printed as 1 or 0. (MSVC isn't
@ -685,21 +786,20 @@ std::string* MakeCheckOpString<std::string, std::string>(
// The checked condition is wrapped with ANALYZER_ASSUME_TRUE, which under
// static analysis builds, blocks analysis of the current path if the
// condition is false.
#define DEFINE_CHECK_OP_IMPL(name, op) \
template <class t1, class t2> \
constexpr std::string* Check##name##Impl(const t1& v1, const t2& v2, \
const char* names) { \
if (ANALYZER_ASSUME_TRUE(v1 op v2)) \
return nullptr; \
else \
return ::logging::MakeCheckOpString(v1, v2, names); \
} \
constexpr std::string* Check##name##Impl(int v1, int v2, \
const char* names) { \
if (ANALYZER_ASSUME_TRUE(v1 op v2)) \
return nullptr; \
else \
return ::logging::MakeCheckOpString(v1, v2, names); \
#define DEFINE_CHECK_OP_IMPL(name, op) \
template <class t1, class t2> \
inline std::string* Check##name##Impl(const t1& v1, const t2& v2, \
const char* names) { \
if (ANALYZER_ASSUME_TRUE(v1 op v2)) \
return NULL; \
else \
return ::logging::MakeCheckOpString(v1, v2, names); \
} \
inline std::string* Check##name##Impl(int v1, int v2, const char* names) { \
if (ANALYZER_ASSUME_TRUE(v1 op v2)) \
return NULL; \
else \
return ::logging::MakeCheckOpString(v1, v2, names); \
}
DEFINE_CHECK_OP_IMPL(EQ, ==)
DEFINE_CHECK_OP_IMPL(NE, !=)
@ -717,9 +817,9 @@ DEFINE_CHECK_OP_IMPL(GT, > )
#define CHECK_GT(val1, val2) CHECK_OP(GT, > , val1, val2)
#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
#define DCHECK_IS_ON() false
#define DCHECK_IS_ON() 0
#else
#define DCHECK_IS_ON() true
#define DCHECK_IS_ON() 1
#endif
// Definitions for DLOG et al.
@ -785,6 +885,21 @@ const LogSeverity LOG_DCHECK = LOG_FATAL;
// DCHECK_IS_ON() is true. When DCHECK_IS_ON() is false, the macros use
// EAT_STREAM_PARAMETERS to avoid expressions that would create temporaries.
#if defined(_PREFAST_) && defined(OS_WIN)
// See comments on the previous use of __analysis_assume.
#define DCHECK(condition) \
__analysis_assume(!!(condition)), \
LAZY_STREAM(LOG_STREAM(DCHECK), false) \
<< "Check failed: " #condition ". "
#define DPCHECK(condition) \
__analysis_assume(!!(condition)), \
LAZY_STREAM(PLOG_STREAM(DCHECK), false) \
<< "Check failed: " #condition ". "
#else // !(defined(_PREFAST_) && defined(OS_WIN))
#if DCHECK_IS_ON()
#define DCHECK(condition) \
@ -801,6 +916,8 @@ const LogSeverity LOG_DCHECK = LOG_FATAL;
#endif // DCHECK_IS_ON()
#endif // defined(_PREFAST_) && defined(OS_WIN)
// Helper macro for binary operators.
// Don't use this macro directly in your code, use DCHECK_EQ et al below.
// The 'switch' is used to prevent the 'else' from being ambiguous when the
@ -865,7 +982,7 @@ const LogSeverity LOG_DCHECK = LOG_FATAL;
#define DCHECK_GE(val1, val2) DCHECK_OP(GE, >=, val1, val2)
#define DCHECK_GT(val1, val2) DCHECK_OP(GT, > , val1, val2)
#if BUILDFLAG(ENABLE_LOG_ERROR_NOT_REACHED)
#if !DCHECK_IS_ON() && defined(OS_CHROMEOS)
// Implement logging of NOTREACHED() as a dedicated function to get function
// call overhead down to a minimum.
void LogErrorNotReached(const char* file, int line);
@ -921,7 +1038,6 @@ class BASE_EXPORT LogMessage {
// The file and line information passed in to the constructor.
const char* file_;
const int line_;
const char* file_basename_;
// This is useful since the LogMessage class uses a lot of Win32 calls
// that will lose the value of GLE and the code that called the log function
@ -1001,14 +1117,6 @@ class BASE_EXPORT ErrnoLogMessage {
// after this call.
BASE_EXPORT void CloseLogFile();
#if defined(OS_CHROMEOS)
// Returns a new file handle that will write to the same destination as the
// currently open log file. Returns nullptr if logging to a file is disabled,
// or if opening the file failed. This is intended to be used to initialize
// logging in child processes that are unable to open files.
BASE_EXPORT FILE* DuplicateLogFILE();
#endif
// Async signal safe logging mechanism.
BASE_EXPORT void RawLog(int level, const char* message);
@ -1027,7 +1135,7 @@ BASE_EXPORT void RawLog(int level, const char* message);
BASE_EXPORT bool IsLoggingToFileEnabled();
// Returns the default log file path.
BASE_EXPORT std::wstring GetLogFileFullPath();
BASE_EXPORT base::string16 GetLogFileFullPath();
#endif
} // namespace logging
@ -1065,13 +1173,18 @@ inline std::ostream& operator<<(std::ostream& out, const std::wstring& wstr) {
#define NOTIMPLEMENTED_MSG "NOT IMPLEMENTED"
#endif
#define NOTIMPLEMENTED() DLOG(ERROR) << NOTIMPLEMENTED_MSG
#define NOTIMPLEMENTED_LOG_ONCE() \
do { \
static bool logged_once = false; \
DLOG_IF(ERROR, !logged_once) << NOTIMPLEMENTED_MSG; \
logged_once = true; \
} while (0); \
#if defined(OS_ANDROID) && defined(OFFICIAL_BUILD)
#define NOTIMPLEMENTED() EAT_STREAM_PARAMETERS
#define NOTIMPLEMENTED_LOG_ONCE() EAT_STREAM_PARAMETERS
#else
#define NOTIMPLEMENTED() LOG(ERROR) << NOTIMPLEMENTED_MSG
#define NOTIMPLEMENTED_LOG_ONCE() \
do { \
static bool logged_once = false; \
LOG_IF(ERROR, !logged_once) << NOTIMPLEMENTED_MSG; \
logged_once = true; \
} while (0); \
EAT_STREAM_PARAMETERS
#endif
#endif // BASE_LOGGING_H_

Просмотреть файл

@ -10,10 +10,6 @@
#ifndef BASE_MACROS_H_
#define BASE_MACROS_H_
// ALL DISALLOW_xxx MACROS ARE DEPRECATED; DO NOT USE IN NEW CODE.
// Use explicit deletions instead. See the section on copyability/movability in
// //styleguide/c++/c++-dos-and-donts.md for more information.
// Put this in the declarations for a class to be uncopyable.
#define DISALLOW_COPY(TypeName) \
TypeName(const TypeName&) = delete

Просмотреть файл

@ -1,62 +0,0 @@
// 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/memory/platform_shared_memory_region.h"
#include "base/memory/shared_memory_mapping.h"
#include "base/numerics/checked_math.h"
namespace base {
namespace subtle {
// static
PlatformSharedMemoryRegion PlatformSharedMemoryRegion::CreateWritable(
size_t size) {
return Create(Mode::kWritable, size);
}
// static
PlatformSharedMemoryRegion PlatformSharedMemoryRegion::CreateUnsafe(
size_t size) {
return Create(Mode::kUnsafe, size);
}
PlatformSharedMemoryRegion::PlatformSharedMemoryRegion() = default;
PlatformSharedMemoryRegion::PlatformSharedMemoryRegion(
PlatformSharedMemoryRegion&& other) = default;
PlatformSharedMemoryRegion& PlatformSharedMemoryRegion::operator=(
PlatformSharedMemoryRegion&& other) = default;
PlatformSharedMemoryRegion::~PlatformSharedMemoryRegion() = default;
PlatformSharedMemoryRegion::ScopedPlatformHandle
PlatformSharedMemoryRegion::PassPlatformHandle() {
return std::move(handle_);
}
bool PlatformSharedMemoryRegion::MapAt(off_t offset,
size_t size,
void** memory,
size_t* mapped_size) const {
if (!IsValid())
return false;
if (size == 0)
return false;
size_t end_byte;
if (!CheckAdd(offset, size).AssignIfValid(&end_byte) || end_byte > size_) {
return false;
}
bool success = MapAtInternal(offset, size, memory, mapped_size);
if (success) {
DCHECK_EQ(
0U, reinterpret_cast<uintptr_t>(*memory) & (kMapMinimumAlignment - 1));
}
return success;
}
} // namespace subtle
} // namespace base

Просмотреть файл

@ -1,301 +0,0 @@
// 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_MEMORY_PLATFORM_SHARED_MEMORY_REGION_H_
#define BASE_MEMORY_PLATFORM_SHARED_MEMORY_REGION_H_
#include <utility>
#include "base/compiler_specific.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/unguessable_token.h"
#include "build/build_config.h"
#if defined(OS_MACOSX) && !defined(OS_IOS)
#include <mach/mach.h>
#include "base/mac/scoped_mach_port.h"
#elif defined(OS_FUCHSIA)
#include <lib/zx/vmo.h>
#elif defined(OS_WIN)
#include "base/win/scoped_handle.h"
#include "base/win/windows_types.h"
#elif defined(OS_POSIX)
#include <sys/types.h>
#include "base/file_descriptor_posix.h"
#include "base/files/scoped_file.h"
#endif
#if defined(OS_LINUX)
namespace content {
class SandboxIPCHandler;
}
#endif
namespace base {
namespace subtle {
#if defined(OS_POSIX) && (!defined(OS_MACOSX) || defined(OS_IOS)) && \
!defined(OS_ANDROID)
// Helper structs to keep two descriptors on POSIX. It's needed to support
// ConvertToReadOnly().
struct BASE_EXPORT FDPair {
// The main shared memory descriptor that is used for mapping. May be either
// writable or read-only, depending on region's mode.
int fd;
// The read-only descriptor, valid only in kWritable mode. Replaces |fd| when
// a region is converted to read-only.
int readonly_fd;
};
struct BASE_EXPORT ScopedFDPair {
ScopedFDPair();
ScopedFDPair(ScopedFD in_fd, ScopedFD in_readonly_fd);
ScopedFDPair(ScopedFDPair&&);
ScopedFDPair& operator=(ScopedFDPair&&);
~ScopedFDPair();
FDPair get() const;
ScopedFD fd;
ScopedFD readonly_fd;
};
#endif
// Implementation class for shared memory regions.
//
// This class does the following:
//
// - Wraps and owns a shared memory region platform handle.
// - Provides a way to allocate a new region of platform shared memory of given
// size.
// - Provides a way to create mapping of the region in the current process'
// address space, under special access-control constraints (see Mode).
// - Provides methods to help transferring the handle across process boundaries.
// - Holds a 128-bit unique identifier used to uniquely identify the same
// kernel region resource across processes (used for memory tracking).
// - Has a method to retrieve the region's size in bytes.
//
// IMPORTANT NOTE: Users should never use this directly, but
// ReadOnlySharedMemoryRegion, WritableSharedMemoryRegion or
// UnsafeSharedMemoryRegion since this is an implementation class.
class BASE_EXPORT PlatformSharedMemoryRegion {
public:
// Permission mode of the platform handle. Each mode corresponds to one of the
// typed shared memory classes:
//
// * ReadOnlySharedMemoryRegion: A region that can only create read-only
// mappings.
//
// * WritableSharedMemoryRegion: A region that can only create writable
// mappings. The region can be demoted to ReadOnlySharedMemoryRegion without
// the possibility of promoting back to writable.
//
// * UnsafeSharedMemoryRegion: A region that can only create writable
// mappings. The region cannot be demoted to ReadOnlySharedMemoryRegion.
enum class Mode {
kReadOnly, // ReadOnlySharedMemoryRegion
kWritable, // WritableSharedMemoryRegion
kUnsafe, // UnsafeSharedMemoryRegion
kMaxValue = kUnsafe
};
// Errors that can occur during Shared Memory construction.
// These match tools/metrics/histograms/enums.xml.
// This enum is append-only.
enum class CreateError {
SUCCESS = 0,
SIZE_ZERO = 1,
SIZE_TOO_LARGE = 2,
INITIALIZE_ACL_FAILURE = 3,
INITIALIZE_SECURITY_DESC_FAILURE = 4,
SET_SECURITY_DESC_FAILURE = 5,
CREATE_FILE_MAPPING_FAILURE = 6,
REDUCE_PERMISSIONS_FAILURE = 7,
ALREADY_EXISTS = 8,
ALLOCATE_FILE_REGION_FAILURE = 9,
FSTAT_FAILURE = 10,
INODES_MISMATCH = 11,
GET_SHMEM_TEMP_DIR_FAILURE = 12,
kMaxValue = GET_SHMEM_TEMP_DIR_FAILURE
};
#if defined(OS_LINUX)
// Structure to limit access to executable region creation.
struct ExecutableRegion {
private:
// Creates a new shared memory region the unsafe mode (writable and not and
// convertible to read-only), and in addition marked executable. A ScopedFD
// to this region is returned. Any any mapping will have to be done
// manually, including setting executable permissions if necessary
//
// This is only used to support sandbox_ipc_linux.cc, and should not be used
// anywhere else in chrome. This is restricted via AllowCreateExecutable.
// TODO(crbug.com/982879): remove this when NaCl is unshipped.
//
// Returns an invalid ScopedFD if the call fails.
static ScopedFD CreateFD(size_t size);
friend class content::SandboxIPCHandler;
};
#endif
// Platform-specific shared memory type used by this class.
#if defined(OS_MACOSX) && !defined(OS_IOS)
using PlatformHandle = mach_port_t;
using ScopedPlatformHandle = mac::ScopedMachSendRight;
#elif defined(OS_FUCHSIA)
using PlatformHandle = zx::unowned_vmo;
using ScopedPlatformHandle = zx::vmo;
#elif defined(OS_WIN)
using PlatformHandle = HANDLE;
using ScopedPlatformHandle = win::ScopedHandle;
#elif defined(OS_ANDROID)
using PlatformHandle = int;
using ScopedPlatformHandle = ScopedFD;
#else
using PlatformHandle = FDPair;
using ScopedPlatformHandle = ScopedFDPair;
#endif
// The minimum alignment in bytes that any mapped address produced by Map()
// and MapAt() is guaranteed to have.
enum { kMapMinimumAlignment = 32 };
// Creates a new PlatformSharedMemoryRegion with corresponding mode and size.
// Creating in kReadOnly mode isn't supported because then there will be no
// way to modify memory content.
static PlatformSharedMemoryRegion CreateWritable(size_t size);
static PlatformSharedMemoryRegion CreateUnsafe(size_t size);
// Returns a new PlatformSharedMemoryRegion that takes ownership of the
// |handle|. All parameters must be taken from another valid
// PlatformSharedMemoryRegion instance, e.g. |size| must be equal to the
// actual region size as allocated by the kernel.
// Closes the |handle| and returns an invalid instance if passed parameters
// are invalid.
static PlatformSharedMemoryRegion Take(ScopedPlatformHandle handle,
Mode mode,
size_t size,
const UnguessableToken& guid);
#if defined(OS_POSIX) && !defined(OS_ANDROID) && \
!(defined(OS_MACOSX) && !defined(OS_IOS))
// Specialized version of Take() for POSIX that takes only one file descriptor
// instead of pair. Cannot be used with kWritable |mode|.
static PlatformSharedMemoryRegion Take(ScopedFD handle,
Mode mode,
size_t size,
const UnguessableToken& guid);
#endif
// Default constructor initializes an invalid instance, i.e. an instance that
// doesn't wrap any valid platform handle.
PlatformSharedMemoryRegion();
// Move operations are allowed.
PlatformSharedMemoryRegion(PlatformSharedMemoryRegion&&);
PlatformSharedMemoryRegion& operator=(PlatformSharedMemoryRegion&&);
// Destructor closes the platform handle. Does nothing if the handle is
// invalid.
~PlatformSharedMemoryRegion();
// Passes ownership of the platform handle to the caller. The current instance
// becomes invalid. It's the responsibility of the caller to close the
// handle. If the current instance is invalid, ScopedPlatformHandle will also
// be invalid.
ScopedPlatformHandle PassPlatformHandle() WARN_UNUSED_RESULT;
// Returns the platform handle. The current instance keeps ownership of this
// handle.
PlatformHandle GetPlatformHandle() const;
// Whether the platform handle is valid.
bool IsValid() const;
// Duplicates the platform handle and creates a new PlatformSharedMemoryRegion
// with the same |mode_|, |size_| and |guid_| that owns this handle. Returns
// invalid region on failure, the current instance remains valid.
// Can be called only in kReadOnly and kUnsafe modes, CHECK-fails if is
// called in kWritable mode.
PlatformSharedMemoryRegion Duplicate() const;
// Converts the region to read-only. Returns whether the operation succeeded.
// Makes the current instance invalid on failure. Can be called only in
// kWritable mode, all other modes will CHECK-fail. The object will have
// kReadOnly mode after this call on success.
bool ConvertToReadOnly();
#if defined(OS_MACOSX) && !defined(OS_IOS)
// Same as above, but |mapped_addr| is used as a hint to avoid additional
// mapping of the memory object.
// |mapped_addr| must be mapped location of |memory_object_|. If the location
// is unknown, |mapped_addr| should be |nullptr|.
bool ConvertToReadOnly(void* mapped_addr);
#endif // defined(OS_MACOSX) && !defined(OS_IOS)
// Converts the region to unsafe. Returns whether the operation succeeded.
// Makes the current instance invalid on failure. Can be called only in
// kWritable mode, all other modes will CHECK-fail. The object will have
// kUnsafe mode after this call on success.
bool ConvertToUnsafe();
// Maps |size| bytes of the shared memory region starting with the given
// |offset| into the caller's address space. |offset| must be aligned to value
// of |SysInfo::VMAllocationGranularity()|. Fails if requested bytes are out
// of the region limits.
// Returns true and sets |memory| and |mapped_size| on success, returns false
// and leaves output parameters in unspecified state otherwise. The mapped
// address is guaranteed to have an alignment of at least
// |kMapMinimumAlignment|.
bool MapAt(off_t offset,
size_t size,
void** memory,
size_t* mapped_size) const;
const UnguessableToken& GetGUID() const { return guid_; }
size_t GetSize() const { return size_; }
Mode GetMode() const { return mode_; }
private:
FRIEND_TEST_ALL_PREFIXES(PlatformSharedMemoryRegionTest,
CreateReadOnlyRegionDeathTest);
FRIEND_TEST_ALL_PREFIXES(PlatformSharedMemoryRegionTest,
CheckPlatformHandlePermissionsCorrespondToMode);
static PlatformSharedMemoryRegion Create(Mode mode,
size_t size
#if defined(OS_LINUX)
,
bool executable = false
#endif
);
static bool CheckPlatformHandlePermissionsCorrespondToMode(
PlatformHandle handle,
Mode mode,
size_t size);
PlatformSharedMemoryRegion(ScopedPlatformHandle handle,
Mode mode,
size_t size,
const UnguessableToken& guid);
bool MapAtInternal(off_t offset,
size_t size,
void** memory,
size_t* mapped_size) const;
ScopedPlatformHandle handle_;
Mode mode_ = Mode::kReadOnly;
size_t size_ = 0;
UnguessableToken guid_;
DISALLOW_COPY_AND_ASSIGN(PlatformSharedMemoryRegion);
};
} // namespace subtle
} // namespace base
#endif // BASE_MEMORY_PLATFORM_SHARED_MEMORY_REGION_H_

Просмотреть файл

@ -1,343 +0,0 @@
// 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/memory/platform_shared_memory_region.h"
#include <aclapi.h>
#include <stddef.h>
#include <stdint.h>
#include "base/allocator/partition_allocator/page_allocator.h"
#include "base/bits.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/process/process_handle.h"
#include "base/rand_util.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/win/windows_version.h"
namespace base {
namespace subtle {
namespace {
// Emits UMA metrics about encountered errors. Pass zero (0) for |winerror|
// if there is no associated Windows error.
void LogError(PlatformSharedMemoryRegion::CreateError error, DWORD winerror) {
UMA_HISTOGRAM_ENUMERATION("SharedMemory.CreateError", error);
static_assert(ERROR_SUCCESS == 0, "Windows error code changed!");
if (winerror != ERROR_SUCCESS)
UmaHistogramSparse("SharedMemory.CreateWinError", winerror);
}
typedef enum _SECTION_INFORMATION_CLASS {
SectionBasicInformation,
} SECTION_INFORMATION_CLASS;
typedef struct _SECTION_BASIC_INFORMATION {
PVOID BaseAddress;
ULONG Attributes;
LARGE_INTEGER Size;
} SECTION_BASIC_INFORMATION, *PSECTION_BASIC_INFORMATION;
typedef ULONG(__stdcall* NtQuerySectionType)(
HANDLE SectionHandle,
SECTION_INFORMATION_CLASS SectionInformationClass,
PVOID SectionInformation,
ULONG SectionInformationLength,
PULONG ResultLength);
// Returns the length of the memory section starting at the supplied address.
size_t GetMemorySectionSize(void* address) {
MEMORY_BASIC_INFORMATION memory_info;
if (!::VirtualQuery(address, &memory_info, sizeof(memory_info)))
return 0;
return memory_info.RegionSize -
(static_cast<char*>(address) -
static_cast<char*>(memory_info.AllocationBase));
}
// Checks if the section object is safe to map. At the moment this just means
// it's not an image section.
bool IsSectionSafeToMap(HANDLE handle) {
static NtQuerySectionType nt_query_section_func =
reinterpret_cast<NtQuerySectionType>(
::GetProcAddress(::GetModuleHandle(L"ntdll.dll"), "NtQuerySection"));
DCHECK(nt_query_section_func);
// The handle must have SECTION_QUERY access for this to succeed.
SECTION_BASIC_INFORMATION basic_information = {};
ULONG status =
nt_query_section_func(handle, SectionBasicInformation, &basic_information,
sizeof(basic_information), nullptr);
if (status)
return false;
return (basic_information.Attributes & SEC_IMAGE) != SEC_IMAGE;
}
// Returns a HANDLE on success and |nullptr| on failure.
// This function is similar to CreateFileMapping, but removes the permissions
// WRITE_DAC, WRITE_OWNER, READ_CONTROL, and DELETE.
//
// A newly created file mapping has two sets of permissions. It has access
// control permissions (WRITE_DAC, WRITE_OWNER, READ_CONTROL, and DELETE) and
// file permissions (FILE_MAP_READ, FILE_MAP_WRITE, etc.). The Chrome sandbox
// prevents HANDLEs with the WRITE_DAC permission from being duplicated into
// unprivileged processes.
//
// In order to remove the access control permissions, after being created the
// handle is duplicated with only the file access permissions.
HANDLE CreateFileMappingWithReducedPermissions(SECURITY_ATTRIBUTES* sa,
size_t rounded_size,
LPCWSTR name) {
HANDLE h = CreateFileMapping(INVALID_HANDLE_VALUE, sa, PAGE_READWRITE, 0,
static_cast<DWORD>(rounded_size), name);
if (!h) {
LogError(
PlatformSharedMemoryRegion::CreateError::CREATE_FILE_MAPPING_FAILURE,
GetLastError());
return nullptr;
}
HANDLE h2;
ProcessHandle process = GetCurrentProcess();
BOOL success = ::DuplicateHandle(
process, h, process, &h2, FILE_MAP_READ | FILE_MAP_WRITE | SECTION_QUERY,
FALSE, 0);
BOOL rv = ::CloseHandle(h);
DCHECK(rv);
if (!success) {
LogError(
PlatformSharedMemoryRegion::CreateError::REDUCE_PERMISSIONS_FAILURE,
GetLastError());
return nullptr;
}
return h2;
}
} // namespace
// static
PlatformSharedMemoryRegion PlatformSharedMemoryRegion::Take(
win::ScopedHandle handle,
Mode mode,
size_t size,
const UnguessableToken& guid) {
if (!handle.IsValid())
return {};
if (size == 0)
return {};
if (size > static_cast<size_t>(std::numeric_limits<int>::max()))
return {};
if (!IsSectionSafeToMap(handle.Get()))
return {};
CHECK(
CheckPlatformHandlePermissionsCorrespondToMode(handle.Get(), mode, size));
return PlatformSharedMemoryRegion(std::move(handle), mode, size, guid);
}
HANDLE PlatformSharedMemoryRegion::GetPlatformHandle() const {
return handle_.Get();
}
bool PlatformSharedMemoryRegion::IsValid() const {
return handle_.IsValid();
}
PlatformSharedMemoryRegion PlatformSharedMemoryRegion::Duplicate() const {
if (!IsValid())
return {};
CHECK_NE(mode_, Mode::kWritable)
<< "Duplicating a writable shared memory region is prohibited";
HANDLE duped_handle;
ProcessHandle process = GetCurrentProcess();
BOOL success =
::DuplicateHandle(process, handle_.Get(), process, &duped_handle, 0,
FALSE, DUPLICATE_SAME_ACCESS);
if (!success)
return {};
return PlatformSharedMemoryRegion(win::ScopedHandle(duped_handle), mode_,
size_, guid_);
}
bool PlatformSharedMemoryRegion::ConvertToReadOnly() {
if (!IsValid())
return false;
CHECK_EQ(mode_, Mode::kWritable)
<< "Only writable shared memory region can be converted to read-only";
win::ScopedHandle handle_copy(handle_.Take());
HANDLE duped_handle;
ProcessHandle process = GetCurrentProcess();
BOOL success =
::DuplicateHandle(process, handle_copy.Get(), process, &duped_handle,
FILE_MAP_READ | SECTION_QUERY, FALSE, 0);
if (!success)
return false;
handle_.Set(duped_handle);
mode_ = Mode::kReadOnly;
return true;
}
bool PlatformSharedMemoryRegion::ConvertToUnsafe() {
if (!IsValid())
return false;
CHECK_EQ(mode_, Mode::kWritable)
<< "Only writable shared memory region can be converted to unsafe";
mode_ = Mode::kUnsafe;
return true;
}
bool PlatformSharedMemoryRegion::MapAtInternal(off_t offset,
size_t size,
void** memory,
size_t* mapped_size) const {
bool write_allowed = mode_ != Mode::kReadOnly;
// Try to map the shared memory. On the first failure, release any reserved
// address space for a single entry.
for (int i = 0; i < 2; ++i) {
*memory = MapViewOfFile(
handle_.Get(), FILE_MAP_READ | (write_allowed ? FILE_MAP_WRITE : 0),
static_cast<uint64_t>(offset) >> 32, static_cast<DWORD>(offset), size);
if (*memory)
break;
ReleaseReservation();
}
if (!*memory) {
DPLOG(ERROR) << "Failed executing MapViewOfFile";
return false;
}
*mapped_size = GetMemorySectionSize(*memory);
return true;
}
// static
PlatformSharedMemoryRegion PlatformSharedMemoryRegion::Create(Mode mode,
size_t size) {
// TODO(crbug.com/210609): NaCl forces us to round up 64k here, wasting 32k
// per mapping on average.
static const size_t kSectionSize = 65536;
if (size == 0) {
LogError(CreateError::SIZE_ZERO, 0);
return {};
}
// Aligning may overflow so check that the result doesn't decrease.
size_t rounded_size = bits::Align(size, kSectionSize);
if (rounded_size < size ||
rounded_size > static_cast<size_t>(std::numeric_limits<int>::max())) {
LogError(CreateError::SIZE_TOO_LARGE, 0);
return {};
}
CHECK_NE(mode, Mode::kReadOnly) << "Creating a region in read-only mode will "
"lead to this region being non-modifiable";
// Add an empty DACL to enforce anonymous read-only sections.
ACL dacl;
SECURITY_DESCRIPTOR sd;
if (!InitializeAcl(&dacl, sizeof(dacl), ACL_REVISION)) {
LogError(CreateError::INITIALIZE_ACL_FAILURE, GetLastError());
return {};
}
if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
LogError(CreateError::INITIALIZE_SECURITY_DESC_FAILURE, GetLastError());
return {};
}
if (!SetSecurityDescriptorDacl(&sd, TRUE, &dacl, FALSE)) {
LogError(CreateError::SET_SECURITY_DESC_FAILURE, GetLastError());
return {};
}
string16 name;
if (win::GetVersion() < win::Version::WIN8_1) {
// Windows < 8.1 ignores DACLs on certain unnamed objects (like shared
// sections). So, we generate a random name when we need to enforce
// read-only.
uint64_t rand_values[4];
RandBytes(&rand_values, sizeof(rand_values));
name = ASCIIToUTF16(StringPrintf("CrSharedMem_%016llx%016llx%016llx%016llx",
rand_values[0], rand_values[1],
rand_values[2], rand_values[3]));
DCHECK(!name.empty());
}
SECURITY_ATTRIBUTES sa = {sizeof(sa), &sd, FALSE};
// Ask for the file mapping with reduced permisions to avoid passing the
// access control permissions granted by default into unpriviledged process.
HANDLE h = CreateFileMappingWithReducedPermissions(
&sa, rounded_size, name.empty() ? nullptr : as_wcstr(name));
if (h == nullptr) {
// The error is logged within CreateFileMappingWithReducedPermissions().
return {};
}
win::ScopedHandle scoped_h(h);
// Check if the shared memory pre-exists.
if (GetLastError() == ERROR_ALREADY_EXISTS) {
LogError(CreateError::ALREADY_EXISTS, ERROR_ALREADY_EXISTS);
return {};
}
LogError(CreateError::SUCCESS, ERROR_SUCCESS);
return PlatformSharedMemoryRegion(std::move(scoped_h), mode, size,
UnguessableToken::Create());
}
// static
bool PlatformSharedMemoryRegion::CheckPlatformHandlePermissionsCorrespondToMode(
PlatformHandle handle,
Mode mode,
size_t size) {
// Call ::DuplicateHandle() with FILE_MAP_WRITE as a desired access to check
// if the |handle| has a write access.
ProcessHandle process = GetCurrentProcess();
HANDLE duped_handle;
BOOL success = ::DuplicateHandle(process, handle, process, &duped_handle,
FILE_MAP_WRITE, FALSE, 0);
if (success) {
BOOL rv = ::CloseHandle(duped_handle);
DCHECK(rv);
}
bool is_read_only = !success;
bool expected_read_only = mode == Mode::kReadOnly;
if (is_read_only != expected_read_only) {
DLOG(ERROR) << "File mapping handle has wrong access rights: it is"
<< (is_read_only ? " " : " not ") << "read-only but it should"
<< (expected_read_only ? " " : " not ") << "be";
return false;
}
return true;
}
PlatformSharedMemoryRegion::PlatformSharedMemoryRegion(
win::ScopedHandle handle,
Mode mode,
size_t size,
const UnguessableToken& guid)
: handle_(std::move(handle)), mode_(mode), size_(size), guid_(guid) {}
} // namespace subtle
} // namespace base

Просмотреть файл

@ -4,9 +4,6 @@
#include "base/memory/ref_counted.h"
#include <limits>
#include <type_traits>
#include "base/threading/thread_collision_warner.h"
namespace base {
@ -35,35 +32,15 @@ RefCountedThreadSafeBase::~RefCountedThreadSafeBase() {
}
#endif
// For security and correctness, we check the arithmetic on ref counts.
//
// In an attempt to avoid binary bloat (from inlining the `CHECK`), we define
// these functions out-of-line. However, compilers are wily. Further testing may
// show that `NOINLINE` helps or hurts.
//
// This is a security check. In 32-bit-archs, an attacker would run out of
// address space after allocating at most 2^32 scoped_refptrs. This replicates
// that boundary for 64-bit-archs.
#if defined(ARCH_CPU_64_BITS)
void RefCountedBase::AddRefImpl() const {
// An attacker could induce use-after-free bugs, and potentially exploit them,
// by creating so many references to a ref-counted object that the reference
// count overflows. On 32-bit architectures, there is not enough address space
// to succeed. But on 64-bit architectures, it might indeed be possible.
// Therefore, we can elide the check for arithmetic overflow on 32-bit, but we
// must check on 64-bit.
//
// Make sure the addition didn't wrap back around to 0. This form of check
// works because we assert that `ref_count_` is an unsigned integer type.
CHECK(++ref_count_ != 0);
}
void RefCountedBase::ReleaseImpl() const {
// Make sure the subtraction didn't wrap back around from 0 to the max value.
// That could cause memory leaks, and may induce application-semantic
// correctness or safety bugs. (E.g. what if we really needed that object to
// be destroyed at the right time?)
//
// Note that unlike with overflow, underflow could also happen on 32-bit
// architectures. Arguably, we should do this check on32-bit machines too.
CHECK(--ref_count_ != std::numeric_limits<decltype(ref_count_)>::max());
// Check if |ref_count_| overflow only on 64 bit archs since the number of
// objects may exceed 2^32.
// To avoid the binary size bloat, use non-inline function here.
CHECK(++ref_count_ > 0);
}
#endif

Просмотреть файл

@ -69,7 +69,7 @@ class BASE_EXPORT RefCountedBase {
// Returns true if the object should self-delete.
bool Release() const {
ReleaseImpl();
--ref_count_;
// TODO(maruel): Add back once it doesn't assert 500 times/sec.
// Current thread books the critical section "AddRelease"
@ -126,10 +126,8 @@ class BASE_EXPORT RefCountedBase {
#if defined(ARCH_CPU_64_BITS)
void AddRefImpl() const;
void ReleaseImpl() const;
#else
void AddRefImpl() const { ++ref_count_; }
void ReleaseImpl() const { --ref_count_; }
#endif
#if DCHECK_IS_ON()
@ -137,8 +135,6 @@ class BASE_EXPORT RefCountedBase {
#endif
mutable uint32_t ref_count_ = 0;
static_assert(std::is_unsigned<decltype(ref_count_)>::value,
"ref_count_ must be an unsigned type.");
#if DCHECK_IS_ON()
mutable bool needs_adopt_ref_ = false;
@ -448,16 +444,6 @@ class RefCountedData
~RefCountedData() = default;
};
template <typename T>
bool operator==(const RefCountedData<T>& lhs, const RefCountedData<T>& rhs) {
return lhs.data == rhs.data;
}
template <typename T>
bool operator!=(const RefCountedData<T>& lhs, const RefCountedData<T>& rhs) {
return !(lhs == rhs);
}
} // namespace base
#endif // BASE_MEMORY_REF_COUNTED_H_

Просмотреть файл

@ -25,17 +25,10 @@ class RefCounted;
template <class, typename>
class RefCountedThreadSafe;
class SequencedTaskRunner;
class WrappedPromise;
template <typename T>
scoped_refptr<T> AdoptRef(T* t);
namespace internal {
class BasePromise;
} // namespace internal
namespace subtle {
enum AdoptRefTag { kAdoptRefTag };
@ -178,16 +171,8 @@ class scoped_refptr {
constexpr scoped_refptr() = default;
// Allow implicit construction from nullptr.
constexpr scoped_refptr(std::nullptr_t) {}
// Constructs from a raw pointer. Note that this constructor allows implicit
// conversion from T* to scoped_refptr<T> which is strongly discouraged. If
// you are creating a new ref-counted object please use
// base::MakeRefCounted<T>() or base::WrapRefCounted<T>(). Otherwise you
// should move or copy construct from an existing scoped_refptr<T> to the
// ref-counted object.
scoped_refptr(T* p) : ptr_(p) {
// Constructs from raw pointer. constexpr if |p| is null.
constexpr scoped_refptr(T* p) : ptr_(p) {
if (ptr_)
AddRef(ptr_);
}
@ -236,11 +221,6 @@ class scoped_refptr {
return ptr_;
}
scoped_refptr& operator=(std::nullptr_t) {
reset();
return *this;
}
scoped_refptr& operator=(T* p) { return *this = scoped_refptr(p); }
// Unified assignment operator.
@ -280,11 +260,6 @@ class scoped_refptr {
friend scoped_refptr<U> base::AdoptRef(U*);
friend class ::base::SequencedTaskRunner;
// Friend access so these classes can use the constructor below as part of a
// binary size optimization.
friend class ::base::internal::BasePromise;
friend class ::base::WrappedPromise;
// Returns the owned pointer (if any), releasing ownership to the caller. The
// caller is responsible for managing the lifetime of the reference.
T* release();

Просмотреть файл

@ -0,0 +1,245 @@
// 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_MEMORY_SHARED_MEMORY_H_
#define BASE_MEMORY_SHARED_MEMORY_H_
#include <stddef.h>
#include <string>
#include "base/base_export.h"
#include "base/hash.h"
#include "base/macros.h"
#include "base/memory/shared_memory_handle.h"
#include "base/process/process_handle.h"
#include "base/strings/string16.h"
#include "build/build_config.h"
#if defined(OS_POSIX) || defined(OS_FUCHSIA)
#include <stdio.h>
#include <sys/types.h>
#include <semaphore.h>
#include "base/file_descriptor_posix.h"
#include "base/files/file_util.h"
#include "base/files/scoped_file.h"
#endif
#if defined(OS_WIN)
#include "base/win/scoped_handle.h"
#endif
namespace base {
class FilePath;
// Options for creating a shared memory object.
struct BASE_EXPORT SharedMemoryCreateOptions {
#if !defined(OS_FUCHSIA)
// DEPRECATED (crbug.com/345734):
// If NULL, the object is anonymous. This pointer is owned by the caller
// and must live through the call to Create().
const std::string* name_deprecated = nullptr;
// DEPRECATED (crbug.com/345734):
// If true, and the shared memory already exists, Create() will open the
// existing shared memory and ignore the size parameter. If false,
// shared memory must not exist. This flag is meaningless unless
// name_deprecated is non-NULL.
bool open_existing_deprecated = false;
#endif
// Size of the shared memory object to be created.
// When opening an existing object, this has no effect.
size_t size = 0;
// If true, mappings might need to be made executable later.
bool executable = false;
// If true, the file can be shared read-only to a process.
bool share_read_only = false;
};
// Platform abstraction for shared memory.
// SharedMemory consumes a SharedMemoryHandle [potentially one that it created]
// to map a shared memory OS resource into the virtual address space of the
// current process.
class BASE_EXPORT SharedMemory {
public:
SharedMemory();
#if defined(OS_WIN)
// Similar to the default constructor, except that this allows for
// calling LockDeprecated() to acquire the named mutex before either Create or
// Open are called on Windows.
explicit SharedMemory(const string16& name);
#endif
// Create a new SharedMemory object from an existing, open
// shared memory file.
//
// WARNING: This does not reduce the OS-level permissions on the handle; it
// only affects how the SharedMemory will be mmapped. Use
// GetReadOnlyHandle to drop permissions. TODO(jln,jyasskin): DCHECK
// that |read_only| matches the permissions of the handle.
SharedMemory(const SharedMemoryHandle& handle, bool read_only);
// Closes any open files.
~SharedMemory();
// Return true iff the given handle is valid (i.e. not the distingished
// invalid value; NULL for a HANDLE and -1 for a file descriptor)
static bool IsHandleValid(const SharedMemoryHandle& handle);
// Closes a shared memory handle.
static void CloseHandle(const SharedMemoryHandle& handle);
// Returns the maximum number of handles that can be open at once per process.
static size_t GetHandleLimit();
// Duplicates The underlying OS primitive. Returns an invalid handle on
// failure. The caller is responsible for destroying the duplicated OS
// primitive.
static SharedMemoryHandle DuplicateHandle(const SharedMemoryHandle& handle);
#if defined(OS_POSIX) && !(defined(OS_MACOSX) && !defined(OS_IOS))
// This method requires that the SharedMemoryHandle is backed by a POSIX fd.
static int GetFdFromSharedMemoryHandle(const SharedMemoryHandle& handle);
#endif
// Creates a shared memory object as described by the options struct.
// Returns true on success and false on failure.
bool Create(const SharedMemoryCreateOptions& options);
// Creates and maps an anonymous shared memory segment of size size.
// Returns true on success and false on failure.
bool CreateAndMapAnonymous(size_t size);
// Creates an anonymous shared memory segment of size size.
// Returns true on success and false on failure.
bool CreateAnonymous(size_t size) {
SharedMemoryCreateOptions options;
options.size = size;
return Create(options);
}
#if (!defined(OS_MACOSX) || defined(OS_IOS)) && !defined(OS_FUCHSIA)
// DEPRECATED (crbug.com/345734):
// Creates or opens a shared memory segment based on a name.
// If open_existing is true, and the shared memory already exists,
// opens the existing shared memory and ignores the size parameter.
// If open_existing is false, shared memory must not exist.
// size is the size of the block to be created.
// Returns true on success, false on failure.
bool CreateNamedDeprecated(
const std::string& name, bool open_existing, size_t size) {
SharedMemoryCreateOptions options;
options.name_deprecated = &name;
options.open_existing_deprecated = open_existing;
options.size = size;
return Create(options);
}
// Deletes resources associated with a shared memory segment based on name.
// Not all platforms require this call.
bool Delete(const std::string& name);
// Opens a shared memory segment based on a name.
// If read_only is true, opens for read-only access.
// Returns true on success, false on failure.
bool Open(const std::string& name, bool read_only);
#endif // !defined(OS_MACOSX) || defined(OS_IOS)
// Maps the shared memory into the caller's address space.
// Returns true on success, false otherwise. The memory address
// is accessed via the memory() accessor. The mapped address is guaranteed to
// have an alignment of at least MAP_MINIMUM_ALIGNMENT. This method will fail
// if this object is currently mapped.
bool Map(size_t bytes) {
return MapAt(0, bytes);
}
// Same as above, but with |offset| to specify from begining of the shared
// memory block to map.
// |offset| must be alignent to value of |SysInfo::VMAllocationGranularity()|.
bool MapAt(off_t offset, size_t bytes);
enum { MAP_MINIMUM_ALIGNMENT = 32 };
// Unmaps the shared memory from the caller's address space.
// Returns true if successful; returns false on error or if the
// memory is not mapped.
bool Unmap();
// The size requested when the map is first created.
size_t requested_size() const { return requested_size_; }
// The actual size of the mapped memory (may be larger than requested).
size_t mapped_size() const { return mapped_size_; }
// Gets a pointer to the opened memory space if it has been
// Mapped via Map(). Returns NULL if it is not mapped.
void* memory() const { return memory_; }
// Returns the underlying OS handle for this segment.
// Use of this handle for anything other than an opaque
// identifier is not portable.
SharedMemoryHandle handle() const;
// Returns the underlying OS handle for this segment. The caller takes
// ownership of the handle and memory is unmapped. This is equivalent to
// duplicating the handle and then calling Unmap() and Close() on this object,
// without the overhead of duplicating the handle.
SharedMemoryHandle TakeHandle();
// Closes the open shared memory segment. The memory will remain mapped if
// it was previously mapped.
// It is safe to call Close repeatedly.
void Close();
// Returns a read-only handle to this shared memory region. The caller takes
// ownership of the handle. For POSIX handles, CHECK-fails if the region
// wasn't Created or Opened with share_read_only=true, which is required to
// make the handle read-only. When the handle is passed to the IPC subsystem,
// that takes ownership of the handle. As such, it's not valid to pass the
// sample handle to the IPC subsystem twice. Returns an invalid handle on
// failure.
SharedMemoryHandle GetReadOnlyHandle() const;
// Returns an ID for the mapped region. This is ID of the SharedMemoryHandle
// that was mapped. The ID is valid even after the SharedMemoryHandle is
// Closed, as long as the region is not unmapped.
const UnguessableToken& mapped_id() const { return mapped_id_; }
private:
#if defined(OS_POSIX) && !defined(OS_NACL) && !defined(OS_ANDROID) && \
(!defined(OS_MACOSX) || defined(OS_IOS))
bool FilePathForMemoryName(const std::string& mem_name, FilePath* path);
#endif
#if defined(OS_WIN)
// If true indicates this came from an external source so needs extra checks
// before being mapped.
bool external_section_ = false;
string16 name_;
#elif !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
// If valid, points to the same memory region as shm_, but with readonly
// permissions.
SharedMemoryHandle readonly_shm_;
#endif
// The OS primitive that backs the shared memory region.
SharedMemoryHandle shm_;
size_t mapped_size_ = 0;
void* memory_ = nullptr;
bool read_only_ = false;
size_t requested_size_ = 0;
base::UnguessableToken mapped_id_;
DISALLOW_COPY_AND_ASSIGN(SharedMemory);
};
} // namespace base
#endif // BASE_MEMORY_SHARED_MEMORY_H_

Просмотреть файл

@ -0,0 +1,23 @@
// Copyright 2017 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/memory/shared_memory_handle.h"
namespace base {
SharedMemoryHandle::SharedMemoryHandle(const SharedMemoryHandle& handle) =
default;
SharedMemoryHandle& SharedMemoryHandle::operator=(
const SharedMemoryHandle& handle) = default;
base::UnguessableToken SharedMemoryHandle::GetGUID() const {
return guid_;
}
size_t SharedMemoryHandle::GetSize() const {
return size_;
}
} // namespace base

Просмотреть файл

@ -0,0 +1,220 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_MEMORY_SHARED_MEMORY_HANDLE_H_
#define BASE_MEMORY_SHARED_MEMORY_HANDLE_H_
#include <stddef.h>
#include "base/unguessable_token.h"
#include "build/build_config.h"
#if defined(OS_WIN)
#include "base/process/process_handle.h"
#include "base/win/windows_types.h"
#elif defined(OS_MACOSX) && !defined(OS_IOS)
#include <mach/mach.h>
#include "base/base_export.h"
#include "base/macros.h"
#include "base/process/process_handle.h"
#elif defined(OS_POSIX)
#include <sys/types.h>
#include "base/file_descriptor_posix.h"
#elif defined(OS_FUCHSIA)
#include <zircon/types.h>
#endif
namespace base {
// SharedMemoryHandle is the smallest possible IPC-transportable "reference" to
// a shared memory OS resource. A "reference" can be consumed exactly once [by
// base::SharedMemory] to map the shared memory OS resource into the virtual
// address space of the current process.
// TODO(erikchen): This class should have strong ownership semantics to prevent
// leaks of the underlying OS resource. https://crbug.com/640840.
class BASE_EXPORT SharedMemoryHandle {
public:
// The default constructor returns an invalid SharedMemoryHandle.
SharedMemoryHandle();
// Standard copy constructor. The new instance shares the underlying OS
// primitives.
SharedMemoryHandle(const SharedMemoryHandle& handle);
// Standard assignment operator. The updated instance shares the underlying
// OS primitives.
SharedMemoryHandle& operator=(const SharedMemoryHandle& handle);
// Closes the underlying OS resource.
// The fact that this method needs to be "const" is an artifact of the
// original interface for base::SharedMemory::CloseHandle.
// TODO(erikchen): This doesn't clear the underlying reference, which seems
// like a bug, but is how this class has always worked. Fix this:
// https://crbug.com/716072.
void Close() const;
// Whether ownership of the underlying OS resource is implicitly passed to
// the IPC subsystem during serialization.
void SetOwnershipPassesToIPC(bool ownership_passes);
bool OwnershipPassesToIPC() const;
// Whether the underlying OS resource is valid.
bool IsValid() const;
// Duplicates the underlying OS resource. Using the return value as a
// parameter to an IPC message will cause the IPC subsystem to consume the OS
// resource.
SharedMemoryHandle Duplicate() const;
// Uniques identifies the shared memory region that the underlying OS resource
// points to. Multiple SharedMemoryHandles that point to the same shared
// memory region will have the same GUID. Preserved across IPC.
base::UnguessableToken GetGUID() const;
// Returns the size of the memory region that SharedMemoryHandle points to.
size_t GetSize() const;
#if defined(OS_WIN)
// Takes implicit ownership of |h|.
// |guid| uniquely identifies the shared memory region pointed to by the
// underlying OS resource. If the HANDLE is associated with another
// SharedMemoryHandle, the caller must pass the |guid| of that
// SharedMemoryHandle. Otherwise, the caller should generate a new
// UnguessableToken.
// Passing the wrong |size| has no immediate consequence, but may cause errors
// when trying to map the SharedMemoryHandle at a later point in time.
SharedMemoryHandle(HANDLE h, size_t size, const base::UnguessableToken& guid);
HANDLE GetHandle() const;
#elif defined(OS_FUCHSIA)
// Takes implicit ownership of |h|.
// |guid| uniquely identifies the shared memory region pointed to by the
// underlying OS resource. If the zx_handle_t is associated with another
// SharedMemoryHandle, the caller must pass the |guid| of that
// SharedMemoryHandle. Otherwise, the caller should generate a new
// UnguessableToken.
// Passing the wrong |size| has no immediate consequence, but may cause errors
// when trying to map the SharedMemoryHandle at a later point in time.
SharedMemoryHandle(zx_handle_t h,
size_t size,
const base::UnguessableToken& guid);
zx_handle_t GetHandle() const;
#elif defined(OS_MACOSX) && !defined(OS_IOS)
// Makes a Mach-based SharedMemoryHandle of the given size. On error,
// subsequent calls to IsValid() return false.
// Passing the wrong |size| has no immediate consequence, but may cause errors
// when trying to map the SharedMemoryHandle at a later point in time.
SharedMemoryHandle(mach_vm_size_t size, const base::UnguessableToken& guid);
// Makes a Mach-based SharedMemoryHandle from |memory_object|, a named entry
// in the current task. The memory region has size |size|.
// Passing the wrong |size| has no immediate consequence, but may cause errors
// when trying to map the SharedMemoryHandle at a later point in time.
SharedMemoryHandle(mach_port_t memory_object,
mach_vm_size_t size,
const base::UnguessableToken& guid);
// Exposed so that the SharedMemoryHandle can be transported between
// processes.
mach_port_t GetMemoryObject() const;
// The SharedMemoryHandle must be valid.
// Returns whether the SharedMemoryHandle was successfully mapped into memory.
// On success, |memory| is an output variable that contains the start of the
// mapped memory.
bool MapAt(off_t offset, size_t bytes, void** memory, bool read_only);
#elif defined(OS_POSIX)
// Creates a SharedMemoryHandle from an |fd| supplied from an external
// service.
// Passing the wrong |size| has no immediate consequence, but may cause errors
// when trying to map the SharedMemoryHandle at a later point in time.
static SharedMemoryHandle ImportHandle(int fd, size_t size);
// Returns the underlying OS resource.
int GetHandle() const;
// Invalidates [but doesn't close] the underlying OS resource. This will leak
// unless the caller is careful.
int Release();
#endif
#if defined(OS_ANDROID)
// Marks the current file descriptor as read-only, for the purpose of
// mapping. This is independent of the region's read-only status.
void SetReadOnly() { read_only_ = true; }
// Returns true iff the descriptor is to be used for read-only
// mappings.
bool IsReadOnly() const { return read_only_; }
// Returns true iff the corresponding region is read-only.
bool IsRegionReadOnly() const;
// Try to set the region read-only. This will fail any future attempt
// at read-write mapping.
bool SetRegionReadOnly() const;
#endif
#if defined(OS_POSIX) && !(defined(OS_MACOSX) && !defined(OS_IOS))
// Constructs a SharedMemoryHandle backed by a FileDescriptor. The newly
// created instance has the same ownership semantics as base::FileDescriptor.
// This typically means that the SharedMemoryHandle takes ownership of the
// |fd| if |auto_close| is true. Unfortunately, it's common for existing code
// to make shallow copies of SharedMemoryHandle, and the one that is finally
// passed into a base::SharedMemory is the one that "consumes" the fd.
//
// |guid| uniquely identifies the shared memory region pointed to by the
// underlying OS resource. If |file_descriptor| is associated with another
// SharedMemoryHandle, the caller must pass the |guid| of that
// SharedMemoryHandle. Otherwise, the caller should generate a new
// UnguessableToken.
// Passing the wrong |size| has no immediate consequence, but may cause errors
// when trying to map the SharedMemoryHandle at a later point in time.
SharedMemoryHandle(const base::FileDescriptor& file_descriptor,
size_t size,
const base::UnguessableToken& guid);
#endif
private:
#if defined(OS_WIN)
HANDLE handle_ = nullptr;
// Whether passing this object as a parameter to an IPC message passes
// ownership of |handle_| to the IPC stack. This is meant to mimic the
// behavior of the |auto_close| parameter of FileDescriptor. This member only
// affects attachment-brokered SharedMemoryHandles.
// Defaults to |false|.
bool ownership_passes_to_ipc_ = false;
#elif defined(OS_FUCHSIA)
zx_handle_t handle_ = ZX_HANDLE_INVALID;
bool ownership_passes_to_ipc_ = false;
#elif defined(OS_MACOSX) && !defined(OS_IOS)
friend class SharedMemory;
friend bool CheckReadOnlySharedMemoryHandleForTesting(
SharedMemoryHandle handle);
mach_port_t memory_object_ = MACH_PORT_NULL;
// Whether passing this object as a parameter to an IPC message passes
// ownership of |memory_object_| to the IPC stack. This is meant to mimic
// the behavior of the |auto_close| parameter of FileDescriptor.
// Defaults to |false|.
bool ownership_passes_to_ipc_ = false;
#elif defined(OS_ANDROID)
friend class SharedMemory;
FileDescriptor file_descriptor_;
bool read_only_ = false;
#elif defined(OS_POSIX)
FileDescriptor file_descriptor_;
#endif
base::UnguessableToken guid_;
// The size of the region referenced by the SharedMemoryHandle.
size_t size_ = 0;
};
} // namespace base
#endif // BASE_MEMORY_SHARED_MEMORY_HANDLE_H_

Просмотреть файл

@ -0,0 +1,55 @@
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/memory/shared_memory_handle.h"
#include "base/logging.h"
#include "base/unguessable_token.h"
#include <windows.h>
namespace base {
SharedMemoryHandle::SharedMemoryHandle() {}
SharedMemoryHandle::SharedMemoryHandle(HANDLE h,
size_t size,
const base::UnguessableToken& guid)
: handle_(h), guid_(guid), size_(size) {}
void SharedMemoryHandle::Close() const {
DCHECK(handle_ != nullptr);
::CloseHandle(handle_);
}
bool SharedMemoryHandle::IsValid() const {
return handle_ != nullptr;
}
SharedMemoryHandle SharedMemoryHandle::Duplicate() const {
HANDLE duped_handle;
ProcessHandle process = GetCurrentProcess();
BOOL success = ::DuplicateHandle(process, handle_, process, &duped_handle, 0,
FALSE, DUPLICATE_SAME_ACCESS);
if (!success)
return SharedMemoryHandle();
base::SharedMemoryHandle handle(duped_handle, GetSize(), GetGUID());
handle.SetOwnershipPassesToIPC(true);
return handle;
}
HANDLE SharedMemoryHandle::GetHandle() const {
return handle_;
}
void SharedMemoryHandle::SetOwnershipPassesToIPC(bool ownership_passes) {
ownership_passes_to_ipc_ = ownership_passes;
}
bool SharedMemoryHandle::OwnershipPassesToIPC() const {
return ownership_passes_to_ipc_;
}
} // namespace base

Просмотреть файл

@ -1,115 +0,0 @@
// 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/memory/shared_memory_mapping.h"
#include <utility>
#include "base/logging.h"
#include "base/memory/shared_memory_tracker.h"
#include "base/unguessable_token.h"
#include "build/build_config.h"
#if defined(OS_POSIX)
#include <sys/mman.h>
#endif
#if defined(OS_WIN)
#include <aclapi.h>
#endif
#if defined(OS_MACOSX) && !defined(OS_IOS)
#include <mach/mach_vm.h>
#include "base/mac/mach_logging.h"
#endif
#if defined(OS_FUCHSIA)
#include <lib/zx/vmar.h>
#include "base/fuchsia/fuchsia_logging.h"
#endif
namespace base {
SharedMemoryMapping::SharedMemoryMapping() = default;
SharedMemoryMapping::SharedMemoryMapping(SharedMemoryMapping&& mapping) noexcept
: memory_(mapping.memory_),
size_(mapping.size_),
mapped_size_(mapping.mapped_size_),
guid_(mapping.guid_) {
mapping.memory_ = nullptr;
}
SharedMemoryMapping& SharedMemoryMapping::operator=(
SharedMemoryMapping&& mapping) noexcept {
Unmap();
memory_ = mapping.memory_;
size_ = mapping.size_;
mapped_size_ = mapping.mapped_size_;
guid_ = mapping.guid_;
mapping.memory_ = nullptr;
return *this;
}
SharedMemoryMapping::~SharedMemoryMapping() {
Unmap();
}
SharedMemoryMapping::SharedMemoryMapping(void* memory,
size_t size,
size_t mapped_size,
const UnguessableToken& guid)
: memory_(memory), size_(size), mapped_size_(mapped_size), guid_(guid) {
SharedMemoryTracker::GetInstance()->IncrementMemoryUsage(*this);
}
void SharedMemoryMapping::Unmap() {
if (!IsValid())
return;
SharedMemoryTracker::GetInstance()->DecrementMemoryUsage(*this);
#if defined(OS_WIN)
if (!UnmapViewOfFile(memory_))
DPLOG(ERROR) << "UnmapViewOfFile";
#elif defined(OS_FUCHSIA)
uintptr_t addr = reinterpret_cast<uintptr_t>(memory_);
zx_status_t status = zx::vmar::root_self()->unmap(addr, mapped_size_);
if (status != ZX_OK)
ZX_DLOG(ERROR, status) << "zx_vmar_unmap";
#elif defined(OS_MACOSX) && !defined(OS_IOS)
kern_return_t kr = mach_vm_deallocate(
mach_task_self(), reinterpret_cast<mach_vm_address_t>(memory_),
mapped_size_);
MACH_DLOG_IF(ERROR, kr != KERN_SUCCESS, kr) << "mach_vm_deallocate";
#else
if (munmap(memory_, mapped_size_) < 0)
DPLOG(ERROR) << "munmap";
#endif
}
ReadOnlySharedMemoryMapping::ReadOnlySharedMemoryMapping() = default;
ReadOnlySharedMemoryMapping::ReadOnlySharedMemoryMapping(
ReadOnlySharedMemoryMapping&&) noexcept = default;
ReadOnlySharedMemoryMapping& ReadOnlySharedMemoryMapping::operator=(
ReadOnlySharedMemoryMapping&&) noexcept = default;
ReadOnlySharedMemoryMapping::ReadOnlySharedMemoryMapping(
void* address,
size_t size,
size_t mapped_size,
const UnguessableToken& guid)
: SharedMemoryMapping(address, size, mapped_size, guid) {}
WritableSharedMemoryMapping::WritableSharedMemoryMapping() = default;
WritableSharedMemoryMapping::WritableSharedMemoryMapping(
WritableSharedMemoryMapping&&) noexcept = default;
WritableSharedMemoryMapping& WritableSharedMemoryMapping::operator=(
WritableSharedMemoryMapping&&) noexcept = default;
WritableSharedMemoryMapping::WritableSharedMemoryMapping(
void* address,
size_t size,
size_t mapped_size,
const UnguessableToken& guid)
: SharedMemoryMapping(address, size, mapped_size, guid) {}
} // namespace base

Просмотреть файл

@ -1,252 +0,0 @@
// 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_MEMORY_SHARED_MEMORY_MAPPING_H_
#define BASE_MEMORY_SHARED_MEMORY_MAPPING_H_
#include <cstddef>
#include <type_traits>
#include "base/containers/buffer_iterator.h"
#include "base/containers/span.h"
#include "base/macros.h"
#include "base/unguessable_token.h"
namespace base {
namespace subtle {
class PlatformSharedMemoryRegion;
} // namespace subtle
// Base class for scoped handles to a shared memory mapping created from a
// shared memory region. Created shared memory mappings remain valid even if the
// creator region is transferred or destroyed.
//
// Each mapping has an UnguessableToken that identifies the shared memory region
// it was created from. This is used for memory metrics, to avoid overcounting
// shared memory.
class BASE_EXPORT SharedMemoryMapping {
public:
// Default constructor initializes an invalid instance.
SharedMemoryMapping();
// Move operations are allowed.
SharedMemoryMapping(SharedMemoryMapping&& mapping) noexcept;
SharedMemoryMapping& operator=(SharedMemoryMapping&& mapping) noexcept;
// Unmaps the region if the mapping is valid.
virtual ~SharedMemoryMapping();
// Returns true iff the mapping is valid. False means there is no
// corresponding area of memory.
bool IsValid() const { return memory_ != nullptr; }
// Returns the logical size of the mapping in bytes. This is precisely the
// size requested by whoever created the mapping, and it is always less than
// or equal to |mapped_size()|. This is undefined for invalid instances.
size_t size() const {
DCHECK(IsValid());
return size_;
}
// Returns the actual size of the mapping in bytes. This is always at least
// as large as |size()| but may be larger due to platform mapping alignment
// constraints. This is undefined for invalid instances.
size_t mapped_size() const {
DCHECK(IsValid());
return mapped_size_;
}
// Returns 128-bit GUID of the region this mapping belongs to.
const UnguessableToken& guid() const {
DCHECK(IsValid());
return guid_;
}
protected:
SharedMemoryMapping(void* address,
size_t size,
size_t mapped_size,
const UnguessableToken& guid);
void* raw_memory_ptr() const { return memory_; }
private:
friend class SharedMemoryTracker;
void Unmap();
void* memory_ = nullptr;
size_t size_ = 0;
size_t mapped_size_ = 0;
UnguessableToken guid_;
DISALLOW_COPY_AND_ASSIGN(SharedMemoryMapping);
};
// Class modeling a read-only mapping of a shared memory region into the
// current process' address space. This is created by ReadOnlySharedMemoryRegion
// instances.
class BASE_EXPORT ReadOnlySharedMemoryMapping : public SharedMemoryMapping {
public:
// Default constructor initializes an invalid instance.
ReadOnlySharedMemoryMapping();
// Move operations are allowed.
ReadOnlySharedMemoryMapping(ReadOnlySharedMemoryMapping&&) noexcept;
ReadOnlySharedMemoryMapping& operator=(
ReadOnlySharedMemoryMapping&&) noexcept;
// Returns the base address of the mapping. This is read-only memory. This is
// page-aligned. This is nullptr for invalid instances.
const void* memory() const { return raw_memory_ptr(); }
// Returns a pointer to a page-aligned const T if the mapping is valid and
// large enough to contain a T, or nullptr otherwise.
template <typename T>
const T* GetMemoryAs() const {
static_assert(std::is_trivially_copyable<T>::value,
"Copying non-trivially-copyable object across memory spaces "
"is dangerous");
if (!IsValid())
return nullptr;
if (sizeof(T) > size())
return nullptr;
return static_cast<const T*>(raw_memory_ptr());
}
// Returns a span of const T. The number of elements is autodeduced from the
// size of the shared memory mapping. The number of elements may be
// autodeduced as zero, i.e. the mapping is invalid or the size of the mapping
// isn't large enough to contain even one T: in that case, an empty span
// will be returned. The first element, if any, is guaranteed to be
// page-aligned.
template <typename T>
span<const T> GetMemoryAsSpan() const {
static_assert(std::is_trivially_copyable<T>::value,
"Copying non-trivially-copyable object across memory spaces "
"is dangerous");
if (!IsValid())
return span<const T>();
size_t count = size() / sizeof(T);
return GetMemoryAsSpan<T>(count);
}
// Returns a span of const T with |count| elements if the mapping is valid and
// large enough to contain |count| elements, or an empty span otherwise. The
// first element, if any, is guaranteed to be page-aligned.
template <typename T>
span<const T> GetMemoryAsSpan(size_t count) const {
static_assert(std::is_trivially_copyable<T>::value,
"Copying non-trivially-copyable object across memory spaces "
"is dangerous");
if (!IsValid())
return span<const T>();
if (size() / sizeof(T) < count)
return span<const T>();
return span<const T>(static_cast<const T*>(raw_memory_ptr()), count);
}
// Returns a BufferIterator of const T.
template <typename T>
BufferIterator<const T> GetMemoryAsBufferIterator() const {
return BufferIterator<const T>(GetMemoryAsSpan<T>());
}
private:
friend class ReadOnlySharedMemoryRegion;
ReadOnlySharedMemoryMapping(void* address,
size_t size,
size_t mapped_size,
const UnguessableToken& guid);
DISALLOW_COPY_AND_ASSIGN(ReadOnlySharedMemoryMapping);
};
// Class modeling a writable mapping of a shared memory region into the
// current process' address space. This is created by *SharedMemoryRegion
// instances.
class BASE_EXPORT WritableSharedMemoryMapping : public SharedMemoryMapping {
public:
// Default constructor initializes an invalid instance.
WritableSharedMemoryMapping();
// Move operations are allowed.
WritableSharedMemoryMapping(WritableSharedMemoryMapping&&) noexcept;
WritableSharedMemoryMapping& operator=(
WritableSharedMemoryMapping&&) noexcept;
// Returns the base address of the mapping. This is writable memory. This is
// page-aligned. This is nullptr for invalid instances.
void* memory() const { return raw_memory_ptr(); }
// Returns a pointer to a page-aligned T if the mapping is valid and large
// enough to contain a T, or nullptr otherwise.
template <typename T>
T* GetMemoryAs() const {
static_assert(std::is_trivially_copyable<T>::value,
"Copying non-trivially-copyable object across memory spaces "
"is dangerous");
if (!IsValid())
return nullptr;
if (sizeof(T) > size())
return nullptr;
return static_cast<T*>(raw_memory_ptr());
}
// Returns a span of T. The number of elements is autodeduced from the size of
// the shared memory mapping. The number of elements may be autodeduced as
// zero, i.e. the mapping is invalid or the size of the mapping isn't large
// enough to contain even one T: in that case, an empty span will be returned.
// The first element, if any, is guaranteed to be page-aligned.
template <typename T>
span<T> GetMemoryAsSpan() const {
static_assert(std::is_trivially_copyable<T>::value,
"Copying non-trivially-copyable object across memory spaces "
"is dangerous");
if (!IsValid())
return span<T>();
size_t count = size() / sizeof(T);
return GetMemoryAsSpan<T>(count);
}
// Returns a span of T with |count| elements if the mapping is valid and large
// enough to contain |count| elements, or an empty span otherwise. The first
// element, if any, is guaranteed to be page-aligned.
template <typename T>
span<T> GetMemoryAsSpan(size_t count) const {
static_assert(std::is_trivially_copyable<T>::value,
"Copying non-trivially-copyable object across memory spaces "
"is dangerous");
if (!IsValid())
return span<T>();
if (size() / sizeof(T) < count)
return span<T>();
return span<T>(static_cast<T*>(raw_memory_ptr()), count);
}
// Returns a BufferIterator of T.
template <typename T>
BufferIterator<T> GetMemoryAsBufferIterator() {
return BufferIterator<T>(GetMemoryAsSpan<T>());
}
private:
friend WritableSharedMemoryMapping MapAtForTesting(
subtle::PlatformSharedMemoryRegion* region,
off_t offset,
size_t size);
friend class ReadOnlySharedMemoryRegion;
friend class WritableSharedMemoryRegion;
friend class UnsafeSharedMemoryRegion;
WritableSharedMemoryMapping(void* address,
size_t size,
size_t mapped_size,
const UnguessableToken& guid);
DISALLOW_COPY_AND_ASSIGN(WritableSharedMemoryMapping);
};
} // namespace base
#endif // BASE_MEMORY_SHARED_MEMORY_MAPPING_H_

Просмотреть файл

@ -0,0 +1,388 @@
// Copyright (c) 2011 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/memory/shared_memory.h"
#include <aclapi.h>
#include <stddef.h>
#include <stdint.h>
#include "base/allocator/partition_allocator/page_allocator.h"
#include "base/logging.h"
#include "base/memory/shared_memory_tracker.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/rand_util.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/unguessable_token.h"
#include "base/win/windows_version.h"
namespace base {
namespace {
// Errors that can occur during Shared Memory construction.
// These match tools/metrics/histograms/histograms.xml.
// This enum is append-only.
enum CreateError {
SUCCESS = 0,
SIZE_ZERO = 1,
SIZE_TOO_LARGE = 2,
INITIALIZE_ACL_FAILURE = 3,
INITIALIZE_SECURITY_DESC_FAILURE = 4,
SET_SECURITY_DESC_FAILURE = 5,
CREATE_FILE_MAPPING_FAILURE = 6,
REDUCE_PERMISSIONS_FAILURE = 7,
ALREADY_EXISTS = 8,
CREATE_ERROR_LAST = ALREADY_EXISTS
};
// Emits UMA metrics about encountered errors. Pass zero (0) for |winerror|
// if there is no associated Windows error.
void LogError(CreateError error, DWORD winerror) {
UMA_HISTOGRAM_ENUMERATION("SharedMemory.CreateError", error,
CREATE_ERROR_LAST + 1);
static_assert(ERROR_SUCCESS == 0, "Windows error code changed!");
if (winerror != ERROR_SUCCESS)
UmaHistogramSparse("SharedMemory.CreateWinError", winerror);
}
typedef enum _SECTION_INFORMATION_CLASS {
SectionBasicInformation,
} SECTION_INFORMATION_CLASS;
typedef struct _SECTION_BASIC_INFORMATION {
PVOID BaseAddress;
ULONG Attributes;
LARGE_INTEGER Size;
} SECTION_BASIC_INFORMATION, *PSECTION_BASIC_INFORMATION;
typedef ULONG(__stdcall* NtQuerySectionType)(
HANDLE SectionHandle,
SECTION_INFORMATION_CLASS SectionInformationClass,
PVOID SectionInformation,
ULONG SectionInformationLength,
PULONG ResultLength);
// Returns the length of the memory section starting at the supplied address.
size_t GetMemorySectionSize(void* address) {
MEMORY_BASIC_INFORMATION memory_info;
if (!::VirtualQuery(address, &memory_info, sizeof(memory_info)))
return 0;
return memory_info.RegionSize - (static_cast<char*>(address) -
static_cast<char*>(memory_info.AllocationBase));
}
// Checks if the section object is safe to map. At the moment this just means
// it's not an image section.
bool IsSectionSafeToMap(HANDLE handle) {
static NtQuerySectionType nt_query_section_func;
if (!nt_query_section_func) {
nt_query_section_func = reinterpret_cast<NtQuerySectionType>(
::GetProcAddress(::GetModuleHandle(L"ntdll.dll"), "NtQuerySection"));
DCHECK(nt_query_section_func);
}
// The handle must have SECTION_QUERY access for this to succeed.
SECTION_BASIC_INFORMATION basic_information = {};
ULONG status =
nt_query_section_func(handle, SectionBasicInformation, &basic_information,
sizeof(basic_information), nullptr);
if (status)
return false;
return (basic_information.Attributes & SEC_IMAGE) != SEC_IMAGE;
}
// Returns a HANDLE on success and |nullptr| on failure.
// This function is similar to CreateFileMapping, but removes the permissions
// WRITE_DAC, WRITE_OWNER, READ_CONTROL, and DELETE.
//
// A newly created file mapping has two sets of permissions. It has access
// control permissions (WRITE_DAC, WRITE_OWNER, READ_CONTROL, and DELETE) and
// file permissions (FILE_MAP_READ, FILE_MAP_WRITE, etc.). ::DuplicateHandle()
// with the parameter DUPLICATE_SAME_ACCESS copies both sets of permissions.
//
// The Chrome sandbox prevents HANDLEs with the WRITE_DAC permission from being
// duplicated into unprivileged processes. But the only way to copy file
// permissions is with the parameter DUPLICATE_SAME_ACCESS. This means that
// there is no way for a privileged process to duplicate a file mapping into an
// unprivileged process while maintaining the previous file permissions.
//
// By removing all access control permissions of a file mapping immediately
// after creation, ::DuplicateHandle() effectively only copies the file
// permissions.
HANDLE CreateFileMappingWithReducedPermissions(SECURITY_ATTRIBUTES* sa,
size_t rounded_size,
LPCWSTR name) {
HANDLE h = CreateFileMapping(INVALID_HANDLE_VALUE, sa, PAGE_READWRITE, 0,
static_cast<DWORD>(rounded_size), name);
if (!h) {
LogError(CREATE_FILE_MAPPING_FAILURE, GetLastError());
return nullptr;
}
HANDLE h2;
BOOL success = ::DuplicateHandle(
GetCurrentProcess(), h, GetCurrentProcess(), &h2,
FILE_MAP_READ | FILE_MAP_WRITE | SECTION_QUERY, FALSE, 0);
BOOL rv = ::CloseHandle(h);
DCHECK(rv);
if (!success) {
LogError(REDUCE_PERMISSIONS_FAILURE, GetLastError());
return nullptr;
}
return h2;
}
} // namespace.
SharedMemory::SharedMemory() {}
SharedMemory::SharedMemory(const string16& name) : name_(name) {}
SharedMemory::SharedMemory(const SharedMemoryHandle& handle, bool read_only)
: external_section_(true), shm_(handle), read_only_(read_only) {}
SharedMemory::~SharedMemory() {
Unmap();
Close();
}
// static
bool SharedMemory::IsHandleValid(const SharedMemoryHandle& handle) {
return handle.IsValid();
}
// static
void SharedMemory::CloseHandle(const SharedMemoryHandle& handle) {
handle.Close();
}
// static
size_t SharedMemory::GetHandleLimit() {
// Rounded down from value reported here:
// http://blogs.technet.com/b/markrussinovich/archive/2009/09/29/3283844.aspx
return static_cast<size_t>(1 << 23);
}
// static
SharedMemoryHandle SharedMemory::DuplicateHandle(
const SharedMemoryHandle& handle) {
return handle.Duplicate();
}
bool SharedMemory::CreateAndMapAnonymous(size_t size) {
return CreateAnonymous(size) && Map(size);
}
bool SharedMemory::Create(const SharedMemoryCreateOptions& options) {
// TODO(crbug.com/210609): NaCl forces us to round up 64k here, wasting 32k
// per mapping on average.
static const size_t kSectionMask = 65536 - 1;
DCHECK(!options.executable);
DCHECK(!shm_.IsValid());
if (options.size == 0) {
LogError(SIZE_ZERO, 0);
return false;
}
// Check maximum accounting for overflow.
if (options.size >
static_cast<size_t>(std::numeric_limits<int>::max()) - kSectionMask) {
LogError(SIZE_TOO_LARGE, 0);
return false;
}
size_t rounded_size = (options.size + kSectionMask) & ~kSectionMask;
name_ = options.name_deprecated ? ASCIIToUTF16(*options.name_deprecated)
: string16();
SECURITY_ATTRIBUTES sa = {sizeof(sa), nullptr, FALSE};
SECURITY_DESCRIPTOR sd;
ACL dacl;
if (name_.empty()) {
// Add an empty DACL to enforce anonymous read-only sections.
sa.lpSecurityDescriptor = &sd;
if (!InitializeAcl(&dacl, sizeof(dacl), ACL_REVISION)) {
LogError(INITIALIZE_ACL_FAILURE, GetLastError());
return false;
}
if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
LogError(INITIALIZE_SECURITY_DESC_FAILURE, GetLastError());
return false;
}
if (!SetSecurityDescriptorDacl(&sd, TRUE, &dacl, FALSE)) {
LogError(SET_SECURITY_DESC_FAILURE, GetLastError());
return false;
}
if (win::GetVersion() < win::VERSION_WIN8_1) {
// Windows < 8.1 ignores DACLs on certain unnamed objects (like shared
// sections). So, we generate a random name when we need to enforce
// read-only.
uint64_t rand_values[4];
RandBytes(&rand_values, sizeof(rand_values));
name_ = ASCIIToUTF16(StringPrintf(
"CrSharedMem_%016llx%016llx%016llx%016llx", rand_values[0],
rand_values[1], rand_values[2], rand_values[3]));
DCHECK(!name_.empty());
}
}
shm_ = SharedMemoryHandle(
CreateFileMappingWithReducedPermissions(
&sa, rounded_size, name_.empty() ? nullptr : as_wcstr(name_)),
rounded_size, UnguessableToken::Create());
if (!shm_.IsValid()) {
// The error is logged within CreateFileMappingWithReducedPermissions().
return false;
}
requested_size_ = options.size;
// Check if the shared memory pre-exists.
if (GetLastError() == ERROR_ALREADY_EXISTS) {
// If the file already existed, set requested_size_ to 0 to show that
// we don't know the size.
requested_size_ = 0;
external_section_ = true;
if (!options.open_existing_deprecated) {
Close();
// From "if" above: GetLastError() == ERROR_ALREADY_EXISTS.
LogError(ALREADY_EXISTS, ERROR_ALREADY_EXISTS);
return false;
}
}
LogError(SUCCESS, ERROR_SUCCESS);
return true;
}
bool SharedMemory::Delete(const std::string& name) {
// intentionally empty -- there is nothing for us to do on Windows.
return true;
}
bool SharedMemory::Open(const std::string& name, bool read_only) {
DCHECK(!shm_.IsValid());
DWORD access = FILE_MAP_READ | SECTION_QUERY;
if (!read_only)
access |= FILE_MAP_WRITE;
name_ = ASCIIToUTF16(name);
read_only_ = read_only;
// This form of sharing shared memory is deprecated. https://crbug.com/345734.
// However, we can't get rid of it without a significant refactor because its
// used to communicate between two versions of the same service process, very
// early in the life cycle.
// Technically, we should also pass the GUID from the original shared memory
// region. We don't do that - this means that we will overcount this memory,
// which thankfully isn't relevant since Chrome only communicates with a
// single version of the service process.
// We pass the size |0|, which is a dummy size and wrong, but otherwise
// harmless.
shm_ = SharedMemoryHandle(
OpenFileMapping(access, false, name_.empty() ? nullptr : as_wcstr(name_)),
0u, UnguessableToken::Create());
if (!shm_.IsValid())
return false;
// If a name specified assume it's an external section.
if (!name_.empty())
external_section_ = true;
// Note: size_ is not set in this case.
return true;
}
bool SharedMemory::MapAt(off_t offset, size_t bytes) {
if (!shm_.IsValid()) {
DLOG(ERROR) << "Invalid SharedMemoryHandle.";
return false;
}
if (bytes > static_cast<size_t>(std::numeric_limits<int>::max())) {
DLOG(ERROR) << "Bytes required exceeds the 2G limitation.";
return false;
}
if (memory_) {
DLOG(ERROR) << "The SharedMemory has been mapped already.";
return false;
}
if (external_section_ && !IsSectionSafeToMap(shm_.GetHandle())) {
DLOG(ERROR) << "SharedMemoryHandle is not safe to be mapped.";
return false;
}
// Try to map the shared memory. On the first failure, release any reserved
// address space for a single retry.
for (int i = 0; i < 2; ++i) {
memory_ = MapViewOfFile(
shm_.GetHandle(),
read_only_ ? FILE_MAP_READ : FILE_MAP_READ | FILE_MAP_WRITE,
static_cast<uint64_t>(offset) >> 32, static_cast<DWORD>(offset), bytes);
if (memory_)
break;
ReleaseReservation();
}
if (!memory_) {
DPLOG(ERROR) << "Failed executing MapViewOfFile";
return false;
}
DCHECK_EQ(0U, reinterpret_cast<uintptr_t>(memory_) &
(SharedMemory::MAP_MINIMUM_ALIGNMENT - 1));
mapped_size_ = GetMemorySectionSize(memory_);
mapped_id_ = shm_.GetGUID();
SharedMemoryTracker::GetInstance()->IncrementMemoryUsage(*this);
return true;
}
bool SharedMemory::Unmap() {
if (!memory_)
return false;
SharedMemoryTracker::GetInstance()->DecrementMemoryUsage(*this);
UnmapViewOfFile(memory_);
memory_ = nullptr;
mapped_id_ = UnguessableToken();
return true;
}
SharedMemoryHandle SharedMemory::GetReadOnlyHandle() const {
HANDLE result;
ProcessHandle process = GetCurrentProcess();
if (!::DuplicateHandle(process, shm_.GetHandle(), process, &result,
FILE_MAP_READ | SECTION_QUERY, FALSE, 0)) {
return SharedMemoryHandle();
}
SharedMemoryHandle handle =
SharedMemoryHandle(result, shm_.GetSize(), shm_.GetGUID());
handle.SetOwnershipPassesToIPC(true);
return handle;
}
void SharedMemory::Close() {
if (shm_.IsValid()) {
shm_.Close();
shm_ = SharedMemoryHandle();
}
}
SharedMemoryHandle SharedMemory::handle() const {
return shm_;
}
SharedMemoryHandle SharedMemory::TakeHandle() {
SharedMemoryHandle handle(shm_);
handle.SetOwnershipPassesToIPC(true);
Unmap();
shm_ = SharedMemoryHandle();
return handle;
}
} // namespace base

Просмотреть файл

@ -1,80 +0,0 @@
// 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/memory/unsafe_shared_memory_region.h"
#include <utility>
namespace base {
UnsafeSharedMemoryRegion::CreateFunction*
UnsafeSharedMemoryRegion::create_hook_ = nullptr;
// static
UnsafeSharedMemoryRegion UnsafeSharedMemoryRegion::Create(size_t size) {
if (create_hook_)
return create_hook_(size);
subtle::PlatformSharedMemoryRegion handle =
subtle::PlatformSharedMemoryRegion::CreateUnsafe(size);
return UnsafeSharedMemoryRegion(std::move(handle));
}
// static
UnsafeSharedMemoryRegion UnsafeSharedMemoryRegion::Deserialize(
subtle::PlatformSharedMemoryRegion handle) {
return UnsafeSharedMemoryRegion(std::move(handle));
}
// static
subtle::PlatformSharedMemoryRegion
UnsafeSharedMemoryRegion::TakeHandleForSerialization(
UnsafeSharedMemoryRegion region) {
return std::move(region.handle_);
}
UnsafeSharedMemoryRegion::UnsafeSharedMemoryRegion() = default;
UnsafeSharedMemoryRegion::UnsafeSharedMemoryRegion(
UnsafeSharedMemoryRegion&& region) = default;
UnsafeSharedMemoryRegion& UnsafeSharedMemoryRegion::operator=(
UnsafeSharedMemoryRegion&& region) = default;
UnsafeSharedMemoryRegion::~UnsafeSharedMemoryRegion() = default;
UnsafeSharedMemoryRegion UnsafeSharedMemoryRegion::Duplicate() const {
return UnsafeSharedMemoryRegion(handle_.Duplicate());
}
WritableSharedMemoryMapping UnsafeSharedMemoryRegion::Map() const {
return MapAt(0, handle_.GetSize());
}
WritableSharedMemoryMapping UnsafeSharedMemoryRegion::MapAt(off_t offset,
size_t size) const {
if (!IsValid())
return {};
void* memory = nullptr;
size_t mapped_size = 0;
if (!handle_.MapAt(offset, size, &memory, &mapped_size))
return {};
return WritableSharedMemoryMapping(memory, size, mapped_size,
handle_.GetGUID());
}
bool UnsafeSharedMemoryRegion::IsValid() const {
return handle_.IsValid();
}
UnsafeSharedMemoryRegion::UnsafeSharedMemoryRegion(
subtle::PlatformSharedMemoryRegion handle)
: handle_(std::move(handle)) {
if (handle_.IsValid()) {
CHECK_EQ(handle_.GetMode(),
subtle::PlatformSharedMemoryRegion::Mode::kUnsafe);
}
}
} // namespace base

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше