diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /security/sandbox/chromium-shim | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'security/sandbox/chromium-shim')
90 files changed, 8172 insertions, 0 deletions
diff --git a/security/sandbox/chromium-shim/base/allocator/buildflags.h b/security/sandbox/chromium-shim/base/allocator/buildflags.h new file mode 100644 index 0000000000..1799e64067 --- /dev/null +++ b/security/sandbox/chromium-shim/base/allocator/buildflags.h @@ -0,0 +1,20 @@ +/* -*- 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/allocator:buildflags" + +#ifndef BASE_ALLOCATOR_BUILDFLAGS_H_ +#define BASE_ALLOCATOR_BUILDFLAGS_H_ + +#include "build/buildflag.h" + +#define BUILDFLAG_INTERNAL_USE_TCMALLOC() (0) + +#endif // BASE_ALLOCATOR_BUILDFLAGS_H_ diff --git a/security/sandbox/chromium-shim/base/allocator/partition_allocator/page_allocator.h b/security/sandbox/chromium-shim/base/allocator/partition_allocator/page_allocator.h new file mode 100644 index 0000000000..e3bb27d897 --- /dev/null +++ b/security/sandbox/chromium-shim/base/allocator/partition_allocator/page_allocator.h @@ -0,0 +1,21 @@ +/* -*- 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 Chromium source file +// base/allocator/partition_allocator/page_allocator.h. +// To provide to an empty ReleaseReservation function, because we never call +// ReserveAddressSpace. + +#ifndef BASE_ALLOCATOR_PARTITION_ALLOCATOR_PAGE_ALLOCATOR_H_ +#define BASE_ALLOCATOR_PARTITION_ALLOCATOR_PAGE_ALLOCATOR_H_ + +namespace base { + +BASE_EXPORT void ReleaseReservation() {} + +} // namespace base + +#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_PAGE_ALLOCATOR_H_ diff --git a/security/sandbox/chromium-shim/base/debug/activity_tracker.h b/security/sandbox/chromium-shim/base/debug/activity_tracker.h new file mode 100644 index 0000000000..b59cd12cc0 --- /dev/null +++ b/security/sandbox/chromium-shim/base/debug/activity_tracker.h @@ -0,0 +1,61 @@ +/* -*- 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 Chromium source file base/debug/activity_tracker.h. +// To provide a class required in base/synchronization/lock_impl_win.cc +// ScopedLockAcquireActivity. We don't use activity tracking. + +#ifndef BASE_DEBUG_ACTIVITY_TRACKER_H_ +#define BASE_DEBUG_ACTIVITY_TRACKER_H_ + +#include "base/base_export.h" +#include "base/compiler_specific.h" +#include "base/macros.h" + +namespace base { +class PlatformThreadHandle; +class WaitableEvent; + +namespace internal { +class LockImpl; +} + +namespace debug { + +class BASE_EXPORT GlobalActivityTracker { + public: + static bool IsEnabled() { return false; } + DISALLOW_COPY_AND_ASSIGN(GlobalActivityTracker); +}; + +class BASE_EXPORT ScopedLockAcquireActivity +{ + public: + ALWAYS_INLINE + explicit ScopedLockAcquireActivity(const base::internal::LockImpl* lock) {} + DISALLOW_COPY_AND_ASSIGN(ScopedLockAcquireActivity); +}; + +class BASE_EXPORT ScopedEventWaitActivity +{ + public: + ALWAYS_INLINE + explicit ScopedEventWaitActivity(const base::WaitableEvent* event) {} + DISALLOW_COPY_AND_ASSIGN(ScopedEventWaitActivity); +}; + +class BASE_EXPORT ScopedThreadJoinActivity +{ + public: + ALWAYS_INLINE + explicit ScopedThreadJoinActivity(const base::PlatformThreadHandle* thread) {} + DISALLOW_COPY_AND_ASSIGN(ScopedThreadJoinActivity); +}; + +} // namespace debug +} // namespace base + +#endif // BASE_DEBUG_ACTIVITY_TRACKER_H_ diff --git a/security/sandbox/chromium-shim/base/debug/crash_logging.cpp b/security/sandbox/chromium-shim/base/debug/crash_logging.cpp new file mode 100644 index 0000000000..b2c3f7afa2 --- /dev/null +++ b/security/sandbox/chromium-shim/base/debug/crash_logging.cpp @@ -0,0 +1,22 @@ +/* -*- 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 diff --git a/security/sandbox/chromium-shim/base/debug/debugging_buildflags.h b/security/sandbox/chromium-shim/base/debug/debugging_buildflags.h new file mode 100644 index 0000000000..a2b89849a5 --- /dev/null +++ b/security/sandbox/chromium-shim/base/debug/debugging_buildflags.h @@ -0,0 +1,21 @@ +/* -*- 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:debugging_buildflags" + +#ifndef BASE_DEBUG_DEBUGGING_BUILDFLAGS_H_ +#define BASE_DEBUG_DEBUGGING_BUILDFLAGS_H_ + +#include "build/buildflag.h" + +#define BUILDFLAG_INTERNAL_ENABLE_LOCATION_SOURCE() (1) +#define BUILDFLAG_INTERNAL_ENABLE_PROFILING() (0) + +#endif // BASE_DEBUG_DEBUGGING_BUILDFLAGS_H_ diff --git a/security/sandbox/chromium-shim/base/debug/stack_trace.h b/security/sandbox/chromium-shim/base/debug/stack_trace.h new file mode 100644 index 0000000000..2ab1485204 --- /dev/null +++ b/security/sandbox/chromium-shim/base/debug/stack_trace.h @@ -0,0 +1,30 @@ +/* -*- 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 Chromium source file base/debug/stack_trace.h +// to provide a dummy class StackTrace. + +#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 +} // namespace base + +#endif // BASE_DEBUG_STACK_TRACE_H_ diff --git a/security/sandbox/chromium-shim/base/feature_list.h b/security/sandbox/chromium-shim/base/feature_list.h new file mode 100644 index 0000000000..ada5c22f24 --- /dev/null +++ b/security/sandbox/chromium-shim/base/feature_list.h @@ -0,0 +1,52 @@ +/* -*- 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/feature_list.h. +// This just returns the default state for a feature. + +#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. +enum FeatureState { + FEATURE_DISABLED_BY_DEFAULT, + FEATURE_ENABLED_BY_DEFAULT, +}; + +// The Feature struct is used to define the default state for a feature. See +// comment below for more details. There must only ever be one struct instance +// for a given feature name - generally defined as a constant global variable or +// file static. It should never be used as a constexpr as it breaks +// pointer-based identity lookup. +struct BASE_EXPORT Feature { + // The name of the feature. This should be unique to each feature and is used + // for enabling/disabling features via command line flags and experiments. + // It is strongly recommended to use CamelCase style for feature names, e.g. + // "MyGreatFeature". + const char* const name; + + // The default state (i.e. enabled or disabled) for this feature. + const FeatureState default_state; +}; + +class BASE_EXPORT FeatureList { + public: + static bool IsEnabled(const Feature& feature) { + return feature.default_state == FEATURE_ENABLED_BY_DEFAULT; + } + + static FeatureList* GetInstance() { return nullptr; } + + DISALLOW_COPY_AND_ASSIGN(FeatureList); +}; + +} // namespace base + +#endif // BASE_FEATURE_LIST_H_ diff --git a/security/sandbox/chromium-shim/base/file_version_info_win.cpp b/security/sandbox/chromium-shim/base/file_version_info_win.cpp new file mode 100644 index 0000000000..bc4d6a4fe0 --- /dev/null +++ b/security/sandbox/chromium-shim/base/file_version_info_win.cpp @@ -0,0 +1,90 @@ +/* -*- 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/file_version_info_win.cc + +#include "base/file_version_info_win.h" + +#include "base/files/file_path.h" +#include "base/memory/ptr_util.h" +#include "base/threading/scoped_blocking_call.h" + +#include "mozilla/Unused.h" + +namespace { + +struct LanguageAndCodePage { + WORD language; + WORD code_page; +}; + +// Returns the \VarFileInfo\Translation value extracted from the +// VS_VERSION_INFO resource in |data|. +LanguageAndCodePage* GetTranslate(const void* data) { + static constexpr wchar_t kTranslation[] = L"\\VarFileInfo\\Translation"; + LPVOID translate = nullptr; + UINT dummy_size; + if (::VerQueryValue(data, kTranslation, &translate, &dummy_size)) + return static_cast<LanguageAndCodePage*>(translate); + return nullptr; +} + +const VS_FIXEDFILEINFO& GetVsFixedFileInfo(const void* data) { + static constexpr wchar_t kRoot[] = L"\\"; + LPVOID fixed_file_info = nullptr; + UINT dummy_size; + CHECK(::VerQueryValue(data, kRoot, &fixed_file_info, &dummy_size)); + return *static_cast<VS_FIXEDFILEINFO*>(fixed_file_info); +} + +} // namespace + +// static +std::unique_ptr<FileVersionInfoWin> +FileVersionInfoWin::CreateFileVersionInfoWin(const base::FilePath& file_path) { + base::ScopedBlockingCall scoped_blocking_call(FROM_HERE, + base::BlockingType::MAY_BLOCK); + + DWORD dummy; + const wchar_t* path = file_path.value().c_str(); + const DWORD length = ::GetFileVersionInfoSize(path, &dummy); + if (length == 0) + return nullptr; + + std::vector<uint8_t> data(length, 0); + + if (!::GetFileVersionInfo(path, dummy, length, data.data())) + return nullptr; + + const LanguageAndCodePage* translate = GetTranslate(data.data()); + if (!translate) + return nullptr; + + return base::WrapUnique(new FileVersionInfoWin( + std::move(data), translate->language, translate->code_page)); +} + +base::Version FileVersionInfoWin::GetFileVersion() const { + return base::Version({HIWORD(fixed_file_info_.dwFileVersionMS), + LOWORD(fixed_file_info_.dwFileVersionMS), + HIWORD(fixed_file_info_.dwFileVersionLS), + LOWORD(fixed_file_info_.dwFileVersionLS)}); +} + +FileVersionInfoWin::FileVersionInfoWin(std::vector<uint8_t>&& data, + WORD language, + WORD code_page) + : owned_data_(std::move(data)), + data_(owned_data_.data()), + language_(language), + code_page_(code_page), + fixed_file_info_(GetVsFixedFileInfo(data_)) { + DCHECK(!owned_data_.empty()); + + mozilla::Unused << language_; + mozilla::Unused << code_page_; +} diff --git a/security/sandbox/chromium-shim/base/file_version_info_win.h b/security/sandbox/chromium-shim/base/file_version_info_win.h new file mode 100644 index 0000000000..9f41901864 --- /dev/null +++ b/security/sandbox/chromium-shim/base/file_version_info_win.h @@ -0,0 +1,54 @@ +/* -*- 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/file_version_info_win.h. + +#ifndef BASE_FILE_VERSION_INFO_WIN_H_ +#define BASE_FILE_VERSION_INFO_WIN_H_ + +#include <memory> +#include <vector> + +#include "base/macros.h" +#include "base/version.h" + +#include "mozilla/Assertions.h" + +struct tagVS_FIXEDFILEINFO; +typedef tagVS_FIXEDFILEINFO VS_FIXEDFILEINFO; + +namespace base { +class FilePath; +} + +class FileVersionInfoWin { + public: + static std::unique_ptr<FileVersionInfoWin> CreateFileVersionInfoWin( + const base::FilePath& file_path); + + // Get file version number in dotted version format. + base::Version GetFileVersion() const; + + private: + // |data| is a VS_VERSION_INFO resource. |language| and |code_page| are + // extracted from the \VarFileInfo\Translation value of |data|. + FileVersionInfoWin(std::vector<uint8_t>&& data, + WORD language, + WORD code_page); + + const std::vector<uint8_t> owned_data_; + const void* const data_; + const WORD language_; + const WORD code_page_; + + // This is a reference for a portion of |data_|. + const VS_FIXEDFILEINFO& fixed_file_info_; + + DISALLOW_COPY_AND_ASSIGN(FileVersionInfoWin); +}; + +#endif // BASE_FILE_VERSION_INFO_WIN_H_ diff --git a/security/sandbox/chromium-shim/base/files/file_path.cpp b/security/sandbox/chromium-shim/base/files/file_path.cpp new file mode 100644 index 0000000000..bcbfecab99 --- /dev/null +++ b/security/sandbox/chromium-shim/base/files/file_path.cpp @@ -0,0 +1,217 @@ +// 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. + +// This is a partial implementation of Chromium's source file +// base/file/file_path.cc. + +#include "base/files/file_path.h" + +namespace base { + +using StringType = FilePath::StringType; +using StringPieceType = FilePath::StringPieceType; + +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; + +FilePath::FilePath(const FilePath& that) = default; +FilePath::FilePath(FilePath&& that) noexcept = default; + +FilePath::FilePath(StringPieceType path) : path_(path) { + StringType::size_type nul_pos = path_.find(kStringTerminator); + if (nul_pos != StringType::npos) + path_.erase(nul_pos, StringType::npos); +} + +FilePath::~FilePath() = default; + +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 diff --git a/security/sandbox/chromium-shim/base/files/file_util.h b/security/sandbox/chromium-shim/base/files/file_util.h new file mode 100644 index 0000000000..bd6ce0c0a8 --- /dev/null +++ b/security/sandbox/chromium-shim/base/files/file_util.h @@ -0,0 +1,11 @@ +/* -*- 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 Chromium source file base/files/file_util.h +// This is included in base/memory/shared_memory.h, but it only actually +// requires the include for base/files/file_path.h. + +#include "base/files/file_path.h" diff --git a/security/sandbox/chromium-shim/base/gtest_prod_util.h b/security/sandbox/chromium-shim/base/gtest_prod_util.h new file mode 100644 index 0000000000..b45a1586b0 --- /dev/null +++ b/security/sandbox/chromium-shim/base/gtest_prod_util.h @@ -0,0 +1,22 @@ +/* -*- 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/. */ + +#ifndef BASE_GTEST_PROD_UTIL_H_ +#define BASE_GTEST_PROD_UTIL_H_ + +#ifndef FRIEND_TEST +#define FRIEND_TEST(A, B) +#endif + +#ifndef FRIEND_TEST_ALL_PREFIXES +#define FRIEND_TEST_ALL_PREFIXES(test_case_name, test_name) +#endif + +#ifndef FORWARD_DECLARE_TEST +#define FORWARD_DECLARE_TEST(test_case_name, test_name) +#endif + +#endif // BASE_GTEST_PROD_UTIL_H_ diff --git a/security/sandbox/chromium-shim/base/logging.cpp b/security/sandbox/chromium-shim/base/logging.cpp new file mode 100644 index 0000000000..9ac163c0ea --- /dev/null +++ b/security/sandbox/chromium-shim/base/logging.cpp @@ -0,0 +1,160 @@ +/* -*- 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 stripped down version of the Chromium source file base/logging.cc +// This prevents dependency on the Chromium logging and dependency creep in +// general. +// At some point we should find a way to hook this into our own logging see +// bug 1013988. +// The formatting in this file matches the original Chromium file to aid future +// merging. + +#include "base/logging.h" + +#if defined(OS_WIN) +#include <windows.h> +#endif + +#if defined(OS_POSIX) +#include <errno.h> +#endif + +#if defined(OS_WIN) +#include "base/strings/utf_string_conversions.h" +#endif + +#include <algorithm> + +#include "mozilla/Assertions.h" +#include "mozilla/Unused.h" + +namespace logging { + +namespace { + +int g_min_log_level = 0; + +LoggingDestination g_logging_destination = LOG_DEFAULT; + +// For LOG_ERROR and above, always print to stderr. +const int kAlwaysPrintErrorLevel = LOG_ERROR; + +// A log message handler that gets notified of every log message we process. +LogMessageHandlerFunction log_message_handler = nullptr; + +} // namespace + +// This is never instantiated, it's just used for EAT_STREAM_PARAMETERS to have +// an object of the correct type on the LHS of the unused part of the ternary +// operator. +std::ostream* g_swallow_stream; + +void SetMinLogLevel(int level) { + g_min_log_level = std::min(LOG_FATAL, level); +} + +int GetMinLogLevel() { + return g_min_log_level; +} + +bool ShouldCreateLogMessage(int severity) { + if (severity < g_min_log_level) + return false; + + // Return true here unless we know ~LogMessage won't do anything. Note that + // ~LogMessage writes to stderr if severity_ >= kAlwaysPrintErrorLevel, even + // when g_logging_destination is LOG_NONE. + return g_logging_destination != LOG_NONE || log_message_handler || + severity >= kAlwaysPrintErrorLevel; +} + +int GetVlogLevelHelper(const char* file, size_t N) { + return 0; +} + +// Explicit instantiations for commonly used comparisons. +template std::string* MakeCheckOpString<int, int>( + const int&, const int&, const char* names); +template std::string* MakeCheckOpString<unsigned long, unsigned long>( + const unsigned long&, const unsigned long&, const char* names); +template std::string* MakeCheckOpString<unsigned long, unsigned int>( + const unsigned long&, const unsigned int&, const char* names); +template std::string* MakeCheckOpString<unsigned int, unsigned long>( + const unsigned int&, const unsigned long&, const char* names); +template std::string* MakeCheckOpString<std::string, std::string>( + const std::string&, const std::string&, const char* name); + +LogMessage::LogMessage(const char* file, int line, LogSeverity severity) + : severity_(severity), file_(file), line_(line) { +} + +LogMessage::LogMessage(const char* file, int line, const char* condition) + : severity_(LOG_FATAL), file_(file), line_(line) { +} + +LogMessage::LogMessage(const char* file, int line, std::string* result) + : severity_(LOG_FATAL), file_(file), line_(line) { + delete result; +} + +LogMessage::LogMessage(const char* file, int line, LogSeverity severity, + std::string* result) + : severity_(severity), file_(file), line_(line) { + delete result; +} + +LogMessage::~LogMessage() { + if (severity_ == LOG_FATAL) { + MOZ_CRASH("Hit fatal chromium sandbox condition."); + } +} + +SystemErrorCode GetLastSystemErrorCode() { +#if defined(OS_WIN) + return ::GetLastError(); +#elif defined(OS_POSIX) + return errno; +#else +#error Not implemented +#endif +} + +#if defined(OS_WIN) +Win32ErrorLogMessage::Win32ErrorLogMessage(const char* file, + int line, + LogSeverity severity, + SystemErrorCode err) + : err_(err), + log_message_(file, line, severity) { + mozilla::Unused << err_; +} + +Win32ErrorLogMessage::~Win32ErrorLogMessage() { +} +#elif defined(OS_POSIX) +ErrnoLogMessage::ErrnoLogMessage(const char* file, + int line, + LogSeverity severity, + SystemErrorCode err) + : err_(err), + log_message_(file, line, severity) { + mozilla::Unused << err_; +} + +ErrnoLogMessage::~ErrnoLogMessage() { +} +#endif // OS_WIN + +void RawLog(int level, const char* message) { +} + +} // namespace logging + +#if defined(OS_WIN) +std::ostream& std::operator<<(std::ostream& out, const wchar_t* wstr) { + return out << base::WideToUTF8(std::wstring(wstr)); +} +#endif diff --git a/security/sandbox/chromium-shim/base/logging_buildflags.h b/security/sandbox/chromium-shim/base/logging_buildflags.h new file mode 100644 index 0000000000..4c7b5451a3 --- /dev/null +++ b/security/sandbox/chromium-shim/base/logging_buildflags.h @@ -0,0 +1,20 @@ +/* -*- 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_
diff --git a/security/sandbox/chromium-shim/base/memory/shared_memory_tracker.h b/security/sandbox/chromium-shim/base/memory/shared_memory_tracker.h new file mode 100644 index 0000000000..0439410ebb --- /dev/null +++ b/security/sandbox/chromium-shim/base/memory/shared_memory_tracker.h @@ -0,0 +1,40 @@ +/* -*- 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 Chromium source file base/memory/shared_memory_tracker.h. +// To provide a class required in base/memory/shared_memory_win.cc. +// The class is used for memory tracking and dumping, which we don't use and +// has significant dependencies. + +#ifndef BASE_MEMORY_SHARED_MEMORY_TRACKER_H_ +#define BASE_MEMORY_SHARED_MEMORY_TRACKER_H_ + +namespace base { + +// SharedMemoryTracker tracks shared memory usage. +class BASE_EXPORT SharedMemoryTracker { + public: + // Returns a singleton instance. + static SharedMemoryTracker* GetInstance() + { + static SharedMemoryTracker* instance = new SharedMemoryTracker; + return instance; + } + + void IncrementMemoryUsage(const SharedMemoryMapping& mapping) {}; + + void DecrementMemoryUsage(const SharedMemoryMapping& mapping) {}; + + private: + SharedMemoryTracker() {}; + ~SharedMemoryTracker() = default; + + DISALLOW_COPY_AND_ASSIGN(SharedMemoryTracker); +}; + +} // namespace base + +#endif // BASE_MEMORY_SHARED_MEMORY_TRACKER_H_ diff --git a/security/sandbox/chromium-shim/base/metrics/histogram_functions.h b/security/sandbox/chromium-shim/base/metrics/histogram_functions.h new file mode 100644 index 0000000000..408e51b408 --- /dev/null +++ b/security/sandbox/chromium-shim/base/metrics/histogram_functions.h @@ -0,0 +1,20 @@ +/* -*- 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 Chromium source file base/metrics/histogram_functions.h. +// To provide to empty histogram functions required for compilation. +// We don't require Chromiums histogram collection code. + +#ifndef BASE_METRICS_HISTOGRAM_FUNCTIONS_H_ +#define BASE_METRICS_HISTOGRAM_FUNCTIONS_H_ + +namespace base { + +BASE_EXPORT void UmaHistogramSparse(const std::string& name, int sample) {} + +} // namespace base + +#endif // BASE_METRICS_HISTOGRAM_FUNCTIONS_H_ diff --git a/security/sandbox/chromium-shim/base/metrics/histogram_macros.h b/security/sandbox/chromium-shim/base/metrics/histogram_macros.h new file mode 100644 index 0000000000..725d7f8076 --- /dev/null +++ b/security/sandbox/chromium-shim/base/metrics/histogram_macros.h @@ -0,0 +1,16 @@ +/* -*- 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 Chromium source file base/metrics/histogram_macros.h. +// To provide empty histogram macros required for compilation. +// We don't require Chromiums histogram collection code. + +#ifndef BASE_METRICS_HISTOGRAM_MACROS_H_ +#define BASE_METRICS_HISTOGRAM_MACROS_H_ + +#define UMA_HISTOGRAM_ENUMERATION(name, sample) do { } while (0) + +#endif // BASE_METRICS_HISTOGRAM_MACROS_H_ diff --git a/security/sandbox/chromium-shim/base/observer_list.h b/security/sandbox/chromium-shim/base/observer_list.h new file mode 100644 index 0000000000..1d539dacb9 --- /dev/null +++ b/security/sandbox/chromium-shim/base/observer_list.h @@ -0,0 +1,12 @@ +/* -*- 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_ diff --git a/security/sandbox/chromium-shim/base/process/launch.h b/security/sandbox/chromium-shim/base/process/launch.h new file mode 100644 index 0000000000..5ead4b40e9 --- /dev/null +++ b/security/sandbox/chromium-shim/base/process/launch.h @@ -0,0 +1,25 @@ +/* -*- 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_
diff --git a/security/sandbox/chromium-shim/base/process/memory_win.cpp b/security/sandbox/chromium-shim/base/process/memory_win.cpp new file mode 100644 index 0000000000..26987fc410 --- /dev/null +++ b/security/sandbox/chromium-shim/base/process/memory_win.cpp @@ -0,0 +1,17 @@ +/* -*- 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 diff --git a/security/sandbox/chromium-shim/base/scoped_native_library.h b/security/sandbox/chromium-shim/base/scoped_native_library.h new file mode 100644 index 0000000000..d6fdf478ec --- /dev/null +++ b/security/sandbox/chromium-shim/base/scoped_native_library.h @@ -0,0 +1,31 @@ +/* -*- 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 Chromium source file base/scoped_native_library.h +// The chromium sandbox only requires ScopedNativeLibrary class to automatically +// unload the library, which we can achieve with UniquePtr. + +#ifndef BASE_SCOPED_NATIVE_LIBRARY_H_ +#define BASE_SCOPED_NATIVE_LIBRARY_H_ + +#include "mozilla/UniquePtr.h" + +namespace base { + +struct HModuleFreePolicy +{ + typedef HMODULE pointer; + void operator()(pointer hModule) + { + ::FreeLibrary(hModule); + } +}; + +typedef mozilla::UniquePtr<HMODULE, HModuleFreePolicy> ScopedNativeLibrary; + +} // namespace base + +#endif // BASE_SCOPED_NATIVE_LIBRARY_H_ diff --git a/security/sandbox/chromium-shim/base/synchronization/synchronization_buildflags.h b/security/sandbox/chromium-shim/base/synchronization/synchronization_buildflags.h new file mode 100644 index 0000000000..4b79551541 --- /dev/null +++ b/security/sandbox/chromium-shim/base/synchronization/synchronization_buildflags.h @@ -0,0 +1,17 @@ +/* -*- 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 dummy version of a file that is generated by the chromium build +// from base/BUILD.gn. + +#ifndef BASE_SYNCHRONIZATION_SYNCHRONIZATION_BUILDFLAGS_H_ +#define BASE_SYNCHRONIZATION_SYNCHRONIZATION_BUILDFLAGS_H_ + +#include "build/buildflag.h" + +#define BUILDFLAG_INTERNAL_ENABLE_MUTEX_PRIORITY_INHERITANCE() (0) + +#endif // BASE_SYNCHRONIZATION_SYNCHRONIZATION_BUILDFLAGS_H_ diff --git a/security/sandbox/chromium-shim/base/third_party/nspr/prtime.h b/security/sandbox/chromium-shim/base/third_party/nspr/prtime.h new file mode 100644 index 0000000000..9a18a36376 --- /dev/null +++ b/security/sandbox/chromium-shim/base/third_party/nspr/prtime.h @@ -0,0 +1,8 @@ +/* -*- 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/. */ + +// Grab the copy from in our tree +#include "pr/include/prtime.h" diff --git a/security/sandbox/chromium-shim/base/third_party/nspr/prtypes.h b/security/sandbox/chromium-shim/base/third_party/nspr/prtypes.h new file mode 100644 index 0000000000..6aec5e08fb --- /dev/null +++ b/security/sandbox/chromium-shim/base/third_party/nspr/prtypes.h @@ -0,0 +1,8 @@ +/* -*- 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/. */ + +// Grab the copy from in our tree +#include "pr/include/prtypes.h" diff --git a/security/sandbox/chromium-shim/base/threading/platform_thread_linux.cpp b/security/sandbox/chromium-shim/base/threading/platform_thread_linux.cpp new file mode 100644 index 0000000000..aed65a06bd --- /dev/null +++ b/security/sandbox/chromium-shim/base/threading/platform_thread_linux.cpp @@ -0,0 +1,69 @@ +/* -*- 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 Chromium source file base/threading/platform_thread_linux.h +// with only the functions required. It also has a dummy implementation of +// SetCurrentThreadPriorityForPlatform, which should not be called. + +#include "base/threading/platform_thread.h" + +#include "base/threading/platform_thread_internal_posix.h" + +#include "mozilla/Assertions.h" + +namespace base { +namespace internal { + +namespace { +const struct sched_param kRealTimePrio = {8}; +} // namespace + +const ThreadPriorityToNiceValuePair kThreadPriorityToNiceValueMap[4] = { + {ThreadPriority::BACKGROUND, 10}, + {ThreadPriority::NORMAL, 0}, + {ThreadPriority::DISPLAY, -8}, + {ThreadPriority::REALTIME_AUDIO, -10}, +}; + + +Optional<bool> CanIncreaseCurrentThreadPriorityForPlatform( + ThreadPriority priority) { + MOZ_CRASH(); +} + +bool SetCurrentThreadPriorityForPlatform(ThreadPriority priority) { + MOZ_CRASH(); +} + +Optional<ThreadPriority> GetCurrentThreadPriorityForPlatform() { + int maybe_sched_rr = 0; + struct sched_param maybe_realtime_prio = {0}; + if (pthread_getschedparam(pthread_self(), &maybe_sched_rr, + &maybe_realtime_prio) == 0 && + maybe_sched_rr == SCHED_RR && + maybe_realtime_prio.sched_priority == kRealTimePrio.sched_priority) { + return base::make_optional(ThreadPriority::REALTIME_AUDIO); + } + return base::nullopt; +} + +} // namespace internal + +void InitThreading() {} + +void TerminateOnThread() {} + +size_t GetDefaultThreadStackSize(const pthread_attr_t& attributes) { +#if !defined(THREAD_SANITIZER) + return 0; +#else + // ThreadSanitizer bloats the stack heavily. Evidence has been that the + // default stack size isn't enough for some browser tests. + return 2 * (1 << 23); // 2 times 8192K (the default stack size on Linux). +#endif +} + +} // namespace base diff --git a/security/sandbox/chromium-shim/base/threading/scoped_blocking_call.h b/security/sandbox/chromium-shim/base/threading/scoped_blocking_call.h new file mode 100644 index 0000000000..519850d34a --- /dev/null +++ b/security/sandbox/chromium-shim/base/threading/scoped_blocking_call.h @@ -0,0 +1,47 @@ +/* -*- 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 Chromium source file +// base/threading/scoped_blocking_call.h +// To provide to a dummy ScopedBlockingCall class. This prevents dependency +// creep and we don't use the rest of the blocking call checking. + +#ifndef BASE_THREADING_SCOPED_BLOCKING_CALL_H +#define BASE_THREADING_SCOPED_BLOCKING_CALL_H + +#include "base/base_export.h" +#include "base/location.h" + +namespace base { + +enum class BlockingType { + // The call might block (e.g. file I/O that might hit in memory cache). + MAY_BLOCK, + // The call will definitely block (e.g. cache already checked and now pinging + // server synchronously). + WILL_BLOCK +}; + +class BASE_EXPORT ScopedBlockingCall { + public: + ScopedBlockingCall(const Location& from_here, BlockingType blocking_type) {}; + ~ScopedBlockingCall() {}; +}; + +namespace internal { + +class BASE_EXPORT ScopedBlockingCallWithBaseSyncPrimitives { + public: + ScopedBlockingCallWithBaseSyncPrimitives(const Location& from_here, + BlockingType blocking_type) {} + ~ScopedBlockingCallWithBaseSyncPrimitives() {}; +}; + +} // namespace internal + +} // namespace base + +#endif // BASE_THREADING_SCOPED_BLOCKING_CALL_H diff --git a/security/sandbox/chromium-shim/base/trace_event/heap_profiler_allocation_context_tracker.h b/security/sandbox/chromium-shim/base/trace_event/heap_profiler_allocation_context_tracker.h new file mode 100644 index 0000000000..bb2cca0ec4 --- /dev/null +++ b/security/sandbox/chromium-shim/base/trace_event/heap_profiler_allocation_context_tracker.h @@ -0,0 +1,32 @@ +/* -*- 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 Chromium source file base/trace_event/heap_profiler_allocation_context_tracker.h. +// To provide a function required in base/threading/thread_id_name_manager.cc +// SetCurrentThreadName. We don't use the heap profiler. + +#ifndef BASE_TRACE_EVENT_HEAP_PROFILER_ALLOCATION_CONTEXT_TRACKER_H_ +#define BASE_TRACE_EVENT_HEAP_PROFILER_ALLOCATION_CONTEXT_TRACKER_H_ + +namespace base { +namespace trace_event { + +// The allocation context tracker keeps track of thread-local context for heap +// profiling. It includes a pseudo stack of trace events. On every allocation +// the tracker provides a snapshot of its context in the form of an +// |AllocationContext| that is to be stored together with the allocation +// details. +class BASE_EXPORT AllocationContextTracker { + public: + static void SetCurrentThreadName(const char* name) {} + + DISALLOW_COPY_AND_ASSIGN(AllocationContextTracker); +}; + +} // namespace trace_event +} // namespace base + +#endif // BASE_TRACE_EVENT_HEAP_PROFILER_ALLOCATION_CONTEXT_TRACKER_H_ diff --git a/security/sandbox/chromium-shim/base/tracked_objects.h b/security/sandbox/chromium-shim/base/tracked_objects.h new file mode 100644 index 0000000000..092c9533f6 --- /dev/null +++ b/security/sandbox/chromium-shim/base/tracked_objects.h @@ -0,0 +1,23 @@ +/* -*- 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/. */ + +#ifndef _SECURITY_SANDBOX_TRACKED_OBJECTS_H_ +#define _SECURITY_SANDBOX_TRACKED_OBJECTS_H_ + +#include "mozilla/Assertions.h" + +namespace tracked_objects +{ + class ThreadData + { + public: + static void InitializeThreadContext(const std::string& name) + { + MOZ_CRASH(); + } + }; +} +#endif diff --git a/security/sandbox/chromium-shim/base/win/base_win_buildflags.h b/security/sandbox/chromium-shim/base/win/base_win_buildflags.h new file mode 100644 index 0000000000..93d3e11a45 --- /dev/null +++ b/security/sandbox/chromium-shim/base/win/base_win_buildflags.h @@ -0,0 +1,17 @@ +/* -*- 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 dummy version of a file that is generated by the chromium build +// from base/win/BUILD.gn. + +#ifndef BASE_WIN_BASE_WIN_BUILDFLAGS_H_ +#define BASE_WIN_BASE_WIN_BUILDFLAGS_H_ + +#include "build/buildflag.h" + +#define BUILDFLAG_INTERNAL_SINGLE_MODULE_MODE_HANDLE_VERIFIER() (0) + +#endif // BASE_WIN_BASE_WIN_BUILDFLAGS_H_ diff --git a/security/sandbox/chromium-shim/base/win/registry.h b/security/sandbox/chromium-shim/base/win/registry.h new file mode 100644 index 0000000000..e5d0f26ed2 --- /dev/null +++ b/security/sandbox/chromium-shim/base/win/registry.h @@ -0,0 +1,48 @@ +/* -*- 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 stripped down version of Chromium source file base/win/registry.h +// Within our copy of Chromium files this is only used in base/win/windows_version.cc +// in OSInfo::processor_model_name, which we don't use. +// It is also used in GetUBR, which is used as the VersionNumber.patch, which +// again is not needed by the sandbox. + +#ifndef BASE_WIN_REGISTRY_H_ +#define BASE_WIN_REGISTRY_H_ + +#include <winerror.h> + +namespace base { +namespace win { + +class BASE_EXPORT RegKey { + public: + RegKey() {}; + RegKey(HKEY rootkey, const wchar_t* subkey, REGSAM access) {} + ~RegKey() {} + + LONG Open(HKEY rootkey, const wchar_t* subkey, REGSAM access) { + return ERROR_CANTOPEN; + } + + LONG ReadValueDW(const wchar_t* name, DWORD* out_value) const + { + return ERROR_CANTREAD; + } + + LONG ReadValue(const wchar_t* name, std::wstring* out_value) const + { + return ERROR_CANTREAD; + } + + private: + DISALLOW_COPY_AND_ASSIGN(RegKey); +}; + +} // namespace win +} // namespace base + +#endif // BASE_WIN_REGISTRY_H_ diff --git a/security/sandbox/chromium-shim/base/win/sdkdecls.h b/security/sandbox/chromium-shim/base/win/sdkdecls.h new file mode 100644 index 0000000000..419f8a0973 --- /dev/null +++ b/security/sandbox/chromium-shim/base/win/sdkdecls.h @@ -0,0 +1,135 @@ +/* -*- 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/. */ + +#ifndef _SECURITY_SANDBOX_BASE_SHIM_SDKDECLS_H_ +#define _SECURITY_SANDBOX_BASE_SHIM_SDKDECLS_H_ + +#include <windows.h> + +// This file contains definitions required for things dynamically loaded +// while building or targetting lower platform versions or lower SDKs. + +#if defined(__MINGW32__) +// +// Define Font Disable Policy. When enabled, this option will +// block loading Non System Fonts. +// + +#define PROCESS_CREATION_MITIGATION_POLICY_FONT_DISABLE_MASK (0x00000003uLL << 48) +#define PROCESS_CREATION_MITIGATION_POLICY_FONT_DISABLE_DEFER (0x00000000uLL << 48) +#define PROCESS_CREATION_MITIGATION_POLICY_FONT_DISABLE_ALWAYS_ON (0x00000001uLL << 48) +#define PROCESS_CREATION_MITIGATION_POLICY_FONT_DISABLE_ALWAYS_OFF (0x00000002uLL << 48) +#define PROCESS_CREATION_MITIGATION_POLICY_AUDIT_NONSYSTEM_FONTS (0x00000003uLL << 48) + +// +// Define remote image load options. When enabled, this option will +// block mapping of images from remote devices. +// + +#define PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_NO_REMOTE_MASK (0x00000003uLL << 52) +#define PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_NO_REMOTE_DEFER (0x00000000uLL << 52) +#define PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_NO_REMOTE_ALWAYS_ON (0x00000001uLL << 52) +#define PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_NO_REMOTE_ALWAYS_OFF (0x00000002uLL << 52) +#define PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_NO_REMOTE_RESERVED (0x00000003uLL << 52) + +// +// Define low IL image load options. When enabled, this option will +// block mapping of images that have the low mandatory label. +// + +#define PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_NO_LOW_LABEL_MASK (0x00000003uLL << 56) +#define PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_NO_LOW_LABEL_DEFER (0x00000000uLL << 56) +#define PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_NO_LOW_LABEL_ALWAYS_ON (0x00000001uLL << 56) +#define PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_NO_LOW_LABEL_ALWAYS_OFF (0x00000002uLL << 56) +#define PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_NO_LOW_LABEL_RESERVED (0x00000003uLL << 56) + +// +// Define image load options to prefer System32 images compared to +// the same images in application directory. When enabled, this option +// will prefer loading images from system32 folder. +// + +#define PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_PREFER_SYSTEM32_MASK (0x00000003uLL << 60) +#define PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_PREFER_SYSTEM32_DEFER (0x00000000uLL << 60) +#define PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_PREFER_SYSTEM32_ALWAYS_ON (0x00000001uLL << 60) +#define PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_PREFER_SYSTEM32_ALWAYS_OFF (0x00000002uLL << 60) +#define PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_PREFER_SYSTEM32_RESERVED (0x00000003uLL << 60) + +// +// Define the restricted indirect branch prediction mitigation policy options. +// + +#define PROCESS_CREATION_MITIGATION_POLICY2_RESTRICT_INDIRECT_BRANCH_PREDICTION_MASK (0x00000003ui64 << 16) +#define PROCESS_CREATION_MITIGATION_POLICY2_RESTRICT_INDIRECT_BRANCH_PREDICTION_DEFER (0x00000000ui64 << 16) +#define PROCESS_CREATION_MITIGATION_POLICY2_RESTRICT_INDIRECT_BRANCH_PREDICTION_ALWAYS_ON (0x00000001ui64 << 16) +#define PROCESS_CREATION_MITIGATION_POLICY2_RESTRICT_INDIRECT_BRANCH_PREDICTION_ALWAYS_OFF (0x00000002ui64 << 16) +#define PROCESS_CREATION_MITIGATION_POLICY2_RESTRICT_INDIRECT_BRANCH_PREDICTION_RESERVED (0x00000003ui64 << 16) + +// +// Define the user-mode shadow stack mitigation policy options. +// + +#define PROCESS_CREATION_MITIGATION_POLICY2_CET_USER_SHADOW_STACKS_MASK (0x00000003ui64 << 28) +#define PROCESS_CREATION_MITIGATION_POLICY2_CET_USER_SHADOW_STACKS_DEFER (0x00000000ui64 << 28) +#define PROCESS_CREATION_MITIGATION_POLICY2_CET_USER_SHADOW_STACKS_ALWAYS_ON (0x00000001ui64 << 28) +#define PROCESS_CREATION_MITIGATION_POLICY2_CET_USER_SHADOW_STACKS_ALWAYS_OFF (0x00000002ui64 << 28) +#define PROCESS_CREATION_MITIGATION_POLICY2_CET_USER_SHADOW_STACKS_RESERVED (0x00000003ui64 << 28) +#define PROCESS_CREATION_MITIGATION_POLICY2_CET_USER_SHADOW_STACKS_STRICT_MODE (0x00000003ui64 << 28) + +// +// Define Attribute to disable creation of child process +// + +#define PROCESS_CREATION_CHILD_PROCESS_RESTRICTED 0x01 +#define PROCESS_CREATION_CHILD_PROCESS_OVERRIDE 0x02 + +// +// Define Attribute for Desktop Appx Overide. +// + +#define PROCESS_CREATION_DESKTOP_APPX_OVERRIDE 0x04 + +#define ProcThreadAttributeChildProcessPolicy 14 + +#define PROC_THREAD_ATTRIBUTE_CHILD_PROCESS_POLICY \ + ProcThreadAttributeValue (ProcThreadAttributeChildProcessPolicy, FALSE, TRUE, FALSE) + +// +// Define Attribute to opt out of matching All Application Packages +// + +#define PROCESS_CREATION_ALL_APPLICATION_PACKAGES_OPT_OUT 0x01 + +#define ProcThreadAttributeAllApplicationPackagesPolicy 15 + +#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 + ); + +WINBASEAPI +BOOL +WINAPI +IsUserCetAvailableInEnvironment( + _In_ DWORD UserCetEnvironment + ); + +#define USER_CET_ENVIRONMENT_WIN32_PROCESS 0x00000000 + +#endif // defined(__MINGW32__) + +#endif // _SECURITY_SANDBOX_BASE_SHIM_SDKDECLS_H_ diff --git a/security/sandbox/chromium-shim/base/win/win_util.cpp b/security/sandbox/chromium-shim/base/win/win_util.cpp new file mode 100644 index 0000000000..3ea789675d --- /dev/null +++ b/security/sandbox/chromium-shim/base/win/win_util.cpp @@ -0,0 +1,42 @@ +/* -*- 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 diff --git a/security/sandbox/chromium-shim/base/win/win_util.h b/security/sandbox/chromium-shim/base/win/win_util.h new file mode 100644 index 0000000000..3e91e63d59 --- /dev/null +++ b/security/sandbox/chromium-shim/base/win/win_util.h @@ -0,0 +1,26 @@ +/* -*- 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_ diff --git a/security/sandbox/chromium-shim/patches/after_update/add_WOW64_flags_to_allowed_registry_read_flags.patch b/security/sandbox/chromium-shim/patches/after_update/add_WOW64_flags_to_allowed_registry_read_flags.patch new file mode 100644 index 0000000000..7eb643719e --- /dev/null +++ b/security/sandbox/chromium-shim/patches/after_update/add_WOW64_flags_to_allowed_registry_read_flags.patch @@ -0,0 +1,34 @@ +# HG changeset patch +# User Bob Owen <bobowencode@gmail.com> +# Date 1482405067 0 +# Thu Dec 22 11:11:07 2016 +0000 +# Node ID 43d0efc18f586e1ed90b95c4a52235c4648e96a9 +# Parent 266ef86795979f2ef9b6650d1bb35fb27d11ad86 +Add KEY_WOW64_64Key and KEY_WOW64_32KEY to the Chromium sandbox allowed registry read flags. r=aklotz + +Originally landed as changeset: +https://hg.mozilla.org/mozilla-central/rev/d24db55deb85 + +diff --git a/security/sandbox/chromium/sandbox/win/src/registry_policy.cc b/security/sandbox/chromium/sandbox/win/src/registry_policy.cc +--- a/security/sandbox/chromium/sandbox/win/src/registry_policy.cc ++++ b/security/sandbox/chromium/sandbox/win/src/registry_policy.cc +@@ -15,17 +15,18 @@ + #include "sandbox/win/src/sandbox_types.h" + #include "sandbox/win/src/sandbox_utils.h" + #include "sandbox/win/src/win_utils.h" + + namespace { + + static const uint32_t kAllowedRegFlags = + KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | KEY_NOTIFY | KEY_READ | +- GENERIC_READ | GENERIC_EXECUTE | READ_CONTROL; ++ GENERIC_READ | GENERIC_EXECUTE | READ_CONTROL | KEY_WOW64_64KEY | ++ KEY_WOW64_32KEY; + + // Opens the key referenced by |obj_attributes| with |access| and + // checks what permission was given. Remove the WRITE flags and update + // |access| with the new value. + NTSTATUS TranslateMaximumAllowed(OBJECT_ATTRIBUTES* obj_attributes, + DWORD* access) { + NtOpenKeyFunction NtOpenKey = nullptr; + ResolveNTFunctionPtr("NtOpenKey", &NtOpenKey); diff --git a/security/sandbox/chromium-shim/patches/after_update/add_interception_logging.patch b/security/sandbox/chromium-shim/patches/after_update/add_interception_logging.patch new file mode 100644 index 0000000000..344fd569d7 --- /dev/null +++ b/security/sandbox/chromium-shim/patches/after_update/add_interception_logging.patch @@ -0,0 +1,810 @@ +# HG changeset patch +# User Bob Owen <bobowencode@gmail.com> +# Date 1417281138 0 +# Sat Nov 29 17:12:18 2014 +0000 +# Node ID 4ea2e332affe4b74bd37fbf2fee8da0b1c94e115 +# Parent 5eec91873c96c2cbfc856ba86335fa068c89d6ce +Re-apply - Logging changes to the Chromium interception code. r=tabraldes + +Originally landed as changset: +https://hg.mozilla.org/mozilla-central/rev/0f763c186855 + +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 +@@ -10,16 +10,17 @@ + #include "sandbox/win/src/filesystem_policy.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" + + // This status occurs when trying to access a network share on the machine from + // which it is shared. + #define STATUS_NETWORK_OPEN_RESTRICTION ((NTSTATUS)0xC0000201L) + + namespace sandbox { + + NTSTATUS WINAPI TargetNtCreateFile(NtCreateFileFunction orig_CreateFile, +@@ -37,16 +38,20 @@ NTSTATUS WINAPI TargetNtCreateFile(NtCre + // Check if the process can open it first. + NTSTATUS status = orig_CreateFile( + file, desired_access, object_attributes, io_status, allocation_size, + file_attributes, sharing, disposition, options, ea_buffer, ea_length); + if (STATUS_ACCESS_DENIED != status && + STATUS_NETWORK_OPEN_RESTRICTION != status) + return status; + ++ mozilla::sandboxing::LogBlocked("NtCreateFile", ++ object_attributes->ObjectName->Buffer, ++ object_attributes->ObjectName->Length); ++ + // We don't trust that the IPC can work this early. + if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) + return status; + + do { + if (!ValidParameter(file, sizeof(HANDLE), WRITE)) + break; + if (!ValidParameter(io_status, sizeof(IO_STATUS_BLOCK), WRITE)) +@@ -96,16 +101,19 @@ NTSTATUS WINAPI TargetNtCreateFile(NtCre + + __try { + *file = answer.handle; + io_status->Status = answer.nt_status; + io_status->Information = answer.extended[0].ulong_ptr; + } __except (EXCEPTION_EXECUTE_HANDLER) { + break; + } ++ mozilla::sandboxing::LogAllowed("NtCreateFile", ++ object_attributes->ObjectName->Buffer, ++ object_attributes->ObjectName->Length); + } while (false); + + return status; + } + + NTSTATUS WINAPI TargetNtOpenFile(NtOpenFileFunction orig_OpenFile, + PHANDLE file, + ACCESS_MASK desired_access, +@@ -115,16 +123,20 @@ NTSTATUS WINAPI TargetNtOpenFile(NtOpenF + ULONG options) { + // Check if the process can open it first. + NTSTATUS status = orig_OpenFile(file, desired_access, object_attributes, + io_status, sharing, options); + if (STATUS_ACCESS_DENIED != status && + STATUS_NETWORK_OPEN_RESTRICTION != status) + return status; + ++ mozilla::sandboxing::LogBlocked("NtOpenFile", ++ object_attributes->ObjectName->Buffer, ++ object_attributes->ObjectName->Length); ++ + // We don't trust that the IPC can work this early. + if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) + return status; + + do { + if (!ValidParameter(file, sizeof(HANDLE), WRITE)) + break; + if (!ValidParameter(io_status, sizeof(IO_STATUS_BLOCK), WRITE)) +@@ -171,31 +183,38 @@ NTSTATUS WINAPI TargetNtOpenFile(NtOpenF + + __try { + *file = answer.handle; + io_status->Status = answer.nt_status; + io_status->Information = answer.extended[0].ulong_ptr; + } __except (EXCEPTION_EXECUTE_HANDLER) { + break; + } ++ mozilla::sandboxing::LogAllowed("NtOpenFile", ++ object_attributes->ObjectName->Buffer, ++ object_attributes->ObjectName->Length); + } while (false); + + return status; + } + + NTSTATUS WINAPI + TargetNtQueryAttributesFile(NtQueryAttributesFileFunction orig_QueryAttributes, + POBJECT_ATTRIBUTES object_attributes, + PFILE_BASIC_INFORMATION file_attributes) { + // Check if the process can query it first. + NTSTATUS status = orig_QueryAttributes(object_attributes, file_attributes); + if (STATUS_ACCESS_DENIED != status && + STATUS_NETWORK_OPEN_RESTRICTION != status) + return status; + ++ mozilla::sandboxing::LogBlocked("NtQueryAttributesFile", ++ object_attributes->ObjectName->Buffer, ++ object_attributes->ObjectName->Length); ++ + // We don't trust that the IPC can work this early. + if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) + return status; + + do { + if (!ValidParameter(file_attributes, sizeof(FILE_BASIC_INFORMATION), WRITE)) + break; + +@@ -227,32 +246,39 @@ TargetNtQueryAttributesFile(NtQueryAttri + ResultCode code = CrossCall(ipc, IpcTag::NTQUERYATTRIBUTESFILE, name.get(), + attributes, file_info, &answer); + + if (SBOX_ALL_OK != code) + break; + + status = answer.nt_status; + ++ mozilla::sandboxing::LogAllowed("NtQueryAttributesFile", ++ object_attributes->ObjectName->Buffer, ++ object_attributes->ObjectName->Length); + } while (false); + + return status; + } + + NTSTATUS WINAPI TargetNtQueryFullAttributesFile( + NtQueryFullAttributesFileFunction orig_QueryFullAttributes, + POBJECT_ATTRIBUTES object_attributes, + PFILE_NETWORK_OPEN_INFORMATION file_attributes) { + // Check if the process can query it first. + NTSTATUS status = + orig_QueryFullAttributes(object_attributes, file_attributes); + if (STATUS_ACCESS_DENIED != status && + STATUS_NETWORK_OPEN_RESTRICTION != status) + return status; + ++ mozilla::sandboxing::LogBlocked("NtQueryFullAttributesFile", ++ object_attributes->ObjectName->Buffer, ++ object_attributes->ObjectName->Length); ++ + // We don't trust that the IPC can work this early. + if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) + return status; + + do { + if (!ValidParameter(file_attributes, sizeof(FILE_NETWORK_OPEN_INFORMATION), + WRITE)) + break; +@@ -284,16 +310,20 @@ NTSTATUS WINAPI TargetNtQueryFullAttribu + CrossCallReturn answer = {0}; + ResultCode code = CrossCall(ipc, IpcTag::NTQUERYFULLATTRIBUTESFILE, + name.get(), attributes, file_info, &answer); + + if (SBOX_ALL_OK != code) + break; + + status = answer.nt_status; ++ ++ mozilla::sandboxing::LogAllowed("NtQueryFullAttributesFile", ++ object_attributes->ObjectName->Buffer, ++ object_attributes->ObjectName->Length); + } while (false); + + return status; + } + + NTSTATUS WINAPI + TargetNtSetInformationFile(NtSetInformationFileFunction orig_SetInformationFile, + HANDLE file, +@@ -302,16 +332,18 @@ TargetNtSetInformationFile(NtSetInformat + ULONG length, + FILE_INFORMATION_CLASS file_info_class) { + // Check if the process can open it first. + NTSTATUS status = orig_SetInformationFile(file, io_status, file_info, length, + file_info_class); + if (STATUS_ACCESS_DENIED != status) + return status; + ++ mozilla::sandboxing::LogBlocked("NtSetInformationFile"); ++ + // We don't trust that the IPC can work this early. + if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) + return status; + + do { + void* memory = GetGlobalIPCMemory(); + if (!memory) + break; +@@ -366,14 +398,15 @@ TargetNtSetInformationFile(NtSetInformat + ResultCode code = + CrossCall(ipc, IpcTag::NTSETINFO_RENAME, file, io_status_buffer, + file_info_buffer, length, file_info_class, &answer); + + if (SBOX_ALL_OK != code) + break; + + status = answer.nt_status; ++ mozilla::sandboxing::LogAllowed("NtSetInformationFile"); + } while (false); + + return status; + } + + } // namespace sandbox +diff --git a/security/sandbox/chromium/sandbox/win/src/handle_interception.cc b/security/sandbox/chromium/sandbox/win/src/handle_interception.cc +--- a/security/sandbox/chromium/sandbox/win/src/handle_interception.cc ++++ b/security/sandbox/chromium/sandbox/win/src/handle_interception.cc +@@ -5,16 +5,17 @@ + #include "sandbox/win/src/handle_interception.h" + + #include "sandbox/win/src/crosscall_client.h" + #include "sandbox/win/src/ipc_tags.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 { + + ResultCode DuplicateHandleProxy(HANDLE source_handle, + DWORD target_process_id, + HANDLE* target_handle, + DWORD desired_access, + DWORD options) { +@@ -29,17 +30,19 @@ ResultCode DuplicateHandleProxy(HANDLE s + ResultCode code = CrossCall(ipc, IpcTag::DUPLICATEHANDLEPROXY, + source_handle, target_process_id, + desired_access, options, &answer); + if (SBOX_ALL_OK != code) + return code; + + if (answer.win32_result) { + ::SetLastError(answer.win32_result); ++ mozilla::sandboxing::LogBlocked("DuplicateHandle"); + return SBOX_ERROR_GENERIC; + } + + *target_handle = answer.handle; ++ mozilla::sandboxing::LogAllowed("DuplicateHandle"); + return SBOX_ALL_OK; + } + + } // namespace sandbox + +diff --git a/security/sandbox/chromium/sandbox/win/src/named_pipe_interception.cc b/security/sandbox/chromium/sandbox/win/src/named_pipe_interception.cc +--- a/security/sandbox/chromium/sandbox/win/src/named_pipe_interception.cc ++++ b/security/sandbox/chromium/sandbox/win/src/named_pipe_interception.cc +@@ -7,16 +7,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 { + + HANDLE WINAPI + TargetCreateNamedPipeW(CreateNamedPipeWFunction orig_CreateNamedPipeW, + LPCWSTR pipe_name, + DWORD open_mode, + DWORD pipe_mode, +@@ -26,16 +27,18 @@ TargetCreateNamedPipeW(CreateNamedPipeWF + DWORD default_timeout, + LPSECURITY_ATTRIBUTES security_attributes) { + HANDLE pipe = orig_CreateNamedPipeW( + pipe_name, open_mode, pipe_mode, max_instance, out_buffer_size, + in_buffer_size, default_timeout, security_attributes); + if (INVALID_HANDLE_VALUE != pipe) + return pipe; + ++ mozilla::sandboxing::LogBlocked("CreateNamedPipeW", pipe_name); ++ + // We don't trust that the IPC can work this early. + if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) + return INVALID_HANDLE_VALUE; + + DWORD original_error = ::GetLastError(); + + // We don't support specific Security Attributes. + if (security_attributes) +@@ -61,16 +64,17 @@ TargetCreateNamedPipeW(CreateNamedPipeWF + if (SBOX_ALL_OK != code) + break; + + ::SetLastError(answer.win32_result); + + if (ERROR_SUCCESS != answer.win32_result) + return INVALID_HANDLE_VALUE; + ++ mozilla::sandboxing::LogAllowed("CreateNamedPipeW", pipe_name); + return answer.handle; + } while (false); + + ::SetLastError(original_error); + return INVALID_HANDLE_VALUE; + } + + } // namespace sandbox +diff --git a/security/sandbox/chromium/sandbox/win/src/process_thread_interception.cc b/security/sandbox/chromium/sandbox/win/src/process_thread_interception.cc +--- a/security/sandbox/chromium/sandbox/win/src/process_thread_interception.cc ++++ b/security/sandbox/chromium/sandbox/win/src/process_thread_interception.cc +@@ -10,16 +10,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 { + + SANDBOX_INTERCEPT NtExports g_nt; + + // Hooks NtOpenThread and proxy the call to the broker if it's trying to + // open a thread in the same process. + NTSTATUS WINAPI TargetNtOpenThread(NtOpenThreadFunction orig_OpenThread, +@@ -27,16 +28,17 @@ NTSTATUS WINAPI TargetNtOpenThread(NtOpe + ACCESS_MASK desired_access, + POBJECT_ATTRIBUTES object_attributes, + PCLIENT_ID client_id) { + NTSTATUS status = + orig_OpenThread(thread, desired_access, object_attributes, client_id); + if (NT_SUCCESS(status)) + return status; + ++ mozilla::sandboxing::LogBlocked("NtOpenThread"); + do { + if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) + break; + if (!client_id) + break; + + uint32_t thread_id = 0; + bool should_break = false; +@@ -91,16 +93,17 @@ NTSTATUS WINAPI TargetNtOpenThread(NtOpe + + __try { + // Write the output parameters. + *thread = answer.handle; + } __except (EXCEPTION_EXECUTE_HANDLER) { + break; + } + ++ mozilla::sandboxing::LogAllowed("NtOpenThread"); + return answer.nt_status; + } while (false); + + return status; + } + + // Hooks NtOpenProcess and proxy the call to the broker if it's trying to + // open the current process. +@@ -176,16 +179,17 @@ NTSTATUS WINAPI + TargetNtOpenProcessToken(NtOpenProcessTokenFunction orig_OpenProcessToken, + HANDLE process, + ACCESS_MASK desired_access, + PHANDLE token) { + NTSTATUS status = orig_OpenProcessToken(process, desired_access, token); + if (NT_SUCCESS(status)) + return status; + ++ mozilla::sandboxing::LogBlocked("NtOpenProcessToken"); + do { + if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) + break; + + if (CURRENT_PROCESS != process) + break; + + if (!ValidParameter(token, sizeof(HANDLE), WRITE)) +@@ -207,16 +211,17 @@ TargetNtOpenProcessToken(NtOpenProcessTo + + __try { + // Write the output parameters. + *token = answer.handle; + } __except (EXCEPTION_EXECUTE_HANDLER) { + break; + } + ++ mozilla::sandboxing::LogAllowed("NtOpenProcessToken"); + return answer.nt_status; + } while (false); + + return status; + } + + NTSTATUS WINAPI + TargetNtOpenProcessTokenEx(NtOpenProcessTokenExFunction orig_OpenProcessTokenEx, +@@ -224,16 +229,17 @@ TargetNtOpenProcessTokenEx(NtOpenProcess + ACCESS_MASK desired_access, + ULONG handle_attributes, + PHANDLE token) { + NTSTATUS status = orig_OpenProcessTokenEx(process, desired_access, + handle_attributes, token); + if (NT_SUCCESS(status)) + return status; + ++ mozilla::sandboxing::LogBlocked("NtOpenProcessTokenEx"); + do { + if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) + break; + + if (CURRENT_PROCESS != process) + break; + + if (!ValidParameter(token, sizeof(HANDLE), WRITE)) +@@ -255,16 +261,17 @@ TargetNtOpenProcessTokenEx(NtOpenProcess + + __try { + // Write the output parameters. + *token = answer.handle; + } __except (EXCEPTION_EXECUTE_HANDLER) { + break; + } + ++ mozilla::sandboxing::LogAllowed("NtOpenProcessTokenEx"); + return answer.nt_status; + } while (false); + + return status; + } + + BOOL WINAPI TargetCreateProcessW(CreateProcessWFunction orig_CreateProcessW, + LPCWSTR application_name, +@@ -280,16 +287,18 @@ BOOL WINAPI TargetCreateProcessW(CreateP + if (SandboxFactory::GetTargetServices()->GetState()->IsCsrssConnected() && + orig_CreateProcessW(application_name, command_line, process_attributes, + thread_attributes, inherit_handles, flags, + environment, current_directory, startup_info, + process_information)) { + return true; + } + ++ mozilla::sandboxing::LogBlocked("CreateProcessW", application_name); ++ + // We don't trust that the IPC can work this early. + if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) + return false; + + // Don't call GetLastError before InitCalled() succeeds because kernel32 may + // not be mapped yet. + DWORD original_error = ::GetLastError(); + +@@ -320,16 +329,17 @@ BOOL WINAPI TargetCreateProcessW(CreateP + cur_dir, current_directory, proc_info, &answer); + if (SBOX_ALL_OK != code) + break; + + ::SetLastError(answer.win32_result); + if (ERROR_SUCCESS != answer.win32_result) + return false; + ++ mozilla::sandboxing::LogAllowed("CreateProcessW", application_name); + return true; + } while (false); + + ::SetLastError(original_error); + return false; + } + + BOOL WINAPI TargetCreateProcessA(CreateProcessAFunction orig_CreateProcessA, +@@ -346,16 +356,18 @@ BOOL WINAPI TargetCreateProcessA(CreateP + if (SandboxFactory::GetTargetServices()->GetState()->IsCsrssConnected() && + orig_CreateProcessA(application_name, command_line, process_attributes, + thread_attributes, inherit_handles, flags, + environment, current_directory, startup_info, + process_information)) { + return true; + } + ++ mozilla::sandboxing::LogBlocked("CreateProcessA", application_name); ++ + // We don't trust that the IPC can work this early. + if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) + return false; + + // Don't call GetLastError before InitCalled() succeeds because kernel32 may + // not be mapped yet. + DWORD original_error = ::GetLastError(); + +@@ -420,16 +432,17 @@ BOOL WINAPI TargetCreateProcessA(CreateP + + if (SBOX_ALL_OK != code) + break; + + ::SetLastError(answer.win32_result); + if (ERROR_SUCCESS != answer.win32_result) + return false; + ++ mozilla::sandboxing::LogAllowed("CreateProcessA", application_name); + return true; + } while (false); + + ::SetLastError(original_error); + return false; + } + + HANDLE WINAPI TargetCreateThread(CreateThreadFunction orig_CreateThread, +diff --git a/security/sandbox/chromium/sandbox/win/src/registry_interception.cc b/security/sandbox/chromium/sandbox/win/src/registry_interception.cc +--- a/security/sandbox/chromium/sandbox/win/src/registry_interception.cc ++++ b/security/sandbox/chromium/sandbox/win/src/registry_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 TargetNtCreateKey(NtCreateKeyFunction orig_CreateKey, + PHANDLE key, + ACCESS_MASK desired_access, + POBJECT_ATTRIBUTES object_attributes, + ULONG title_index, +@@ -27,16 +28,22 @@ NTSTATUS WINAPI TargetNtCreateKey(NtCrea + PULONG disposition) { + // Check if the process can create it first. + NTSTATUS status = + orig_CreateKey(key, desired_access, object_attributes, title_index, + class_name, create_options, disposition); + if (NT_SUCCESS(status)) + return status; + ++ if (STATUS_OBJECT_NAME_NOT_FOUND != status) { ++ mozilla::sandboxing::LogBlocked("NtCreateKey", ++ object_attributes->ObjectName->Buffer, ++ object_attributes->ObjectName->Length); ++ } ++ + // We don't trust that the IPC can work this early. + if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) + return status; + + do { + if (!ValidParameter(key, sizeof(HANDLE), WRITE)) + break; + +@@ -114,16 +121,19 @@ NTSTATUS WINAPI TargetNtCreateKey(NtCrea + + if (disposition) + *disposition = answer.extended[0].unsigned_int; + + status = answer.nt_status; + } __except (EXCEPTION_EXECUTE_HANDLER) { + break; + } ++ mozilla::sandboxing::LogAllowed("NtCreateKey", ++ object_attributes->ObjectName->Buffer, ++ object_attributes->ObjectName->Length); + } while (false); + + return status; + } + + NTSTATUS WINAPI CommonNtOpenKey(NTSTATUS status, + PHANDLE key, + ACCESS_MASK desired_access, +@@ -193,30 +203,39 @@ NTSTATUS WINAPI CommonNtOpenKey(NTSTATUS + break; + + __try { + *key = answer.handle; + status = answer.nt_status; + } __except (EXCEPTION_EXECUTE_HANDLER) { + break; + } ++ mozilla::sandboxing::LogAllowed("NtOpenKey[Ex]", ++ object_attributes->ObjectName->Buffer, ++ object_attributes->ObjectName->Length); + } while (false); + + return status; + } + + NTSTATUS WINAPI TargetNtOpenKey(NtOpenKeyFunction orig_OpenKey, + PHANDLE key, + ACCESS_MASK desired_access, + POBJECT_ATTRIBUTES object_attributes) { + // Check if the process can open it first. + NTSTATUS status = orig_OpenKey(key, desired_access, object_attributes); + if (NT_SUCCESS(status)) + return status; + ++ if (STATUS_OBJECT_NAME_NOT_FOUND != status) { ++ mozilla::sandboxing::LogBlocked("NtOpenKey", ++ object_attributes->ObjectName->Buffer, ++ object_attributes->ObjectName->Length); ++ } ++ + return CommonNtOpenKey(status, key, desired_access, object_attributes); + } + + NTSTATUS WINAPI TargetNtOpenKeyEx(NtOpenKeyExFunction orig_OpenKeyEx, + PHANDLE key, + ACCESS_MASK desired_access, + POBJECT_ATTRIBUTES object_attributes, + ULONG open_options) { +@@ -225,12 +244,18 @@ NTSTATUS WINAPI TargetNtOpenKeyEx(NtOpen + orig_OpenKeyEx(key, desired_access, object_attributes, open_options); + + // We do not support open_options at this time. The 2 current known values + // are REG_OPTION_CREATE_LINK, to open a symbolic link, and + // REG_OPTION_BACKUP_RESTORE to open the key with special privileges. + if (NT_SUCCESS(status) || open_options != 0) + return status; + ++ if (STATUS_OBJECT_NAME_NOT_FOUND != status) { ++ mozilla::sandboxing::LogBlocked("NtOpenKeyEx", ++ object_attributes->ObjectName->Buffer, ++ object_attributes->ObjectName->Length); ++ } ++ + return CommonNtOpenKey(status, key, desired_access, object_attributes); + } + + } // 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 +@@ -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 { + + ResultCode ProxyCreateEvent(LPCWSTR name, + uint32_t initial_state, + EVENT_TYPE event_type, + void* ipc_memory, + CrossCallReturn* answer) { +@@ -59,16 +60,20 @@ NTSTATUS WINAPI TargetNtCreateEvent(NtCr + EVENT_TYPE event_type, + BOOLEAN initial_state) { + NTSTATUS status = + orig_CreateEvent(event_handle, desired_access, object_attributes, + event_type, initial_state); + if (status != STATUS_ACCESS_DENIED || !object_attributes) + return status; + ++ mozilla::sandboxing::LogBlocked("NtCreatEvent", ++ object_attributes->ObjectName->Buffer, ++ object_attributes->ObjectName->Length); ++ + // We don't trust that the IPC can work this early. + if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) + return status; + + do { + if (!ValidParameter(event_handle, sizeof(HANDLE), WRITE)) + break; + +@@ -97,30 +102,37 @@ NTSTATUS WINAPI TargetNtCreateEvent(NtCr + break; + } + __try { + *event_handle = answer.handle; + status = STATUS_SUCCESS; + } __except (EXCEPTION_EXECUTE_HANDLER) { + break; + } ++ mozilla::sandboxing::LogAllowed("NtCreateEvent", ++ object_attributes->ObjectName->Buffer, ++ object_attributes->ObjectName->Length); + } while (false); + + return status; + } + + NTSTATUS WINAPI TargetNtOpenEvent(NtOpenEventFunction orig_OpenEvent, + PHANDLE event_handle, + ACCESS_MASK desired_access, + POBJECT_ATTRIBUTES object_attributes) { + NTSTATUS status = + orig_OpenEvent(event_handle, desired_access, object_attributes); + if (status != STATUS_ACCESS_DENIED || !object_attributes) + return status; + ++ mozilla::sandboxing::LogBlocked("NtOpenEvent", ++ object_attributes->ObjectName->Buffer, ++ object_attributes->ObjectName->Length); ++ + // We don't trust that the IPC can work this early. + if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) + return status; + + do { + if (!ValidParameter(event_handle, sizeof(HANDLE), WRITE)) + break; + +@@ -149,14 +161,17 @@ NTSTATUS WINAPI TargetNtOpenEvent(NtOpen + break; + } + __try { + *event_handle = answer.handle; + status = STATUS_SUCCESS; + } __except (EXCEPTION_EXECUTE_HANDLER) { + break; + } ++ mozilla::sandboxing::LogAllowed("NtOpenEvent", ++ object_attributes->ObjectName->Buffer, ++ object_attributes->ObjectName->Length); + } while (false); + + return status; + } + + } // namespace sandbox diff --git a/security/sandbox/chromium-shim/patches/after_update/allow_ntpath_in_SignedPolicy_GenerateRules.patch b/security/sandbox/chromium-shim/patches/after_update/allow_ntpath_in_SignedPolicy_GenerateRules.patch new file mode 100644 index 0000000000..8e6a951467 --- /dev/null +++ b/security/sandbox/chromium-shim/patches/after_update/allow_ntpath_in_SignedPolicy_GenerateRules.patch @@ -0,0 +1,82 @@ +# HG changeset patch +# User Toshihito Kikuchi <tkikuchi@mozilla.com> +# Date 1605814807 28800 +# Thu Nov 19 11:40:07 2020 -0800 +# Node ID 29b049665db1f28ffdfce319ad48912d4a024e23 +# Parent 94435953fb89c1fe147c6b76a9ecb61f59625d30 +Bug 1620114 - Allow an NT path string to be passed to SignedPolicy::GenerateRules. r=bobowen +so that our SandboxBroker can add a policy rule with an NT path directly. + +diff --git a/security/sandbox/chromium/sandbox/win/src/signed_policy.cc b/security/sandbox/chromium/sandbox/win/src/signed_policy.cc +--- a/security/sandbox/chromium/sandbox/win/src/signed_policy.cc ++++ b/security/sandbox/chromium/sandbox/win/src/signed_policy.cc +@@ -7,39 +7,63 @@ + #include <stdint.h> + + #include <string> + + #include "sandbox/win/src/ipc_tags.h" + #include "sandbox/win/src/policy_engine_opcodes.h" + #include "sandbox/win/src/policy_params.h" + #include "sandbox/win/src/sandbox_policy.h" ++#include "sandbox/win/src/sandbox_utils.h" + #include "sandbox/win/src/win_utils.h" + ++namespace { ++ ++bool IsValidNtPath(const base::FilePath& name) { ++ UNICODE_STRING uni_name; ++ OBJECT_ATTRIBUTES obj_attr; ++ sandbox::InitObjectAttribs(name.value(), OBJ_CASE_INSENSITIVE, nullptr, ++ &obj_attr, &uni_name, nullptr); ++ ++ NtQueryAttributesFileFunction NtQueryAttributesFile = nullptr; ++ ResolveNTFunctionPtr("NtQueryAttributesFile", &NtQueryAttributesFile); ++ FILE_BASIC_INFORMATION file_info; ++ return NtQueryAttributesFile && ++ NT_SUCCESS(NtQueryAttributesFile(&obj_attr, &file_info)); ++} ++ ++} // namespace ++ + namespace sandbox { + + bool SignedPolicy::GenerateRules(const wchar_t* name, + TargetPolicy::Semantics semantics, + LowLevelPolicy* policy) { + // Only support one semantic. + if (TargetPolicy::SIGNED_ALLOW_LOAD != semantics) { + return false; + } + + base::FilePath file_path(name); ++ base::FilePath nt_filename; + std::wstring nt_path_name; +- if (!GetNtPathFromWin32Path(file_path.DirName().value().c_str(), +- &nt_path_name)) ++ if (GetNtPathFromWin32Path(file_path.DirName().value().c_str(), ++ &nt_path_name)) { ++ base::FilePath nt_path(nt_path_name); ++ nt_filename = nt_path.Append(file_path.BaseName()); ++ } else if (IsValidNtPath(file_path)) { ++ nt_filename = std::move(file_path); ++ } else { + return false; +- base::FilePath nt_path(nt_path_name); +- std::wstring nt_filename = nt_path.Append(file_path.BaseName()).value(); ++ } ++ + // Create a rule to ASK_BROKER if name matches. + PolicyRule signed_policy(ASK_BROKER); +- if (!signed_policy.AddStringMatch(IF, NameBased::NAME, nt_filename.c_str(), +- CASE_INSENSITIVE)) { ++ if (!signed_policy.AddStringMatch( ++ IF, NameBased::NAME, nt_filename.value().c_str(), CASE_INSENSITIVE)) { + return false; + } + if (!policy->AddRule(IpcTag::NTCREATESECTION, &signed_policy)) { + return false; + } + + return true; + } diff --git a/security/sandbox/chromium-shim/patches/after_update/allow_rules_for_network_drive_and_non_file_devices.patch b/security/sandbox/chromium-shim/patches/after_update/allow_rules_for_network_drive_and_non_file_devices.patch new file mode 100644 index 0000000000..8d497e1ff9 --- /dev/null +++ b/security/sandbox/chromium-shim/patches/after_update/allow_rules_for_network_drive_and_non_file_devices.patch @@ -0,0 +1,190 @@ +# HG changeset patch +# User Bob Owen <bobowencode@gmail.com> +# Date 1454317140 0 +# Mon Feb 01 08:59:00 2016 +0000 +# Node ID 9870a92ea5f352ab5a841003a30ab52c8deb589e +# Parent d62b6a3a0c58528a8bf864bb5ab6bb9faada972b +Change to allow network drives in sandbox rules with non-file device fix. r=aklotz + +Originally landed in changeset: +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 + + return false; + } + + // |full_path| can have any of the following forms: + // \??\c:\some\foo\bar + // \Device\HarddiskVolume0\some\foo\bar + // \??\HarddiskVolume0\some\foo\bar ++// \??\UNC\SERVER\Share\some\foo\bar + DWORD IsReparsePoint(const std::wstring& 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; + bool nt_path = IsNTPath(full_path, &path); + bool has_drive = StartsWithDriveLetter(path); + bool is_device_path = IsDevicePath(path, &path); + + if (!has_drive && !is_device_path && !nt_path) + return ERROR_INVALID_NAME; + +- bool added_implied_device = false; + if (!has_drive) { +- path = std::wstring(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; +- bool passed_once = false; ++ // Ensure that volume path matches start of path. ++ wchar_t vol_path[MAX_PATH]; ++ if (!::GetVolumePathNameW(path.c_str(), vol_path, MAX_PATH)) { ++ // This will fail if this is a device that isn't volume related, which can't ++ // then be a reparse point. ++ return is_device_path ? ERROR_NOT_A_REPARSE_POINT : ERROR_INVALID_NAME; ++ } ++ ++ // vol_path includes a trailing slash, so reduce size for path and loop check. ++ size_t vol_path_len = wcslen(vol_path) - 1; ++ if (!EqualPath(path, vol_path, vol_path_len)) { ++ return ERROR_INVALID_NAME; ++ } + + do { +- path = path.substr(0, last_pos); +- + DWORD attributes = ::GetFileAttributes(path.c_str()); + if (INVALID_FILE_ATTRIBUTES == attributes) { + DWORD error = ::GetLastError(); + if (error != ERROR_FILE_NOT_FOUND && error != ERROR_PATH_NOT_FOUND && ++ error != ERROR_INVALID_FUNCTION && + error != ERROR_INVALID_NAME) { + // Unexpected error. +- if (passed_once && added_implied_device && +- (path.rfind(L'\\') == kNTDotPrefixLen - 1)) { +- break; +- } + return error; + } + } else if (FILE_ATTRIBUTE_REPARSE_POINT & attributes) { + // This is a reparse point. + return ERROR_SUCCESS; + } + +- passed_once = true; +- last_pos = path.rfind(L'\\'); +- } while (last_pos > 2); // Skip root dir. ++ path.resize(path.rfind(L'\\')); ++ } while (path.size() > vol_path_len); // Skip root dir. + + return ERROR_NOT_A_REPARSE_POINT; + } + + // We get a |full_path| of the forms accepted by IsReparsePoint(), and the name + // 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; + if (!GetPathFromHandle(handle, &actual_path)) + return false; + + std::wstring path(full_path); + DCHECK_NT(!path.empty()); + + // This may end with a backslash. +- const wchar_t kBackslash = '\\'; +- if (path.back() == kBackslash) +- path = path.substr(0, path.length() - 1); ++ if (path.back() == L'\\') { ++ path.pop_back(); ++ } + +- // Perfect match (case-insesitive check). ++ // Perfect match (case-insensitive check). + if (EqualPath(actual_path, path)) + return true; + + bool nt_path = IsNTPath(path, &path); + bool has_drive = StartsWithDriveLetter(path); + + if (!has_drive && nt_path) { + std::wstring simple_actual_path; +- if (!IsDevicePath(actual_path, &simple_actual_path)) +- return false; +- +- // Perfect match (case-insesitive check). +- return (EqualPath(simple_actual_path, path)); ++ if (IsDevicePath(path, &path)) { ++ if (IsDevicePath(actual_path, &simple_actual_path)) { ++ // Perfect match (case-insensitive check). ++ return (EqualPath(simple_actual_path, path)); ++ } else { ++ return false; ++ } ++ } else { ++ // Add Win32 device namespace for GetVolumePathName. ++ path.insert(0, kNTDotPrefix); ++ } + } + +- if (!has_drive) ++ // Get the volume path in the same format as actual_path. ++ wchar_t vol_path[MAX_PATH]; ++ if (!::GetVolumePathName(path.c_str(), vol_path, MAX_PATH)) { + return false; +- +- // We only need 3 chars, but let's alloc a buffer for four. +- wchar_t drive[4] = {0}; +- wchar_t vol_name[MAX_PATH]; +- memcpy(drive, &path[0], 2 * sizeof(*drive)); +- +- // We'll get a double null terminated string. +- DWORD vol_length = ::QueryDosDeviceW(drive, vol_name, MAX_PATH); +- if (vol_length < 2 || vol_length == MAX_PATH) ++ } ++ size_t vol_path_len = wcslen(vol_path); ++ base::string16 nt_vol; ++ if (!GetNtPathFromWin32Path(vol_path, &nt_vol)) { + return false; +- +- // Ignore the nulls at the end. +- vol_length = static_cast<DWORD>(wcslen(vol_name)); ++ } + + // The two paths should be the same length. +- if (vol_length + path.size() - 2 != actual_path.size()) ++ if (nt_vol.size() + path.size() - vol_path_len != actual_path.size()) { + return false; ++ } + +- // Check up to the drive letter. +- if (!EqualPath(actual_path, vol_name, vol_length)) ++ // Check the volume matches. ++ if (!EqualPath(actual_path, nt_vol.c_str(), nt_vol.size())) { + return false; ++ } + +- // Check the path after the drive letter. +- if (!EqualPath(actual_path, vol_length, path, 2)) ++ // Check the path after the volume matches. ++ if (!EqualPath(actual_path, nt_vol.size(), path, vol_path_len)) { + return false; ++ } + + return true; + } + + // 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) { diff --git a/security/sandbox/chromium-shim/patches/after_update/arm64_set_LoaderThreads.patch b/security/sandbox/chromium-shim/patches/after_update/arm64_set_LoaderThreads.patch new file mode 100644 index 0000000000..4d1817db17 --- /dev/null +++ b/security/sandbox/chromium-shim/patches/after_update/arm64_set_LoaderThreads.patch @@ -0,0 +1,99 @@ +# HG changeset patch +# User Bob Owen <bobowencode@gmail.com> +# Date 1549645620 0 +# Fri Feb 08 17:07:00 2019 +0000 +# Node ID fb5e7c1090a7ddfde22fd2fb5f8a957ccc61fa64 +# 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/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 + bool rv = GetPathFromHandle(file, nt_path); + ::CloseHandle(file); + return rv; + } + + bool WriteProtectedChildMemory(HANDLE child_process, + void* address, + const void* buffer, +- size_t length) { ++ size_t length, ++ DWORD writeProtection) { + // First, remove the protections. + DWORD old_protection; +- if (!::VirtualProtectEx(child_process, address, length, PAGE_WRITECOPY, ++ if (!::VirtualProtectEx(child_process, address, length, writeProtection, + &old_protection)) + return false; + + SIZE_T written; + bool ok = + ::WriteProcessMemory(child_process, address, buffer, length, &written) && + (length == written); + +@@ -544,16 +545,40 @@ void* GetProcessBaseAddress(HANDLE proce + &bytes_read) || + (sizeof(magic) != bytes_read)) { + return nullptr; + } + + if (magic[0] != 'M' || magic[1] != 'Z') + return nullptr; + ++#if defined(_M_ARM64) ++ // Windows 10 on ARM64 has multi-threaded DLL loading that does not work with ++ // the sandbox. (On x86 this gets disabled by hook detection code that was not ++ // ported to ARM64). This overwrites the LoaderThreads value in the process ++ // parameters part of the PEB, if it is set to the default of 0 (which ++ // actually means it defaults to 4 loading threads). This is an undocumented ++ // 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); ++ const uint32_t loaderThreadsOffset = 0x40c; ++ uint32_t maxLoaderThreads = 0; ++ BOOL memoryRead = ::ReadProcessMemory( ++ process, processParameters + loaderThreadsOffset, &maxLoaderThreads, ++ sizeof(maxLoaderThreads), &bytes_read); ++ if (memoryRead && (sizeof(maxLoaderThreads) == bytes_read) && ++ (maxLoaderThreads == 0)) { ++ maxLoaderThreads = 1; ++ WriteProtectedChildMemory(process, processParameters + loaderThreadsOffset, ++ &maxLoaderThreads, sizeof(maxLoaderThreads), ++ PAGE_READWRITE); ++ } ++#endif ++ + 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; +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); + + // Writes |length| bytes from the provided |buffer| into the address space of + // |child_process|, at the specified |address|, preserving the original write + // protection attributes. Returns true on success. + bool WriteProtectedChildMemory(HANDLE child_process, + void* address, + const void* buffer, +- size_t length); ++ 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, diff --git a/security/sandbox/chromium-shim/patches/after_update/change_to_DCHECK_in_CloseHandleWrapper.patch b/security/sandbox/chromium-shim/patches/after_update/change_to_DCHECK_in_CloseHandleWrapper.patch new file mode 100644 index 0000000000..3d6bfaa54f --- /dev/null +++ b/security/sandbox/chromium-shim/patches/after_update/change_to_DCHECK_in_CloseHandleWrapper.patch @@ -0,0 +1,38 @@ +# HG changeset patch +# User Bob Owen <bobowencode@gmail.com> +# Date 1563194469 -3600 +# Mon Jul 15 13:41:09 2019 +0100 +# Node ID 6d4e1a08b36e4191bd5ba7a338965f42f09162a6 +# Parent 7d9b5d8c9b9b36b135237292785537fc13f40226 +Bug 1564899: Make CloseHandleWrapper CHECK a DCHECK on non-Nightly builds. r=handyman! + +This is because we are hitting it frequently during PolicyBase::OnJobEmpty and +currently we can't work out how this can happen. + +diff --git a/security/sandbox/chromium/base/win/scoped_handle_verifier.cc b/security/sandbox/chromium/base/win/scoped_handle_verifier.cc +--- a/security/sandbox/chromium/base/win/scoped_handle_verifier.cc ++++ b/security/sandbox/chromium/base/win/scoped_handle_verifier.cc +@@ -65,17 +65,23 @@ ScopedHandleVerifier* ScopedHandleVerifi + if (!g_active_verifier) + ScopedHandleVerifier::InstallVerifier(); + + return g_active_verifier; + } + + bool CloseHandleWrapper(HANDLE handle) { + if (!::CloseHandle(handle)) ++ // Making this DCHECK on non-Nighly as we are hitting this frequently, ++ // looks like we are closing handles twice somehow. See bug 1564899. ++#if defined(NIGHTLY_BUILD) + CHECK(false); // CloseHandle failed. ++#else ++ DCHECK(false); // CloseHandle failed. ++#endif + return true; + } + + // Assigns the g_active_verifier global within the GetLock() lock. + // If |existing_verifier| is non-null then |enabled| is ignored. + void ThreadSafeAssignOrCreateScopedHandleVerifier( + ScopedHandleVerifier* existing_verifier, + bool enabled) { diff --git a/security/sandbox/chromium-shim/patches/after_update/linux_32bit_arg_fixup.patch b/security/sandbox/chromium-shim/patches/after_update/linux_32bit_arg_fixup.patch new file mode 100644 index 0000000000..5cc66ad09b --- /dev/null +++ b/security/sandbox/chromium-shim/patches/after_update/linux_32bit_arg_fixup.patch @@ -0,0 +1,84 @@ +commit e0a00891b67ec162a17aa241a83b171b313de9fe +Author: Jed Davis <jld@mozilla.com> +Date: Mon Apr 18 18:00:10 2022 -0600 + + Make the sandbox fix up non-extended 32-bit types. + +diff --git a/security/sandbox/chromium/sandbox/linux/bpf_dsl/policy_compiler.cc b/security/sandbox/chromium/sandbox/linux/bpf_dsl/policy_compiler.cc +index 347304889eae4..b909fc37f6174 100644 +--- a/security/sandbox/chromium/sandbox/linux/bpf_dsl/policy_compiler.cc ++++ b/security/sandbox/chromium/sandbox/linux/bpf_dsl/policy_compiler.cc +@@ -19,6 +19,7 @@ + #include "sandbox/linux/bpf_dsl/policy.h" + #include "sandbox/linux/bpf_dsl/seccomp_macros.h" + #include "sandbox/linux/bpf_dsl/syscall_set.h" ++#include "sandbox/linux/seccomp-bpf/syscall.h" + #include "sandbox/linux/system_headers/linux_filter.h" + #include "sandbox/linux/system_headers/linux_seccomp.h" + #include "sandbox/linux/system_headers/linux_syscalls.h" +@@ -318,8 +319,7 @@ CodeGen::Node PolicyCompiler::MaskedEqualHalf(int argno, + // Special logic for sanity checking the upper 32-bits of 32-bit system + // call arguments. + +- // TODO(mdempsky): Compile Unexpected64bitArgument() just per program. +- CodeGen::Node invalid_64bit = Unexpected64bitArgument(); ++ CodeGen::Node invalid_64bit = Unexpected64bitArgument(argno); + + const uint32_t upper = SECCOMP_ARG_MSB_IDX(argno); + const uint32_t lower = SECCOMP_ARG_LSB_IDX(argno); +@@ -335,8 +335,13 @@ CodeGen::Node PolicyCompiler::MaskedEqualHalf(int argno, + BPF_JMP + BPF_JEQ + BPF_K, 0, passed, invalid_64bit)); + } + +- // On 64-bit platforms, the upper 32-bits may be 0 or ~0; but we only allow +- // ~0 if the sign bit of the lower 32-bits is set too: ++ // On 64-bit platforms, the ABI (at least on x86_64) allows any value ++ // for the upper half, but to avoid potential vulnerabilties if an ++ // argument is incorrectly tested as a 32-bit type, we require it to be ++ // either zero-extended or sign-extended. That is, the upper 32-bits ++ // may be 0 or ~0; but we only allow ~0 if the sign bit of the lower ++ // 32-bits is set too: ++ // + // LDW [upper] + // JEQ 0, passed, (next) + // JEQ ~0, (next), invalid +@@ -424,8 +429,18 @@ CodeGen::Node PolicyCompiler::MaskedEqualHalf(int argno, + BPF_JMP + BPF_JEQ + BPF_K, value, passed, failed))); + } + +-CodeGen::Node PolicyCompiler::Unexpected64bitArgument() { +- return CompileResult(panic_func_("Unexpected 64bit argument detected")); ++CodeGen::Node PolicyCompiler::Unexpected64bitArgument(int argno) { ++ // This situation is unlikely, but possible. Return to userspace, ++ // zero-extend the problematic argument, and re-issue the syscall. ++ return CompileResult(bpf_dsl::Trap( ++ [](const arch_seccomp_data& args_ref, void* aux) -> intptr_t { ++ arch_seccomp_data args = args_ref; ++ int argno = (int)(intptr_t)aux; ++ args.args[argno] &= 0xFFFFFFFF; ++ return Syscall::Call(args.nr, args.args[0], args.args[1], args.args[2], ++ args.args[3], args.args[4], args.args[5]); ++ }, ++ (void*)(intptr_t)argno)); + } + + CodeGen::Node PolicyCompiler::Return(uint32_t ret) { +diff --git a/security/sandbox/chromium/sandbox/linux/bpf_dsl/policy_compiler.h b/security/sandbox/chromium/sandbox/linux/bpf_dsl/policy_compiler.h +index 48b1d780d956f..2acf878474a7d 100644 +--- a/security/sandbox/chromium/sandbox/linux/bpf_dsl/policy_compiler.h ++++ b/security/sandbox/chromium/sandbox/linux/bpf_dsl/policy_compiler.h +@@ -132,9 +132,11 @@ class SANDBOX_EXPORT PolicyCompiler { + CodeGen::Node passed, + CodeGen::Node failed); + +- // Returns the fatal CodeGen::Node that is used to indicate that somebody +- // attempted to pass a 64bit value in a 32bit system call argument. +- CodeGen::Node Unexpected64bitArgument(); ++ // Returns the CodeGen::Node that is used to handle the case where a ++ // system call argument was expected to be a 32-bit type, but the ++ // value in the 64-bit register doesn't correspond to a ++ // zero-extended or sign-extended 32-bit value. ++ CodeGen::Node Unexpected64bitArgument(int argno); + + const Policy* policy_; + TrapRegistry* registry_; diff --git a/security/sandbox/chromium-shim/patches/after_update/move_shared_memory_duplication_after_initialization.patch b/security/sandbox/chromium-shim/patches/after_update/move_shared_memory_duplication_after_initialization.patch new file mode 100644 index 0000000000..f8250b788d --- /dev/null +++ b/security/sandbox/chromium-shim/patches/after_update/move_shared_memory_duplication_after_initialization.patch @@ -0,0 +1,94 @@ +# 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()) diff --git a/security/sandbox/chromium-shim/patches/after_update/patch_order.txt b/security/sandbox/chromium-shim/patches/after_update/patch_order.txt new file mode 100644 index 0000000000..4266bee9c0 --- /dev/null +++ b/security/sandbox/chromium-shim/patches/after_update/patch_order.txt @@ -0,0 +1,8 @@ +add_interception_logging.patch +allow_rules_for_network_drive_and_non_file_devices.patch +add_WOW64_flags_to_allowed_registry_read_flags.patch +arm64_set_LoaderThreads.patch +change_to_DCHECK_in_CloseHandleWrapper.patch +move_shared_memory_duplication_after_initialization.patch +allow_ntpath_in_SignedPolicy_GenerateRules.patch +linux_32bit_arg_fixup.patch diff --git a/security/sandbox/chromium-shim/patches/with_update/aarch64_control_flow_guard.patch b/security/sandbox/chromium-shim/patches/with_update/aarch64_control_flow_guard.patch new file mode 100644 index 0000000000..5a5c2f95de --- /dev/null +++ b/security/sandbox/chromium-shim/patches/with_update/aarch64_control_flow_guard.patch @@ -0,0 +1,65 @@ +# HG changeset patch +# User David Major <dmajor@mozilla.com> +# Date 1560264749 -3600 +# Tue Jun 11 15:52:29 2019 +0100 +# Node ID 6acdba6bd34e773d5e2d6a8461e3679a33340f77 +# Parent a0adb2e7f668ed430948ae1ffaa42ec011ffde50 +Bug 1523526: Don't allow CFG on old releases of Windows for arm64 + +There's a bug in ole32.dll on arm64 versions of Windows prior to 1809, that crashes our content processes if we enable CFG. We've reported the issue, but even if it gets fixed, we can't assume users will have the update. + +This patch uses process mitigation policy flags to disable CFG on arm64 before 1809. Based on testing, we only need to do this in the sandbox for child processes, and it's not strictly necessary for the launcher stub to set the flag on the main process. But I've included that anyway as a guard against some yet-undiscovered scenario that might hit the issue and make the browser unusable. + +The effects of this patch won't be visible until we actually enable CFG in a subsequent landing. + +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 + + // Mitigations >= 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; + } ++ ++ if (flags & MITIGATION_CONTROL_FLOW_GUARD_DISABLE) { ++ *policy_value_1 |= ++ PROCESS_CREATION_MITIGATION_POLICY_CONTROL_FLOW_GUARD_ALWAYS_OFF; ++ } + } + + // Mitigations >= 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 + const MitigationFlags MITIGATION_IMAGE_LOAD_PREFER_SYS32 = 0x00100000; + + // Prevents hyperthreads from interfering with indirect branch predictions. + // (SPECTRE Variant 2 mitigation.) Corresponds to + // PROCESS_CREATION_MITIGATION_POLICY2_RESTRICT_INDIRECT_BRANCH_PREDICTION_ALWAYS_ON. + const MitigationFlags MITIGATION_RESTRICT_INDIRECT_BRANCH_PREDICTION = + 0x00200000; + ++// Begin Mozilla-added flags. ++// Working down from the high bit to avoid conflict with new upstream flags. ++ ++// Disable Control Flow Guard. This may seem more like an anti-mitigation, but ++// this flag allows code to make targeted changes to CFG to avoid bugs, while ++// leaving it enabled in the common case. Corresponds to ++// PROCESS_CREATION_MITIGATION_POLICY_CONTROL_FLOW_GUARD_ALWAYS_ON. ++const MitigationFlags MITIGATION_CONTROL_FLOW_GUARD_DISABLE = 0x80000000; ++ + } // namespace sandbox + + #endif // SANDBOX_SRC_SECURITY_LEVEL_H_ diff --git a/security/sandbox/chromium-shim/patches/with_update/add_CET_STRICT_MODE.patch b/security/sandbox/chromium-shim/patches/with_update/add_CET_STRICT_MODE.patch new file mode 100644 index 0000000000..fc0dee5f36 --- /dev/null +++ b/security/sandbox/chromium-shim/patches/with_update/add_CET_STRICT_MODE.patch @@ -0,0 +1,94 @@ +# HG changeset patch +# User Bob Owen <bobowencode@gmail.com> +# Date 1611849321 0 +# Thu Jan 28 15:55:21 2021 +0000 +# Node ID c9195d88e6c67ef2c23c12e307bc16b94d696f50 +# Parent 37557864a6845bb8068904e44e8a7dd16746d211 +Bug 1716024 p1: Add MITIGATION_CET_COMPAT_MODE to chromium sandbox code. r=handyman! + +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 +@@ -80,16 +80,37 @@ bool IsRunning32bitEmulatedOnArm64() { + if (!retval) + return false; + if (native_machine == IMAGE_FILE_MACHINE_ARM64) + return true; + #endif // defined(ARCH_CPU_X86) + return false; + } + ++// Returns true if user-mode Hardware-enforced Stack Protection is available for ++// the Win32 environment. ++bool IsUserCetWin32Available() { ++ static bool cetAvailable = []() -> bool { ++ using IsUserCetAvailableInEnvironmentFunction = ++ decltype(&IsUserCetAvailableInEnvironment); ++ ++ IsUserCetAvailableInEnvironmentFunction is_user_cet_available = ++ reinterpret_cast<IsUserCetAvailableInEnvironmentFunction>( ++ ::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), ++ "IsUserCetAvailableInEnvironment")); ++ if (!is_user_cet_available) { ++ return false; ++ } ++ ++ return is_user_cet_available(USER_CET_ENVIRONMENT_WIN32_PROCESS); ++ }(); ++ ++ return cetAvailable; ++} ++ + } // namespace + + namespace sandbox { + + bool ApplyProcessMitigationsToCurrentProcess(MitigationFlags flags) { + if (!CanSetProcessMitigationsPostStartup(flags)) + return false; + +@@ -487,16 +508,25 @@ void ConvertProcessMitigationsToPolicy(M + // the underlying hardware does not support the implementation. + // Windows just does its best under the hood for the given hardware. + if (flags & MITIGATION_RESTRICT_INDIRECT_BRANCH_PREDICTION) { + *policy_value_2 |= + PROCESS_CREATION_MITIGATION_POLICY2_RESTRICT_INDIRECT_BRANCH_PREDICTION_ALWAYS_ON; + } + } + ++ // Mitigations >= Win10 20H1 ++ //---------------------------------------------------------------------------- ++ if (version >= base::win::Version::WIN10_20H1) { ++ if (flags & MITIGATION_CET_COMPAT_MODE && IsUserCetWin32Available()) { ++ *policy_value_2 |= ++ PROCESS_CREATION_MITIGATION_POLICY2_CET_USER_SHADOW_STACKS_ALWAYS_ON; ++ } ++ } ++ + // When done setting policy flags, sanity check supported policies on this + // machine, and then update |size|. + + const ULONG64* supported = GetSupportedMitigations(); + + *policy_value_1 = *policy_value_1 & supported[0]; + *policy_value_2 = *policy_value_2 & supported[1]; + +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 +@@ -286,11 +286,15 @@ const MitigationFlags MITIGATION_RESTRIC + // Working down from the high bit to avoid conflict with new upstream flags. + + // Disable Control Flow Guard. This may seem more like an anti-mitigation, but + // this flag allows code to make targeted changes to CFG to avoid bugs, while + // leaving it enabled in the common case. Corresponds to + // PROCESS_CREATION_MITIGATION_POLICY_CONTROL_FLOW_GUARD_ALWAYS_ON. + const MitigationFlags MITIGATION_CONTROL_FLOW_GUARD_DISABLE = 0x80000000; + ++// This enables CET User Shadow Stack for compatible modules and corresponds to ++// PROCESS_CREATION_MITIGATION_POLICY2_CET_USER_SHADOW_STACKS_ALWAYS_ON. ++const MitigationFlags MITIGATION_CET_COMPAT_MODE = 0x40000000; ++ + } // namespace sandbox + + #endif // SANDBOX_SRC_SECURITY_LEVEL_H_ diff --git a/security/sandbox/chromium-shim/patches/with_update/add_loongarch_defines.patch b/security/sandbox/chromium-shim/patches/with_update/add_loongarch_defines.patch new file mode 100644 index 0000000000..0dcc969be3 --- /dev/null +++ b/security/sandbox/chromium-shim/patches/with_update/add_loongarch_defines.patch @@ -0,0 +1,32 @@ +# HG changeset patch +# User Zhao Jiazhong <zhaojiazhong-hf@loongson.cn> +# Date 1684413793 -28800 +# Thu May 18 20:43:13 2023 +0800 +# Node ID c1e4ab25fefb3a54ae35ae82b7718bf71f992a36 +# Parent e974af195c9886356987dd99ba40ab25692c134c +Bug 1833852 - Add loongarch defines to build/build_config.h. r=bobowen + +Fix firefox for loongarch64 building issue. + +Differential Revision: https://phabricator.services.mozilla.com/D178435 + +diff --git a/security/sandbox/chromium/build/build_config.h b/security/sandbox/chromium/build/build_config.h +--- a/security/sandbox/chromium/build/build_config.h ++++ b/security/sandbox/chromium/build/build_config.h +@@ -170,6 +170,16 @@ + #define ARCH_CPU_RISCV64 1 + #define ARCH_CPU_64_BITS 1 + #define ARCH_CPU_LITTLE_ENDIAN 1 ++#elif defined(__loongarch__) ++#define ARCH_CPU_LOONGARCH_FAMILY 1 ++#define ARCH_CPU_LITTLE_ENDIAN 1 ++#if __loongarch_grlen == 64 ++#define ARCH_CPU_LOONGARCH64 1 ++#define ARCH_CPU_64_BITS 1 ++#else ++#define ARCH_CPU_LOONGARCH32 1 ++#define ARCH_CPU_32_BITS 1 ++#endif + #else + #error Please add support for your architecture in build/build_config.h + #endif diff --git a/security/sandbox/chromium-shim/patches/with_update/add_option_to_not_use_restricting_sids.patch b/security/sandbox/chromium-shim/patches/with_update/add_option_to_not_use_restricting_sids.patch new file mode 100644 index 0000000000..d215715152 --- /dev/null +++ b/security/sandbox/chromium-shim/patches/with_update/add_option_to_not_use_restricting_sids.patch @@ -0,0 +1,305 @@ +# HG changeset patch +# User Bob Owen <bobowencode@gmail.com> +# Date 1499762660 -3600 +# Tue Jul 11 09:44:20 2017 +0100 +# Node ID 4fb5bb81a2626a6262813bb556e2e059c2323562 +# Parent 45f3ef4037e040c820c0dd8eec6cff9d0745ae41 +Bug 1366701 - Add option to Windows chromium sandbox policy to not use restricting SIDs. r=jimm + +This originally landed in changeset: +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 + + } // namespace + + DWORD CreateRestrictedToken(HANDLE effective_token, + TokenLevel security_level, + IntegrityLevel integrity_level, + TokenType token_type, + bool lockdown_default_dacl, ++ bool use_restricting_sids, + base::win::ScopedHandle* token) { + RestrictedToken restricted_token; + restricted_token.Init(effective_token); + if (lockdown_default_dacl) + restricted_token.SetLockdownDefaultDacl(); + + std::vector<std::wstring> privilege_exceptions; + std::vector<Sid> sid_exceptions; +@@ -73,19 +74,22 @@ DWORD CreateRestrictedToken(HANDLE effec + deny_sids = false; + remove_privileges = false; + break; + } + case USER_RESTRICTED_SAME_ACCESS: { + deny_sids = false; + remove_privileges = false; + +- unsigned err_code = restricted_token.AddRestrictingSidAllSids(); +- if (ERROR_SUCCESS != err_code) +- return err_code; ++ if (use_restricting_sids) { ++ unsigned err_code = restricted_token.AddRestrictingSidAllSids(); ++ if (ERROR_SUCCESS != err_code) { ++ return err_code; ++ } ++ } + + break; + } + case USER_NON_ADMIN: { + sid_exceptions.push_back(WinBuiltinUsersSid); + sid_exceptions.push_back(WinWorldSid); + sid_exceptions.push_back(WinInteractiveSid); + sid_exceptions.push_back(WinAuthenticatedUserSid); +@@ -108,64 +112,74 @@ DWORD CreateRestrictedToken(HANDLE effec + break; + } + case USER_RESTRICTED_NON_ADMIN: { + sid_exceptions.push_back(WinBuiltinUsersSid); + sid_exceptions.push_back(WinWorldSid); + sid_exceptions.push_back(WinInteractiveSid); + sid_exceptions.push_back(WinAuthenticatedUserSid); + privilege_exceptions.push_back(SE_CHANGE_NOTIFY_NAME); +- restricted_token.AddRestrictingSid(WinBuiltinUsersSid); +- restricted_token.AddRestrictingSid(WinWorldSid); +- restricted_token.AddRestrictingSid(WinInteractiveSid); +- restricted_token.AddRestrictingSid(WinAuthenticatedUserSid); +- restricted_token.AddRestrictingSid(WinRestrictedCodeSid); +- restricted_token.AddRestrictingSidCurrentUser(); +- restricted_token.AddRestrictingSidLogonSession(); ++ if (use_restricting_sids) { ++ restricted_token.AddRestrictingSid(WinBuiltinUsersSid); ++ restricted_token.AddRestrictingSid(WinWorldSid); ++ restricted_token.AddRestrictingSid(WinInteractiveSid); ++ restricted_token.AddRestrictingSid(WinAuthenticatedUserSid); ++ restricted_token.AddRestrictingSid(WinRestrictedCodeSid); ++ restricted_token.AddRestrictingSidCurrentUser(); ++ restricted_token.AddRestrictingSidLogonSession(); ++ } + break; + } + case USER_INTERACTIVE: { + sid_exceptions.push_back(WinBuiltinUsersSid); + sid_exceptions.push_back(WinWorldSid); + sid_exceptions.push_back(WinInteractiveSid); + sid_exceptions.push_back(WinAuthenticatedUserSid); + privilege_exceptions.push_back(SE_CHANGE_NOTIFY_NAME); +- restricted_token.AddRestrictingSid(WinBuiltinUsersSid); +- restricted_token.AddRestrictingSid(WinWorldSid); +- restricted_token.AddRestrictingSid(WinRestrictedCodeSid); +- restricted_token.AddRestrictingSidCurrentUser(); +- restricted_token.AddRestrictingSidLogonSession(); ++ if (use_restricting_sids) { ++ restricted_token.AddRestrictingSid(WinBuiltinUsersSid); ++ restricted_token.AddRestrictingSid(WinWorldSid); ++ restricted_token.AddRestrictingSid(WinRestrictedCodeSid); ++ restricted_token.AddRestrictingSidCurrentUser(); ++ restricted_token.AddRestrictingSidLogonSession(); ++ } + 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); +- restricted_token.AddRestrictingSid(WinBuiltinUsersSid); +- restricted_token.AddRestrictingSid(WinWorldSid); +- restricted_token.AddRestrictingSid(WinRestrictedCodeSid); ++ if (use_restricting_sids) { ++ restricted_token.AddRestrictingSid(WinBuiltinUsersSid); ++ restricted_token.AddRestrictingSid(WinWorldSid); ++ restricted_token.AddRestrictingSid(WinRestrictedCodeSid); + +- // 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(); ++ // 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(); ++ } + break; + } + case USER_RESTRICTED: { + privilege_exceptions.push_back(SE_CHANGE_NOTIFY_NAME); + restricted_token.AddUserSidForDenyOnly(); +- restricted_token.AddRestrictingSid(WinRestrictedCodeSid); ++ if (use_restricting_sids) { ++ restricted_token.AddRestrictingSid(WinRestrictedCodeSid); ++ } + break; + } + case USER_LOCKDOWN: { + restricted_token.AddUserSidForDenyOnly(); +- restricted_token.AddRestrictingSid(WinNullSid); ++ if (use_restricting_sids) { ++ restricted_token.AddRestrictingSid(WinNullSid); ++ } + break; + } + default: { return ERROR_BAD_ARGUMENTS; } + } + + DWORD err_code = ERROR_SUCCESS; + if (deny_sids) { + err_code = restricted_token.AddAllSidsForDenyOnly(&sid_exceptions); +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, ++ 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 +@@ -101,16 +101,21 @@ class TargetPolicy { + virtual ResultCode SetTokenLevel(TokenLevel initial, TokenLevel lockdown) = 0; + + // Returns the initial token level. + virtual TokenLevel GetInitialTokenLevel() const = 0; + + // Returns the lockdown token level. + virtual TokenLevel GetLockdownTokenLevel() const = 0; + ++ // Sets that we should not use restricting SIDs in the access tokens. We need ++ // to do this in some circumstances even though it weakens the sandbox. ++ // The default is to use them. ++ virtual void SetDoNotUseRestrictingSIDs() = 0; ++ + // Sets the security level of the Job Object to which the target process will + // belong. This setting is permanent and cannot be changed once the target + // process is spawned. The job controls the global security settings which + // can not be specified in the token security profile. + // job_level: the security level for the job. See the explanation of each + // level in the JobLevel definition. + // ui_exceptions: specify what specific rights that are disabled in the + // chosen job_level that need to be granted. Use this parameter to avoid +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 + TokenLevel PolicyBase::GetInitialTokenLevel() const { + return initial_level_; + } + + TokenLevel PolicyBase::GetLockdownTokenLevel() const { + return lockdown_level_; + } + ++void PolicyBase::SetDoNotUseRestrictingSIDs() { ++ use_restricting_sids_ = false; ++} ++ + ResultCode PolicyBase::SetJobLevel(JobLevel job_level, uint32_t ui_exceptions) { + if (memory_limit_ && job_level == JOB_NONE) { + return SBOX_ERROR_BAD_PARAMS; + } + job_level_ = job_level; + ui_exceptions_ = ui_exceptions; + return SBOX_ALL_OK; + } +@@ -413,17 +417,18 @@ ResultCode PolicyBase::MakeJobObject(bas + + ResultCode PolicyBase::MakeTokens(base::win::ScopedHandle* initial, + base::win::ScopedHandle* lockdown, + base::win::ScopedHandle* lowbox) { + // 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_, lockdown); ++ PRIMARY, lockdown_default_dacl_, ++ 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) { +@@ -482,17 +487,18 @@ ResultCode PolicyBase::MakeTokens(base:: + } + } + + // 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_, initial); ++ IMPERSONATION, lockdown_default_dacl_, ++ 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 +@@ -41,16 +41,17 @@ class PolicyBase final : public TargetPo + PolicyBase(); + + // TargetPolicy: + void AddRef() override; + void Release() override; + ResultCode SetTokenLevel(TokenLevel initial, TokenLevel lockdown) override; + TokenLevel GetInitialTokenLevel() const override; + TokenLevel GetLockdownTokenLevel() const override; ++ void SetDoNotUseRestrictingSIDs() final; + ResultCode SetJobLevel(JobLevel job_level, uint32_t ui_exceptions) override; + JobLevel GetJobLevel() const override; + ResultCode SetJobMemoryLimit(size_t memory_limit) override; + ResultCode SetAlternateDesktop(bool alternate_winstation) override; + std::wstring 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 + // The policy takes ownership of them. + typedef std::list<TargetProcess*> TargetSet; + TargetSet targets_; + // Standard object-lifetime reference counter. + volatile LONG ref_count; + // The user-defined global policy settings. + TokenLevel lockdown_level_; + TokenLevel initial_level_; ++ bool use_restricting_sids_ = true; + JobLevel job_level_; + uint32_t ui_exceptions_; + size_t memory_limit_; + bool use_alternate_desktop_; + bool use_alternate_winstation_; + // Helps the file system policy initialization. + bool file_system_init_; + bool relaxed_interceptions_; diff --git a/security/sandbox/chromium-shim/patches/with_update/add_return_in_QueryCancellationTraitsForNonCancellables_to_satisfy_build.patch b/security/sandbox/chromium-shim/patches/with_update/add_return_in_QueryCancellationTraitsForNonCancellables_to_satisfy_build.patch new file mode 100644 index 0000000000..c5ee583b01 --- /dev/null +++ b/security/sandbox/chromium-shim/patches/with_update/add_return_in_QueryCancellationTraitsForNonCancellables_to_satisfy_build.patch @@ -0,0 +1,29 @@ +# HG changeset patch +# User Bob Owen <bobowencode@gmail.com> +# Date 1560260462 -3600 +# Tue Jun 11 14:41:02 2019 +0100 +# Node ID cb6cbf2c60077e833f472c82c1f437a794ac5266 +# Parent 71ac3df6aadbce233034b169646b66160c5944dc +Bug 1552160: Add return after NOTREACHED() in QueryCancellationTraitsForNonCancellables to prevent build error. r=jld + +diff --git a/security/sandbox/chromium/base/callback_internal.cc b/security/sandbox/chromium/base/callback_internal.cc +--- a/security/sandbox/chromium/base/callback_internal.cc ++++ b/security/sandbox/chromium/base/callback_internal.cc +@@ -16,16 +16,17 @@ bool QueryCancellationTraitsForNonCancel + BindStateBase::CancellationQueryMode mode) { + switch (mode) { + case BindStateBase::IS_CANCELLED: + return false; + case BindStateBase::MAYBE_VALID: + return true; + } + NOTREACHED(); ++ return false; + } + + } // namespace + + void BindStateBaseRefCountTraits::Destruct(const BindStateBase* bind_state) { + bind_state->destructor_(bind_state); + } + diff --git a/security/sandbox/chromium-shim/patches/with_update/add_support_for_random_restricted_SID.patch b/security/sandbox/chromium-shim/patches/with_update/add_support_for_random_restricted_SID.patch new file mode 100644 index 0000000000..39f6b2538d --- /dev/null +++ b/security/sandbox/chromium-shim/patches/with_update/add_support_for_random_restricted_SID.patch @@ -0,0 +1,461 @@ +# 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. diff --git a/security/sandbox/chromium-shim/patches/with_update/allow_env_changes.patch b/security/sandbox/chromium-shim/patches/with_update/allow_env_changes.patch new file mode 100644 index 0000000000..99fe5e99bc --- /dev/null +++ b/security/sandbox/chromium-shim/patches/with_update/allow_env_changes.patch @@ -0,0 +1,217 @@ +# HG changeset patch +# User Gian-Carlo Pascutto <gcp@mozilla.com> +# Date 1515402436 -3600 +# Mon Jan 08 10:07:16 2018 +0100 +# Node ID 205e7ae2a6bc5ed1cdd1a982a12d99f52ce33258 +# Parent a89071894b4904a0130139a03147d4a6cb5c3bfc +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 + NOTREACHED(); + return 0; + } + + // SpawnTarget does all the interesting sandbox setup and creates the target + // process inside the sandbox. + ResultCode BrokerServicesBase::SpawnTarget(const wchar_t* exe_path, + const wchar_t* command_line, ++ base::EnvironmentMap& env_map, + scoped_refptr<TargetPolicy> policy, + ResultCode* last_warning, + DWORD* last_error, + PROCESS_INFORMATION* target_info) { + if (!exe_path) + return SBOX_ERROR_BAD_PARAMS; + + if (!policy) +@@ -609,17 +610,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( + std::move(initial_token), std::move(lockdown_token), job.Get(), + thread_pool_.get(), + profile ? profile->GetImpersonationCapabilities() : std::vector<Sid>()); + + result = target->Create(exe_path, command_line, inherit_handles, startup_info, +- &process_info, last_error); ++ &process_info, env_map, last_error); + + if (result != SBOX_ALL_OK) { + SpawnCleanup(target); + return result; + } + + if (lowbox_token.IsValid()) { + *last_warning = target->AssignLowBoxToken(lowbox_token); +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 +@@ -7,16 +7,17 @@ + + #include <list> + #include <map> + #include <memory> + #include <set> + #include <utility> + + #include "base/compiler_specific.h" ++#include "base/environment.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" + #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 + + ~BrokerServicesBase(); + + // BrokerServices interface. + ResultCode Init() override; + scoped_refptr<TargetPolicy> CreatePolicy() override; + ResultCode SpawnTarget(const wchar_t* exe_path, + const wchar_t* command_line, ++ base::EnvironmentMap& env_map, + scoped_refptr<TargetPolicy> policy, + ResultCode* last_warning, + DWORD* last_error, + 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 +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 { + // 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 + // responsible for closing the handles returned in this structure. + // Returns: + // ALL_OK if successful. All other return values imply failure. + virtual ResultCode SpawnTarget(const wchar_t* exe_path, + const wchar_t* command_line, ++ base::EnvironmentMap& env_map, + scoped_refptr<TargetPolicy> policy, + ResultCode* last_warning, + DWORD* last_error, + PROCESS_INFORMATION* target) = 0; + + // This call blocks (waits) for all the targets to terminate. + // Returns: + // ALL_OK if successful. All other return values imply failure. +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() { + // Creates the target (child) process suspended and assigns it to the job + // object. + ResultCode TargetProcess::Create( + const wchar_t* exe_path, + const wchar_t* command_line, + bool inherit_handles, + const base::win::StartupInformation& startup_info, + base::win::ScopedProcessInformation* target_info, ++ base::EnvironmentMap& env_changes, + DWORD* win_error) { + exe_name_.reset(_wcsdup(exe_path)); + + // the command line needs to be writable by CreateProcess(). + std::unique_ptr<wchar_t, base::FreeDeleter> cmd_line(_wcsdup(command_line)); + + // Start the target process suspended. + DWORD flags = +@@ -156,22 +158,29 @@ ResultCode TargetProcess::Create( + flags |= EXTENDED_STARTUPINFO_PRESENT; + + 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; + } + ++ LPTCH original_environment = GetEnvironmentStrings(); ++ base::NativeEnvironmentString new_environment = ++ base::internal::AlterEnvironment(original_environment, env_changes); ++ // Ignore return value? What can we do? ++ FreeEnvironmentStrings(original_environment); ++ LPVOID new_env_ptr = (void*)new_environment.data(); ++ + PROCESS_INFORMATION temp_process_info = {}; + if (!::CreateProcessAsUserW(lockdown_token_.Get(), exe_path, cmd_line.get(), + nullptr, // No security attribute. + nullptr, // No thread attribute. + inherit_handles, flags, +- nullptr, // Use the environment of the caller. ++ new_env_ptr, + nullptr, // Use current directory of the caller. + startup_info.startup_info(), + &temp_process_info)) { + *win_error = ::GetLastError(); + return SBOX_ERROR_CREATE_PROCESS; + } + base::win::ScopedProcessInformation process_info(temp_process_info); + +diff --git a/security/sandbox/chromium/sandbox/win/src/target_process.h b/security/sandbox/chromium/sandbox/win/src/target_process.h +--- a/security/sandbox/chromium/sandbox/win/src/target_process.h ++++ b/security/sandbox/chromium/sandbox/win/src/target_process.h +@@ -9,16 +9,17 @@ + + #include <stddef.h> + #include <stdint.h> + + #include <memory> + #include <vector> + + #include "base/macros.h" ++#include "base/environment.h" + #include "base/memory/free_deleter.h" + #include "base/win/scoped_handle.h" + #include "base/win/scoped_process_information.h" + #include "sandbox/win/src/crosscall_server.h" + #include "sandbox/win/src/sandbox_types.h" + + namespace base { + namespace win { +@@ -54,16 +55,17 @@ class TargetProcess { + void Release() {} + + // Creates the new target process. The process is created suspended. + ResultCode Create(const wchar_t* exe_path, + const wchar_t* command_line, + bool inherit_handles, + const base::win::StartupInformation& startup_info, + base::win::ScopedProcessInformation* target_info, ++ base::EnvironmentMap& env_map, + DWORD* win_error); + + // Assign a new lowbox token to the process post creation. The process + // must still be in its initial suspended state, however this still + // might fail in the presence of third-party software. + ResultCode AssignLowBoxToken(const base::win::ScopedHandle& token); + + // Destroys the target process. diff --git a/security/sandbox/chromium-shim/patches/with_update/allow_read_only_all_paths_rule.patch b/security/sandbox/chromium-shim/patches/with_update/allow_read_only_all_paths_rule.patch new file mode 100644 index 0000000000..b147e5f9fe --- /dev/null +++ b/security/sandbox/chromium-shim/patches/with_update/allow_read_only_all_paths_rule.patch @@ -0,0 +1,142 @@ +# HG changeset patch +# User Bob Owen <bobowencode@gmail.com> +# Date 1490686576 -3600 +# Tue Mar 28 08:36:16 2017 +0100 +# Node ID 698d43688097e19ac64db71a094905035cac4891 +# 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. + +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 +@@ -11,16 +11,20 @@ + #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" + ++// This status occurs when trying to access a network share on the machine from ++// which it is shared. ++#define STATUS_NETWORK_OPEN_RESTRICTION ((NTSTATUS)0xC0000201L) ++ + namespace sandbox { + + NTSTATUS WINAPI TargetNtCreateFile(NtCreateFileFunction orig_CreateFile, + PHANDLE file, + ACCESS_MASK desired_access, + POBJECT_ATTRIBUTES object_attributes, + PIO_STATUS_BLOCK io_status, + PLARGE_INTEGER allocation_size, +@@ -29,17 +33,18 @@ NTSTATUS WINAPI TargetNtCreateFile(NtCre + ULONG disposition, + ULONG options, + PVOID ea_buffer, + ULONG ea_length) { + // Check if the process can open it first. + NTSTATUS status = orig_CreateFile( + file, desired_access, object_attributes, io_status, allocation_size, + file_attributes, sharing, disposition, options, ea_buffer, ea_length); +- if (STATUS_ACCESS_DENIED != status) ++ if (STATUS_ACCESS_DENIED != status && ++ STATUS_NETWORK_OPEN_RESTRICTION != status) + return status; + + // We don't trust that the IPC can work this early. + if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) + return status; + + do { + if (!ValidParameter(file, sizeof(HANDLE), WRITE)) +@@ -106,17 +111,18 @@ NTSTATUS WINAPI TargetNtOpenFile(NtOpenF + ACCESS_MASK desired_access, + POBJECT_ATTRIBUTES object_attributes, + PIO_STATUS_BLOCK io_status, + ULONG sharing, + ULONG options) { + // Check if the process can open it first. + NTSTATUS status = orig_OpenFile(file, desired_access, object_attributes, + io_status, sharing, options); +- if (STATUS_ACCESS_DENIED != status) ++ if (STATUS_ACCESS_DENIED != status && ++ STATUS_NETWORK_OPEN_RESTRICTION != status) + return status; + + // We don't trust that the IPC can work this early. + if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) + return status; + + do { + if (!ValidParameter(file, sizeof(HANDLE), WRITE)) +@@ -176,17 +182,18 @@ NTSTATUS WINAPI TargetNtOpenFile(NtOpenF + } + + NTSTATUS WINAPI + TargetNtQueryAttributesFile(NtQueryAttributesFileFunction orig_QueryAttributes, + POBJECT_ATTRIBUTES object_attributes, + PFILE_BASIC_INFORMATION file_attributes) { + // Check if the process can query it first. + NTSTATUS status = orig_QueryAttributes(object_attributes, file_attributes); +- if (STATUS_ACCESS_DENIED != status) ++ if (STATUS_ACCESS_DENIED != status && ++ STATUS_NETWORK_OPEN_RESTRICTION != status) + return status; + + // We don't trust that the IPC can work this early. + if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) + return status; + + do { + if (!ValidParameter(file_attributes, sizeof(FILE_BASIC_INFORMATION), WRITE)) +@@ -232,17 +239,18 @@ TargetNtQueryAttributesFile(NtQueryAttri + + NTSTATUS WINAPI TargetNtQueryFullAttributesFile( + NtQueryFullAttributesFileFunction orig_QueryFullAttributes, + POBJECT_ATTRIBUTES object_attributes, + PFILE_NETWORK_OPEN_INFORMATION file_attributes) { + // Check if the process can query it first. + NTSTATUS status = + orig_QueryFullAttributes(object_attributes, file_attributes); +- if (STATUS_ACCESS_DENIED != status) ++ if (STATUS_ACCESS_DENIED != status && ++ STATUS_NETWORK_OPEN_RESTRICTION != status) + return status; + + // We don't trust that the IPC can work this early. + if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled()) + return status; + + do { + if (!ValidParameter(file_attributes, sizeof(FILE_NETWORK_OPEN_INFORMATION), +diff --git a/security/sandbox/chromium/sandbox/win/src/filesystem_policy.cc b/security/sandbox/chromium/sandbox/win/src/filesystem_policy.cc +--- a/security/sandbox/chromium/sandbox/win/src/filesystem_policy.cc ++++ b/security/sandbox/chromium/sandbox/win/src/filesystem_policy.cc +@@ -77,17 +77,21 @@ namespace sandbox { + bool FileSystemPolicy::GenerateRules(const wchar_t* name, + TargetPolicy::Semantics semantics, + LowLevelPolicy* policy) { + std::wstring mod_name(name); + if (mod_name.empty()) { + return false; + } + +- if (!PreProcessName(&mod_name)) { ++ // Don't pre-process the path name and check for reparse points if it is the ++ // special case of allowing read access to all paths. ++ if (!(semantics == TargetPolicy::FILES_ALLOW_READONLY ++ && mod_name.compare(L"*") == 0) ++ && !PreProcessName(&mod_name)) { + // The path to be added might contain a reparse point. + NOTREACHED(); + return false; + } + + // TODO(cpu) bug 32224: This prefix add is a hack because we don't have the + // infrastructure to normalize names. In any case we need to escape the + // question marks. diff --git a/security/sandbox/chromium-shim/patches/with_update/allow_reparse_points.patch b/security/sandbox/chromium-shim/patches/with_update/allow_reparse_points.patch new file mode 100644 index 0000000000..e3645d2cd7 --- /dev/null +++ b/security/sandbox/chromium-shim/patches/with_update/allow_reparse_points.patch @@ -0,0 +1,186 @@ +# HG changeset patch +# User Bob Owen <bobowencode@gmail.com> +# Date 1631294898 -3600 +# Fri Sep 10 18:28:18 2021 +0100 +# Node ID adbc9b3051ab7f3c9360f65fe0fc26bd9d9dd499 +# Parent 004b5bea4e78db7ecd665173ce4cf6aa0a1af199 +Bug 1695556 p1: Allow reparse points in chromium sandbox code. + +Differential Revision: https://phabricator.services.mozilla.com/D135692 + +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 +@@ -87,17 +87,16 @@ bool FilesystemDispatcher::NtCreateFile( + std::wstring* name, + uint32_t attributes, + uint32_t desired_access, + uint32_t file_attributes, + uint32_t share_access, + uint32_t create_disposition, + uint32_t create_options) { + if (!PreProcessName(name)) { +- // The path requested might contain a reparse point. + ipc->return_info.nt_status = STATUS_ACCESS_DENIED; + return true; + } + + const wchar_t* filename = name->c_str(); + + uint32_t broker = BROKER_TRUE; + CountedParameterSet<OpenFile> params; +@@ -141,17 +140,16 @@ bool FilesystemDispatcher::NtCreateFile( + + bool FilesystemDispatcher::NtOpenFile(IPCInfo* ipc, + std::wstring* name, + uint32_t attributes, + uint32_t desired_access, + uint32_t share_access, + uint32_t open_options) { + if (!PreProcessName(name)) { +- // The path requested might contain a reparse point. + ipc->return_info.nt_status = STATUS_ACCESS_DENIED; + return true; + } + + const wchar_t* filename = name->c_str(); + + uint32_t broker = BROKER_TRUE; + uint32_t create_disposition = FILE_OPEN; +@@ -196,17 +194,16 @@ bool FilesystemDispatcher::NtOpenFile(IP + bool FilesystemDispatcher::NtQueryAttributesFile(IPCInfo* ipc, + std::wstring* name, + uint32_t attributes, + CountedBuffer* info) { + if (sizeof(FILE_BASIC_INFORMATION) != info->Size()) + return false; + + if (!PreProcessName(name)) { +- // The path requested might contain a reparse point. + ipc->return_info.nt_status = STATUS_ACCESS_DENIED; + return true; + } + + uint32_t broker = BROKER_TRUE; + const wchar_t* filename = name->c_str(); + CountedParameterSet<FileName> params; + params[FileName::NAME] = ParamPickerMake(filename); +@@ -245,17 +242,16 @@ bool FilesystemDispatcher::NtQueryAttrib + bool FilesystemDispatcher::NtQueryFullAttributesFile(IPCInfo* ipc, + std::wstring* name, + uint32_t attributes, + CountedBuffer* info) { + if (sizeof(FILE_NETWORK_OPEN_INFORMATION) != info->Size()) + return false; + + if (!PreProcessName(name)) { +- // The path requested might contain a reparse point. + ipc->return_info.nt_status = STATUS_ACCESS_DENIED; + return true; + } + + uint32_t broker = BROKER_TRUE; + const wchar_t* filename = name->c_str(); + CountedParameterSet<FileName> params; + params[FileName::NAME] = ParamPickerMake(filename); +@@ -307,17 +303,16 @@ bool FilesystemDispatcher::NtSetInformat + + if (!IsSupportedRenameCall(rename_info, length, info_class)) + return false; + + std::wstring name; + name.assign(rename_info->FileName, + rename_info->FileNameLength / sizeof(rename_info->FileName[0])); + if (!PreProcessName(&name)) { +- // The path requested might contain a reparse point. + ipc->return_info.nt_status = STATUS_ACCESS_DENIED; + return true; + } + + uint32_t broker = BROKER_TRUE; + const wchar_t* filename = name.c_str(); + CountedParameterSet<FileName> params; + params[FileName::NAME] = ParamPickerMake(filename); +diff --git a/security/sandbox/chromium/sandbox/win/src/filesystem_policy.cc b/security/sandbox/chromium/sandbox/win/src/filesystem_policy.cc +--- a/security/sandbox/chromium/sandbox/win/src/filesystem_policy.cc ++++ b/security/sandbox/chromium/sandbox/win/src/filesystem_policy.cc +@@ -1,16 +1,17 @@ + // 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 "sandbox/win/src/filesystem_policy.h" + + #include <stdint.h> + ++#include <algorithm> + #include <string> + + #include "base/logging.h" + #include "base/stl_util.h" + #include "base/win/scoped_handle.h" + #include "base/win/windows_version.h" + #include "sandbox/win/src/ipc_tags.h" + #include "sandbox/win/src/policy_engine_opcodes.h" +@@ -39,22 +40,16 @@ NTSTATUS NtCreateFileInTarget(HANDLE* ta + NTSTATUS status = + NtCreateFile(&local_handle, desired_access, obj_attributes, + io_status_block, nullptr, file_attributes, share_access, + create_disposition, create_options, ea_buffer, ea_length); + if (!NT_SUCCESS(status)) { + return status; + } + +- if (!sandbox::SameObject(local_handle, obj_attributes->ObjectName->Buffer)) { +- // The handle points somewhere else. Fail the operation. +- ::CloseHandle(local_handle); +- return STATUS_ACCESS_DENIED; +- } +- + if (!::DuplicateHandle(::GetCurrentProcess(), local_handle, target_process, + target_file_handle, 0, false, + DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { + return STATUS_ACCESS_DENIED; + } + return STATUS_SUCCESS; + } + +@@ -400,23 +395,32 @@ bool FileSystemPolicy::SetInformationFil + static_cast<FILE_INFORMATION_CLASS>(info_class); + *nt_status = NtSetInformationFile(local_handle, io_block, file_info, length, + file_info_class); + + return true; + } + + bool PreProcessName(std::wstring* path) { +- ConvertToLongPath(path); ++ // We now allow symbolic links to be opened via the broker, so we can no ++ // longer rely on the same object check where we checked the path of the ++ // opened file against the original. We don't specify a root when creating ++ // OBJECT_ATTRIBUTES from file names for brokering so they must be fully ++ // qualified and we can just check for the parent directory double dot between ++ // two backslashes. NtCreateFile doesn't seem to allow it anyway, but this is ++ // just an extra precaution. It also doesn't seem to allow the forward slash, ++ // but this is also used for checking policy rules, so we just replace forward ++ // slashes with backslashes. ++ std::replace(path->begin(), path->end(), L'/', L'\\'); ++ if (path->find(L"\\..\\") != std::wstring::npos) { ++ return false; ++ } + +- if (ERROR_NOT_A_REPARSE_POINT == IsReparsePoint(*path)) +- return true; +- +- // We can't process a reparsed file. +- return false; ++ ConvertToLongPath(path); ++ return true; + } + + std::wstring FixNTPrefixForMatch(const std::wstring& name) { + std::wstring mod_name = name; + + // NT prefix escaped for rule matcher + const wchar_t kNTPrefixEscaped[] = L"\\/?/?\\"; + const int kNTPrefixEscapedLen = base::size(kNTPrefixEscaped) - 1; diff --git a/security/sandbox/chromium-shim/patches/with_update/block_NtImpersonateAnonymousToken_before_LowerToken.patch b/security/sandbox/chromium-shim/patches/with_update/block_NtImpersonateAnonymousToken_before_LowerToken.patch new file mode 100644 index 0000000000..735b126858 --- /dev/null +++ b/security/sandbox/chromium-shim/patches/with_update/block_NtImpersonateAnonymousToken_before_LowerToken.patch @@ -0,0 +1,189 @@ +# HG changeset patch +# User Bob Owen <bobowencode@gmail.com> +# Date 1687248452 -3600 +# Tue Jun 20 09:07:32 2023 +0100 +# Node ID a07e3be35d9e5558fb95a18e3b858d5f4654dce9 +# Parent 5f4aecabd0376981a5f837f5de593c106c194712 +Bug 1839463: Block NtImpersonateAnonymousToken before RevertToSelf. + +Note this patch is slightly different from what landed for Bug 1839463, because +that also included the reversion of a different patch. + +diff --git a/security/sandbox/chromium/sandbox/win/src/interceptors.h b/security/sandbox/chromium/sandbox/win/src/interceptors.h +--- a/security/sandbox/chromium/sandbox/win/src/interceptors.h ++++ b/security/sandbox/chromium/sandbox/win/src/interceptors.h +@@ -11,16 +11,17 @@ + + namespace sandbox { + + enum InterceptorId { + // Internal use: + MAP_VIEW_OF_SECTION_ID = 0, + UNMAP_VIEW_OF_SECTION_ID, + // Policy broker: ++ IMPERSONATE_ANONYMOUS_TOKEN_ID, + SET_INFORMATION_THREAD_ID, + OPEN_THREAD_TOKEN_ID, + OPEN_THREAD_TOKEN_EX_ID, + OPEN_THREAD_ID, + OPEN_PROCESS_ID, + OPEN_PROCESS_TOKEN_ID, + OPEN_PROCESS_TOKEN_EX_ID, + // Filesystem dispatcher: +diff --git a/security/sandbox/chromium/sandbox/win/src/interceptors_64.cc b/security/sandbox/chromium/sandbox/win/src/interceptors_64.cc +--- a/security/sandbox/chromium/sandbox/win/src/interceptors_64.cc ++++ b/security/sandbox/chromium/sandbox/win/src/interceptors_64.cc +@@ -46,16 +46,24 @@ NTSTATUS WINAPI TargetNtUnmapViewOfSecti + reinterpret_cast<NtUnmapViewOfSectionFunction>( + g_originals[UNMAP_VIEW_OF_SECTION_ID]); + return TargetNtUnmapViewOfSection(orig_fn, process, base); + } + + // ----------------------------------------------------------------------- + + NTSTATUS WINAPI ++TargetNtImpersonateAnonymousToken64(HANDLE thread) { ++ NtImpersonateAnonymousTokenFunction orig_fn = ++ reinterpret_cast<NtImpersonateAnonymousTokenFunction>( ++ g_originals[IMPERSONATE_ANONYMOUS_TOKEN_ID]); ++ return TargetNtImpersonateAnonymousToken(orig_fn, thread); ++} ++ ++NTSTATUS WINAPI + TargetNtSetInformationThread64(HANDLE thread, + NT_THREAD_INFORMATION_CLASS thread_info_class, + PVOID thread_information, + ULONG thread_information_bytes) { + NtSetInformationThreadFunction orig_fn = + reinterpret_cast<NtSetInformationThreadFunction>( + g_originals[SET_INFORMATION_THREAD_ID]); + return TargetNtSetInformationThread(orig_fn, thread, thread_info_class, +diff --git a/security/sandbox/chromium/sandbox/win/src/interceptors_64.h b/security/sandbox/chromium/sandbox/win/src/interceptors_64.h +--- a/security/sandbox/chromium/sandbox/win/src/interceptors_64.h ++++ b/security/sandbox/chromium/sandbox/win/src/interceptors_64.h +@@ -31,16 +31,20 @@ TargetNtMapViewOfSection64(HANDLE sectio + // It should never be called directly. This function provides the means to + // detect dlls being unloaded, so we can clean up our interceptions. + SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtUnmapViewOfSection64(HANDLE process, + PVOID base); + + // ----------------------------------------------------------------------- + // Interceptors without IPC. + ++// Interception of NtImpersonateAnonymousToken on the child process. ++SANDBOX_INTERCEPT NTSTATUS WINAPI ++TargetNtImpersonateAnonymousToken64(HANDLE thread); ++ + // Interception of NtSetInformationThread on the child process. + SANDBOX_INTERCEPT NTSTATUS WINAPI + TargetNtSetInformationThread64(HANDLE thread, + NT_THREAD_INFORMATION_CLASS thread_info_class, + PVOID thread_information, + ULONG thread_information_bytes); + + // Interception of NtOpenThreadToken on the child process. +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 +@@ -299,16 +299,19 @@ typedef enum _NT_THREAD_INFORMATION_CLAS + ThreadIdealProcessor, + ThreadPriorityBoost, + ThreadSetTlsArrayAddress, + ThreadIsIoPending, + ThreadHideFromDebugger + } NT_THREAD_INFORMATION_CLASS, + *PNT_THREAD_INFORMATION_CLASS; + ++typedef NTSTATUS(WINAPI* NtImpersonateAnonymousTokenFunction)( ++ IN HANDLE ThreadHandle); ++ + typedef NTSTATUS(WINAPI* NtSetInformationThreadFunction)( + IN HANDLE ThreadHandle, + IN NT_THREAD_INFORMATION_CLASS ThreadInformationClass, + IN PVOID ThreadInformation, + IN ULONG ThreadInformationLength); + + // Partial definition only: + typedef enum _PROCESSINFOCLASS { +diff --git a/security/sandbox/chromium/sandbox/win/src/policy_broker.cc b/security/sandbox/chromium/sandbox/win/src/policy_broker.cc +--- a/security/sandbox/chromium/sandbox/win/src/policy_broker.cc ++++ b/security/sandbox/chromium/sandbox/win/src/policy_broker.cc +@@ -95,16 +95,18 @@ bool SetupBasicInterceptions(Interceptio + if (!INTERCEPT_NT(manager, NtOpenThread, OPEN_THREAD_ID, 20) || + !INTERCEPT_NT(manager, NtOpenProcess, OPEN_PROCESS_ID, 20) || + !INTERCEPT_NT(manager, NtOpenProcessToken, OPEN_PROCESS_TOKEN_ID, 16)) + return false; + + // Interceptions with neither policy nor IPC. + if (!INTERCEPT_NT(manager, NtSetInformationThread, SET_INFORMATION_THREAD_ID, + 20) || ++ !INTERCEPT_NT(manager, NtImpersonateAnonymousToken, ++ IMPERSONATE_ANONYMOUS_TOKEN_ID, 8) || + !INTERCEPT_NT(manager, NtOpenThreadToken, OPEN_THREAD_TOKEN_ID, 20)) + return false; + + // This one is also provided by process_thread_policy. + if (!INTERCEPT_NT(manager, NtOpenProcessTokenEx, OPEN_PROCESS_TOKEN_EX_ID, + 20)) + return false; + +diff --git a/security/sandbox/chromium/sandbox/win/src/policy_target.cc b/security/sandbox/chromium/sandbox/win/src/policy_target.cc +--- a/security/sandbox/chromium/sandbox/win/src/policy_target.cc ++++ b/security/sandbox/chromium/sandbox/win/src/policy_target.cc +@@ -67,16 +67,30 @@ bool QueryBroker(IpcTag ipc_id, CountedP + processor.Evaluate(kShortEval, params->parameters, params->count); + DCHECK_NT(POLICY_ERROR != result); + + return POLICY_MATCH == result && ASK_BROKER == processor.GetAction(); + } + + // ----------------------------------------------------------------------- + ++// Hooks NtImpersonateAnonymousToken so we can block until call to LowerToken. ++// This means a non-retricted token behaves the same as restricted one before ++// LowerToken and prevents us from being left with an anonymous logon token ++// because we are blocking the RevertToSelf that would undo it. ++NTSTATUS WINAPI TargetNtImpersonateAnonymousToken( ++ NtImpersonateAnonymousTokenFunction orig_ImpersonateAnonymousToken, ++ HANDLE thread) { ++ if (!SandboxFactory::GetTargetServices()->GetState()->RevertedToSelf()) { ++ return STATUS_ACCESS_DENIED; ++ } ++ ++ return orig_ImpersonateAnonymousToken(thread); ++} ++ + // Hooks NtSetInformationThread to block RevertToSelf from being + // called before the actual call to LowerToken. + NTSTATUS WINAPI TargetNtSetInformationThread( + NtSetInformationThreadFunction orig_SetInformationThread, + HANDLE thread, + NT_THREAD_INFORMATION_CLASS thread_info_class, + PVOID thread_information, + ULONG thread_information_bytes) { +diff --git a/security/sandbox/chromium/sandbox/win/src/policy_target.h b/security/sandbox/chromium/sandbox/win/src/policy_target.h +--- a/security/sandbox/chromium/sandbox/win/src/policy_target.h ++++ b/security/sandbox/chromium/sandbox/win/src/policy_target.h +@@ -14,16 +14,22 @@ namespace sandbox { + struct CountedParameterSetBase; + + // Performs a policy lookup and returns true if the request should be passed to + // the broker process. + bool QueryBroker(IpcTag ipc_id, CountedParameterSetBase* params); + + extern "C" { + ++// Interception of NtImpersonateAnonymousToken on the child process. ++// It should never be called directly. ++SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtImpersonateAnonymousToken( ++ NtImpersonateAnonymousTokenFunction orig_ImpersonateAnonymousToken, ++ HANDLE thread); ++ + // Interception of NtSetInformationThread on the child process. + // It should never be called directly. + SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtSetInformationThread( + NtSetInformationThreadFunction orig_SetInformationThread, HANDLE thread, + NT_THREAD_INFORMATION_CLASS thread_info_class, PVOID thread_information, + ULONG thread_information_bytes); + + // Interception of NtOpenThreadToken on the child process. diff --git a/security/sandbox/chromium-shim/patches/with_update/broker_complex_line_breaks.patch b/security/sandbox/chromium-shim/patches/with_update/broker_complex_line_breaks.patch new file mode 100644 index 0000000000..4d350fa8bc --- /dev/null +++ b/security/sandbox/chromium-shim/patches/with_update/broker_complex_line_breaks.patch @@ -0,0 +1,502 @@ +# HG changeset patch +# User Bob Owen <bobowencode@gmail.com> +# Date 1632737723 -3600 +# Mon Sep 27 11:15:23 2021 +0100 +# Node ID 096696bc1648dbacdfab881c4ed8fe770ebe58b1 +# Parent 254b1fc8768f67d208af199135276abae9aabc0c +Bug 1713973 p2: Add Uniscribe Line Breaking via chromium-sandbox IPC. r=toshi!,r=jfkthame! + +This adds a new cross call using the chromium shared memory IPC to proxy use of +the Uniscribe line breaker, because it cannot be used in the content process +with win32k lockdown enabled. + +If the text being processed is too long to fit into the IPC params then it is +processed in chunks. + +This change implements an INPTR_TYPE in the sandbox, which appears to have +been removed at some point. +It also fixes a bug in OpcodeFactory::MakeOpAction, so that a null param is +passed and we can use an empty parameter set. + +New files are in chromium-shim as these are most likely to require changes and +this means we will not have to update the main chromium patch. + +diff --git a/security/sandbox/chromium/sandbox/win/src/crosscall_client.h b/security/sandbox/chromium/sandbox/win/src/crosscall_client.h +--- a/security/sandbox/chromium/sandbox/win/src/crosscall_client.h ++++ b/security/sandbox/chromium/sandbox/win/src/crosscall_client.h +@@ -39,20 +39,16 @@ + // interpretation of the answer is private to client and server. + // + // The return value is ALL_OK if the IPC was delivered to the server, other + // return codes indicate that the IPC transport failed to deliver it. + namespace sandbox { + + enum class IpcTag; + +-// this is the assumed channel size. This can be overridden in a given +-// IPC implementation. +-const uint32_t kIPCChannelSize = 1024; +- + // The copy helper uses templates to deduce the appropriate copy function to + // copy the input parameters in the buffer that is going to be send across the + // IPC. These template facility can be made more sophisticated as need arises. + + // The default copy helper. It catches the general case where no other + // specialized template matches better. We set the type to UINT32_TYPE, so this + // only works with objects whose size is 32 bits. + template <typename T> +@@ -207,16 +203,42 @@ class CopyHelper<const wchar_t[n]> : pub + // parameters. + class InOutCountedBuffer : public CountedBuffer { + public: + InOutCountedBuffer(void* buffer, uint32_t size) + : CountedBuffer(buffer, size) {} + }; + + // This copy helper template specialization catches the cases where the ++// parameter is a an input buffer. ++template <> ++class CopyHelper<CountedBuffer> { ++ public: ++ CopyHelper(const CountedBuffer t) : t_(t) {} ++ ++ // Returns the pointer to the start of the string. ++ const void* GetStart() const { return t_.Buffer(); } ++ ++ // Update not required so just return true; ++ bool Update(void* buffer) { return true; } ++ ++ // Returns the size of the string in bytes. We define a nullptr string to ++ // be of zero length. ++ uint32_t GetSize() const { return t_.Size(); } ++ ++ // Returns true if the current type is used as an In or InOut parameter. ++ bool IsInOut() { return false; } ++ ++ ArgType GetType() { return INPTR_TYPE; } ++ ++ private: ++ const CountedBuffer t_; ++}; ++ ++// This copy helper template specialization catches the cases where the + // parameter is a an input/output buffer. + template <> + class CopyHelper<InOutCountedBuffer> { + public: + CopyHelper(const InOutCountedBuffer t) : t_(t) {} + + // Returns the pointer to the start of the string. + const void* GetStart() const { return t_.Buffer(); } +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 +@@ -41,16 +41,20 @@ + // them are not supported. + // + // Another limitation of CrossCall is that the return value and output + // parameters can only be uint32_t integers. Returning complex structures or + // strings is not supported. + + namespace sandbox { + ++// this is the assumed channel size. This can be overridden in a given ++// IPC implementation. ++const uint32_t kIPCChannelSize = 1024; ++ + // This is the list of all imported symbols from ntdll.dll. + SANDBOX_INTERCEPT NtExports g_nt; + + namespace { + + // Increases |value| until there is no need for padding given an int64_t + // alignment. Returns the increased value. + inline uint32_t Align(uint32_t value) { +@@ -216,16 +220,21 @@ class ActualCallParams : public CrossCal + // Testing-only constructor. Allows setting the |number_params| to a + // wrong value. + ActualCallParams(IpcTag tag, uint32_t number_params) + : CrossCallParams(tag, number_params) { + param_info_[0].offset_ = + static_cast<uint32_t>(parameters_ - reinterpret_cast<char*>(this)); + } + ++ static constexpr size_t MaxParamsSize() { ++ return sizeof( ++ ActualCallParams<NUMBER_PARAMS, kIPCChannelSize>::parameters_); ++ } ++ + // Testing-only method. Allows setting the apparent size to a wrong value. + // returns the previous size. + uint32_t OverrideSize(uint32_t new_size) { + uint32_t previous_size = param_info_[NUMBER_PARAMS].offset_; + param_info_[NUMBER_PARAMS].offset_ = new_size; + return previous_size; + } + +diff --git a/security/sandbox/chromium/sandbox/win/src/crosscall_server.cc b/security/sandbox/chromium/sandbox/win/src/crosscall_server.cc +--- a/security/sandbox/chromium/sandbox/win/src/crosscall_server.cc ++++ b/security/sandbox/chromium/sandbox/win/src/crosscall_server.cc +@@ -301,17 +301,17 @@ bool CrossCallParamsEx::GetParameterStr( + + bool CrossCallParamsEx::GetParameterPtr(uint32_t index, + uint32_t expected_size, + void** pointer) { + uint32_t size = 0; + ArgType type; + void* start = GetRawParameter(index, &size, &type); + +- if ((size != expected_size) || (INOUTPTR_TYPE != type)) ++ if ((size != expected_size) || (INOUTPTR_TYPE != type && INPTR_TYPE != type)) + return false; + + if (!start) + return false; + + *pointer = start; + return true; + } +diff --git a/security/sandbox/chromium/sandbox/win/src/ipc_args.cc b/security/sandbox/chromium/sandbox/win/src/ipc_args.cc +--- a/security/sandbox/chromium/sandbox/win/src/ipc_args.cc ++++ b/security/sandbox/chromium/sandbox/win/src/ipc_args.cc +@@ -15,16 +15,17 @@ namespace sandbox { + void ReleaseArgs(const IPCParams* ipc_params, void* args[kMaxIpcParams]) { + for (size_t i = 0; i < kMaxIpcParams; i++) { + switch (ipc_params->args[i]) { + case WCHAR_TYPE: { + delete reinterpret_cast<std::wstring*>(args[i]); + args[i] = nullptr; + break; + } ++ case INPTR_TYPE: + case INOUTPTR_TYPE: { + delete reinterpret_cast<CountedBuffer*>(args[i]); + args[i] = nullptr; + break; + } + default: + break; + } +@@ -69,16 +70,17 @@ bool GetArgs(CrossCallParamsEx* params, + void* data; + if (!params->GetParameterVoidPtr(i, &data)) { + ReleaseArgs(ipc_params, args); + return false; + } + args[i] = data; + break; + } ++ case INPTR_TYPE: + case INOUTPTR_TYPE: { + if (!args[i]) { + ReleaseArgs(ipc_params, args); + return false; + } + CountedBuffer* buffer = new CountedBuffer(args[i], size); + args[i] = buffer; + break; +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 +@@ -41,16 +41,17 @@ enum class IpcTag { + GDI_GETCERTIFICATESIZE, + GDI_DESTROYOPMPROTECTEDOUTPUT, + GDI_CONFIGUREOPMPROTECTEDOUTPUT, + GDI_GETOPMINFORMATION, + GDI_GETOPMRANDOMNUMBER, + GDI_GETSUGGESTEDOPMPROTECTEDOUTPUTARRAYSIZE, + GDI_SETOPMSIGNINGKEYANDSEQUENCENUMBERS, + NTCREATESECTION, ++ GETCOMPLEXLINEBREAKS, + LAST + }; + + constexpr size_t kMaxServiceCount = 64; + constexpr size_t kMaxIpcTag = static_cast<size_t>(IpcTag::LAST); + static_assert(kMaxIpcTag <= kMaxServiceCount, "kMaxServiceCount is too low"); + + } // namespace sandbox +diff --git a/security/sandbox/chromium/sandbox/win/src/policy_engine_opcodes.cc b/security/sandbox/chromium/sandbox/win/src/policy_engine_opcodes.cc +--- a/security/sandbox/chromium/sandbox/win/src/policy_engine_opcodes.cc ++++ b/security/sandbox/chromium/sandbox/win/src/policy_engine_opcodes.cc +@@ -78,17 +78,17 @@ EvalResult OpcodeEval<OP_ALWAYS_TRUE>(Po + } + + ////////////////////////////////////////////////////////////////////////////// + // Opcode OpAction: + // Does not require input parameter. + // Argument 0 contains the actual action to return. + + PolicyOpcode* OpcodeFactory::MakeOpAction(EvalResult action, uint32_t options) { +- PolicyOpcode* opcode = MakeBase(OP_ACTION, options, 0); ++ PolicyOpcode* opcode = MakeBase(OP_ACTION, options, -1); + if (!opcode) + return nullptr; + opcode->SetArgument(0, action); + return opcode; + } + + template <> + EvalResult OpcodeEval<OP_ACTION>(PolicyOpcode* opcode, +diff --git a/security/sandbox/chromium/sandbox/win/src/policy_params.h b/security/sandbox/chromium/sandbox/win/src/policy_params.h +--- a/security/sandbox/chromium/sandbox/win/src/policy_params.h ++++ b/security/sandbox/chromium/sandbox/win/src/policy_params.h +@@ -56,11 +56,15 @@ POLPARAMS_BEGIN(OpenKey) + POLPARAMS_END(OpenKey) + + // Policy parameter for name-based policies. + POLPARAMS_BEGIN(HandleTarget) + POLPARAM(NAME) + POLPARAM(TARGET) + POLPARAMS_END(HandleTarget) + ++// Policy parameters where no parameter based checks are done. ++POLPARAMS_BEGIN(EmptyParams) ++POLPARAMS_END(EmptyParams) ++ + } // namespace sandbox + + #endif // SANDBOX_SRC_POLICY_PARAMS_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 +@@ -176,16 +176,19 @@ class TargetServices { + // If the return is ERROR_GENERIC, you can call ::GetLastError() to get + // more information. + virtual ResultCode DuplicateHandle(HANDLE source_handle, + DWORD target_process_id, + HANDLE* target_handle, + DWORD desired_access, + DWORD options) = 0; + ++ virtual ResultCode GetComplexLineBreaks(const WCHAR* text, uint32_t length, ++ uint8_t* break_before) = 0; ++ + protected: + ~TargetServices() {} + }; + + class PolicyInfo { + public: + // Returns a JSON representation of the policy snapshot. + // This pointer has the same lifetime as this PolicyInfo object. +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 +@@ -27,17 +27,18 @@ class TargetPolicy { + 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_SIGNED_BINARY, // Signed binary policy. ++ SUBSYS_LINE_BREAK // Complex line break policy. + }; + + // Allowable semantics when a rule is matched. + enum Semantics { + FILES_ALLOW_ANY, // Allows open or create for any kind of access that + // the file system supports. + FILES_ALLOW_READONLY, // Allows open or create with read access only. + FILES_ALLOW_QUERY, // Allows access to query the attributes of a file. +@@ -60,17 +61,18 @@ class TargetPolicy { + REG_ALLOW_READONLY, // Allows readonly access to a registry key. + REG_ALLOW_ANY, // Allows read and write access to a registry key. + FAKE_USER_GDI_INIT, // Fakes user32 and gdi32 initialization. This can + // be used to allow the DLLs to load and initialize + // even if the process cannot access that subsystem. + IMPLEMENT_OPM_APIS, // Implements FAKE_USER_GDI_INIT and also exposes + // IPC calls to handle Output Protection Manager + // APIs. +- SIGNED_ALLOW_LOAD // Allows loading the module when CIG is enabled. ++ SIGNED_ALLOW_LOAD, // Allows loading the module when CIG is enabled. ++ LINE_BREAK_ALLOW // Allow complex line break brokering. + }; + + // Increments the reference count of this object. The reference count must + // be incremented if this interface is given to another component. + virtual void AddRef() = 0; + + // Decrements the reference count of this object. When the reference count + // is zero the object is automatically destroyed. +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 +@@ -15,16 +15,17 @@ + #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" + #include "sandbox/win/src/job.h" ++#include "sandbox/win/src/line_break_policy.h" + #include "sandbox/win/src/named_pipe_policy.h" + #include "sandbox/win/src/policy_broker.h" + #include "sandbox/win/src/policy_engine_processor.h" + #include "sandbox/win/src/policy_low_level.h" + #include "sandbox/win/src/process_mitigations.h" + #include "sandbox/win/src/process_mitigations_win32k_policy.h" + #include "sandbox/win/src/process_thread_policy.h" + #include "sandbox/win/src/registry_policy.h" +@@ -809,16 +810,23 @@ ResultCode PolicyBase::AddRuleInternal(S + "policy rules."; + if (!SignedPolicy::GenerateRules(pattern, semantics, policy_maker_)) { + NOTREACHED(); + return SBOX_ERROR_BAD_PARAMS; + } + } + break; + } ++ case SUBSYS_LINE_BREAK: { ++ if (!LineBreakPolicy::GenerateRules(pattern, semantics, policy_maker_)) { ++ NOTREACHED(); ++ return SBOX_ERROR_BAD_PARAMS; ++ } ++ break; ++ } + + default: { return SBOX_ERROR_UNSUPPORTED; } + } + + return SBOX_ALL_OK; + } + + } // namespace sandbox +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 +@@ -9,16 +9,17 @@ + #include <process.h> + #include <stdint.h> + + #include "base/win/windows_version.h" + #include "sandbox/win/src/crosscall_client.h" + #include "sandbox/win/src/handle_closer_agent.h" + #include "sandbox/win/src/handle_interception.h" + #include "sandbox/win/src/heap_helper.h" ++#include "sandbox/win/src/line_break_interception.h" + #include "sandbox/win/src/ipc_tags.h" + #include "sandbox/win/src/process_mitigations.h" + #include "sandbox/win/src/restricted_token_utils.h" + #include "sandbox/win/src/sandbox.h" + #include "sandbox/win/src/sandbox_nt_util.h" + #include "sandbox/win/src/sandbox_types.h" + #include "sandbox/win/src/sharedmem_ipc_client.h" + +@@ -240,19 +241,24 @@ void ProcessState::SetRevertedToSelf() { + if (process_state_ < ProcessStateInternal::REVERTED_TO_SELF) + process_state_ = ProcessStateInternal::REVERTED_TO_SELF; + } + + void ProcessState::SetCsrssConnected(bool csrss_connected) { + csrss_connected_ = csrss_connected; + } + +- + ResultCode TargetServicesBase::DuplicateHandle(HANDLE source_handle, + DWORD target_process_id, + HANDLE* target_handle, + DWORD desired_access, + DWORD options) { + return sandbox::DuplicateHandleProxy(source_handle, target_process_id, + target_handle, desired_access, options); + } + ++ResultCode TargetServicesBase::GetComplexLineBreaks(const WCHAR* text, ++ uint32_t length, ++ uint8_t* break_before) { ++ return sandbox::GetComplexLineBreaksProxy(text, length, break_before); ++} ++ + } // namespace sandbox +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 +@@ -45,16 +45,18 @@ class TargetServicesBase : public Target + ResultCode Init() override; + void LowerToken() override; + ProcessState* GetState() override; + ResultCode DuplicateHandle(HANDLE source_handle, + DWORD target_process_id, + HANDLE* target_handle, + DWORD desired_access, + DWORD options) override; ++ ResultCode GetComplexLineBreaks(const WCHAR* text, uint32_t length, ++ uint8_t* break_before) final; + + // Factory method. + static TargetServicesBase* GetInstance(); + + // Sends a simple IPC Message that has a well-known answer. Returns true + // if the IPC was successful and false otherwise. There are 2 versions of + // this test: 1 and 2. The first one send a simple message while the + // second one send a message with an in/out param. +diff --git a/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.cc b/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.cc +--- a/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.cc ++++ b/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.cc +@@ -9,16 +9,17 @@ + + #include "base/logging.h" + #include "sandbox/win/src/crosscall_server.h" + #include "sandbox/win/src/filesystem_dispatcher.h" + #include "sandbox/win/src/handle_dispatcher.h" + #include "sandbox/win/src/interception.h" + #include "sandbox/win/src/internal_types.h" + #include "sandbox/win/src/ipc_tags.h" ++#include "sandbox/win/src/line_break_dispatcher.h" + #include "sandbox/win/src/named_pipe_dispatcher.h" + #include "sandbox/win/src/process_mitigations_win32k_dispatcher.h" + #include "sandbox/win/src/process_thread_dispatcher.h" + #include "sandbox/win/src/registry_dispatcher.h" + #include "sandbox/win/src/sandbox_policy_base.h" + #include "sandbox/win/src/signed_dispatcher.h" + #include "sandbox/win/src/sync_dispatcher.h" + +@@ -90,16 +91,20 @@ TopLevelDispatcher::TopLevelDispatcher(P + IpcTag::GDI_GETSUGGESTEDOPMPROTECTEDOUTPUTARRAYSIZE)] = dispatcher; + ipc_targets_[static_cast<size_t>( + IpcTag::GDI_SETOPMSIGNINGKEYANDSEQUENCENUMBERS)] = dispatcher; + process_mitigations_win32k_dispatcher_.reset(dispatcher); + + dispatcher = new SignedDispatcher(policy_); + ipc_targets_[static_cast<size_t>(IpcTag::NTCREATESECTION)] = dispatcher; + signed_dispatcher_.reset(dispatcher); ++ ++ dispatcher = new LineBreakDispatcher(policy_); ++ ipc_targets_[static_cast<size_t>(IpcTag::GETCOMPLEXLINEBREAKS)] = dispatcher; ++ line_break_dispatcher_.reset(dispatcher); + } + + TopLevelDispatcher::~TopLevelDispatcher() {} + + // When an IPC is ready in any of the targets we get called. We manage an array + // of IPC dispatchers which are keyed on the IPC tag so we normally delegate + // to the appropriate dispatcher unless we can handle the IPC call ourselves. + Dispatcher* TopLevelDispatcher::OnMessageReady(IPCParams* ipc, +diff --git a/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.h b/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.h +--- a/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.h ++++ b/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.h +@@ -38,16 +38,17 @@ class TopLevelDispatcher : public Dispat + std::unique_ptr<Dispatcher> filesystem_dispatcher_; + std::unique_ptr<Dispatcher> named_pipe_dispatcher_; + std::unique_ptr<Dispatcher> thread_process_dispatcher_; + std::unique_ptr<Dispatcher> sync_dispatcher_; + std::unique_ptr<Dispatcher> registry_dispatcher_; + std::unique_ptr<Dispatcher> handle_dispatcher_; + std::unique_ptr<Dispatcher> process_mitigations_win32k_dispatcher_; + std::unique_ptr<Dispatcher> signed_dispatcher_; ++ std::unique_ptr<Dispatcher> line_break_dispatcher_; + Dispatcher* ipc_targets_[kMaxIpcTag]; + + DISALLOW_COPY_AND_ASSIGN(TopLevelDispatcher); + }; + + } // namespace sandbox + + #endif // SANDBOX_SRC_TOP_LEVEL_DISPATCHER_H__ diff --git a/security/sandbox/chromium-shim/patches/with_update/derive_sid_from_name.patch b/security/sandbox/chromium-shim/patches/with_update/derive_sid_from_name.patch new file mode 100644 index 0000000000..e798262861 --- /dev/null +++ b/security/sandbox/chromium-shim/patches/with_update/derive_sid_from_name.patch @@ -0,0 +1,74 @@ +# HG changeset patch +# User Bob Owen <bobowencode@gmail.com> +# Date 1677499923 0 +# Mon Feb 27 12:12:03 2023 +0000 +Expose Sid::FromNamedCapability through broker services. + +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 +@@ -730,9 +730,16 @@ ResultCode BrokerServicesBase::GetPolicy + return SBOX_ERROR_GENERIC; + } + + // Ownership has passed to tracker thread. + receiver.release(); + return SBOX_ALL_OK; + } + ++bool BrokerServicesBase::DeriveCapabilitySidFromName(const wchar_t* name, ++ PSID derived_sid, ++ DWORD sid_buffer_length) { ++ return ::CopySid(sid_buffer_length, derived_sid, ++ Sid::FromNamedCapability(name).GetPSID()); ++} ++ + } // 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 +@@ -57,16 +57,19 @@ class BrokerServicesBase final : public + // 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; + ++ bool DeriveCapabilitySidFromName(const wchar_t* name, PSID derived_sid, ++ DWORD sid_buffer_length) override; ++ + private: + // The routine that the worker thread executes. It is in charge of + // notifications and cleanup-related tasks. + static DWORD WINAPI TargetEventsThread(PVOID param); + + // The completion port used by the job objects to communicate events to + // the worker thread. + base::win::ScopedHandle job_port_; +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 +@@ -117,16 +117,21 @@ class BrokerServices { + // 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 + // callback. + virtual ResultCode GetPolicyDiagnostics( + std::unique_ptr<PolicyDiagnosticsReceiver> receiver) = 0; + ++ // Derive a capability PSID from the given string. ++ virtual bool DeriveCapabilitySidFromName(const wchar_t* name, ++ PSID derived_sid, ++ DWORD sid_buffer_length) = 0; ++ + 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 + // pointer only if this process is in fact a target. A process is a target diff --git a/security/sandbox/chromium-shim/patches/with_update/fix_broker_alive_mutex.patch b/security/sandbox/chromium-shim/patches/with_update/fix_broker_alive_mutex.patch new file mode 100644 index 0000000000..35b763c40c --- /dev/null +++ b/security/sandbox/chromium-shim/patches/with_update/fix_broker_alive_mutex.patch @@ -0,0 +1,104 @@ +# HG changeset patch +# User Yannis Juglaret <yjuglaret@mozilla.com> +# Date 1704300086 -3600 +# Wed Jan 03 17:41:26 2024 +0100 +# Node ID c08c4330fa141f5c7f8fa646ce179969e98cfd60 +# Parent 4a7e58fdaac86befe272259c2f603e2229080a5b +Bug 1851889 - Create the broker alive mutex during sandbox initialization. r=bobowen + +The sandbox IPC client/server communication protocol relies on a mutex +that clients can use to check if the broker process is still alive; e.g. +when a response takes more than one second to come. This mutex is owned +by a thread of the broker process and will be marked as abandoned when +that thread dies. + +Clients assume that the broker alive mutex being abandoned means that +the whole broker process crashed. Therefore it is necessary that the +thread that owns the broker alive mutex lives as long as the whole +broker process, since clients cannot distinguish between the death of +this thread and the death of the whole broker process. + +In upstream code, the broker alive mutex gets created during the first +call to SpawnTarget, which means that it is implicitly required that +this call occurs from a thread that lives as long as the broker process +will. Since we call SpawnTarget from the IPC launcher thread, which dies +during XPCOM shutdown, we are breaking this implicit requirement. + +Therefore, this patch makes us create the broker alive mutex from the +main thread, during sandbox initialization. This ensures that clients +will not get disturbed by the death of the IPC launcher thread anymore. + +Differential Revision: https://phabricator.services.mozilla.com/D197423 + +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 +@@ -172,6 +172,9 @@ ResultCode BrokerServicesBase::Init() { + if (!job_thread_.IsValid()) + return SBOX_ERROR_CANNOT_INIT_BROKERSERVICES; + ++ if (!SharedMemIPCServer::CreateBrokerAliveMutex()) ++ return SBOX_ERROR_CANNOT_INIT_BROKERSERVICES; ++ + return SBOX_ALL_OK; + } + +diff --git a/security/sandbox/chromium/sandbox/win/src/sharedmem_ipc_server.cc b/security/sandbox/chromium/sandbox/win/src/sharedmem_ipc_server.cc +--- a/security/sandbox/chromium/sandbox/win/src/sharedmem_ipc_server.cc ++++ b/security/sandbox/chromium/sandbox/win/src/sharedmem_ipc_server.cc +@@ -24,6 +24,18 @@ volatile HANDLE g_alive_mutex = nullptr; + + namespace sandbox { + ++/* static */ bool SharedMemIPCServer::CreateBrokerAliveMutex() { ++ DCHECK(!g_alive_mutex); ++ // We create a initially owned mutex. If the server dies unexpectedly, ++ // the thread that owns it will fail to release the lock and windows will ++ // report to the target (when it tries to acquire it) that the wait was ++ // abandoned. Note: We purposely leak the local handle because we want it to ++ // be closed by Windows itself so it is properly marked as abandoned if the ++ // server dies. ++ g_alive_mutex = ::CreateMutexW(nullptr, true, nullptr); ++ return static_cast<bool>(g_alive_mutex); ++} ++ + SharedMemIPCServer::ServerControl::ServerControl() {} + + SharedMemIPCServer::ServerControl::~ServerControl() {} +@@ -37,19 +49,7 @@ SharedMemIPCServer::SharedMemIPCServer(H + target_process_(target_process), + target_process_id_(target_process_id), + call_dispatcher_(dispatcher) { +- // We create a initially owned mutex. If the server dies unexpectedly, +- // the thread that owns it will fail to release the lock and windows will +- // report to the target (when it tries to acquire it) that the wait was +- // abandoned. Note: We purposely leak the local handle because we want it to +- // be closed by Windows itself so it is properly marked as abandoned if the +- // server dies. +- if (!g_alive_mutex) { +- HANDLE mutex = ::CreateMutexW(nullptr, true, nullptr); +- if (::InterlockedCompareExchangePointer(&g_alive_mutex, mutex, nullptr)) { +- // We lost the race to create the mutex. +- ::CloseHandle(mutex); +- } +- } ++ DCHECK(g_alive_mutex); + } + + SharedMemIPCServer::~SharedMemIPCServer() { +diff --git a/security/sandbox/chromium/sandbox/win/src/sharedmem_ipc_server.h b/security/sandbox/chromium/sandbox/win/src/sharedmem_ipc_server.h +--- a/security/sandbox/chromium/sandbox/win/src/sharedmem_ipc_server.h ++++ b/security/sandbox/chromium/sandbox/win/src/sharedmem_ipc_server.h +@@ -60,6 +60,12 @@ class SharedMemIPCServer { + // creates the kernels events used to signal the IPC. + bool Init(void* shared_mem, uint32_t shared_size, uint32_t channel_size); + ++ // Create the mutex used by clients to check if the broker process crashed. ++ // This function must be called only once, from a thread that will live as ++ // long as the whole broker process will. This call must occur prior to any ++ // SharedMemIPCServer creation. ++ static bool CreateBrokerAliveMutex(); ++ + private: + // Allow tests to be marked DISABLED_. Note that FLAKY_ and FAILS_ prefixes + // do not work with sandbox tests. diff --git a/security/sandbox/chromium-shim/patches/with_update/ifdef_out_AppContainerProfileBase_testing_functions.patch b/security/sandbox/chromium-shim/patches/with_update/ifdef_out_AppContainerProfileBase_testing_functions.patch new file mode 100644 index 0000000000..325d23cc19 --- /dev/null +++ b/security/sandbox/chromium-shim/patches/with_update/ifdef_out_AppContainerProfileBase_testing_functions.patch @@ -0,0 +1,79 @@ +# HG changeset patch +# User Bob Owen <bobowencode@gmail.com> +# Date 1560259052 -3600 +# Tue Jun 11 14:17:32 2019 +0100 +# Node ID ca1bafe49015cb6625648274f32959e4160a6ce9 +# Parent 3ec022faaf83642e3c1894d83ff99926bada990c +Hash if out testing functions that cause dependency creep. r=aklotz + +diff --git a/security/sandbox/chromium/sandbox/win/src/app_container_profile_base.cc b/security/sandbox/chromium/sandbox/win/src/app_container_profile_base.cc +--- a/security/sandbox/chromium/sandbox/win/src/app_container_profile_base.cc ++++ b/security/sandbox/chromium/sandbox/win/src/app_container_profile_base.cc +@@ -3,17 +3,19 @@ + // found in the LICENSE file. + + #include <memory> + + #include <aclapi.h> + #include <userenv.h> + + #include "base/strings/stringprintf.h" ++#if !defined(MOZ_SANDBOX) + #include "base/win/scoped_co_mem.h" ++#endif + #include "base/win/scoped_handle.h" + #include "sandbox/win/src/app_container_profile_base.h" + #include "sandbox/win/src/restricted_token_utils.h" + #include "sandbox/win/src/win_utils.h" + + namespace sandbox { + + namespace { +@@ -167,39 +169,47 @@ bool AppContainerProfileBase::GetRegistr + HKEY key_handle; + if (FAILED(get_app_container_registry_location(desired_access, &key_handle))) + return false; + key->Set(key_handle); + return true; + } + + bool AppContainerProfileBase::GetFolderPath(base::FilePath* file_path) { ++#if defined(MOZ_SANDBOX) ++ IMMEDIATE_CRASH(); ++#else + static GetAppContainerFolderPathFunc* get_app_container_folder_path = + reinterpret_cast<GetAppContainerFolderPathFunc*>(GetProcAddress( + GetModuleHandle(L"userenv"), "GetAppContainerFolderPath")); + if (!get_app_container_folder_path) + return false; + std::wstring sddl_str; + if (!package_sid_.ToSddlString(&sddl_str)) + return false; + base::win::ScopedCoMem<wchar_t> path_str; + if (FAILED(get_app_container_folder_path(sddl_str.c_str(), &path_str))) + return false; + *file_path = base::FilePath(path_str.get()); + return true; ++#endif + } + + bool AppContainerProfileBase::GetPipePath(const wchar_t* pipe_name, + base::FilePath* pipe_path) { ++#if defined(MOZ_SANDBOX) ++ IMMEDIATE_CRASH(); ++#else + std::wstring sddl_str; + if (!package_sid_.ToSddlString(&sddl_str)) + return false; + *pipe_path = base::FilePath(base::StringPrintf(L"\\\\.\\pipe\\%ls\\%ls", + sddl_str.c_str(), pipe_name)); + return true; ++#endif + } + + bool AppContainerProfileBase::AccessCheck(const wchar_t* object_name, + SE_OBJECT_TYPE object_type, + DWORD desired_access, + DWORD* granted_access, + BOOL* access_status) { + GENERIC_MAPPING generic_mapping; diff --git a/security/sandbox/chromium-shim/patches/with_update/ifdef_out_FromStringInternal.patch b/security/sandbox/chromium-shim/patches/with_update/ifdef_out_FromStringInternal.patch new file mode 100644 index 0000000000..411d896570 --- /dev/null +++ b/security/sandbox/chromium-shim/patches/with_update/ifdef_out_FromStringInternal.patch @@ -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 34b1e1189bcbb3b8ecbfc4c9decc1c6dfc46c1e6 +# Parent c3dc5b64a97fe0526ab8826bdcb47740592472b7 +Don't compile base::Time::FromStringInternal. r=aklotz + +This has a dependency on nspr, which causes issues. + +Originally landed in changeset: +https://hg.mozilla.org/mozilla-central/rev/477b991bf6fa7b4511768649c9bf37c7275d30d9 + +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; + } + // This function must not fail. + NOTREACHED(); + return Time(); + } + ++#if !defined(MOZ_SANDBOX) + // static + bool Time::FromStringInternal(const char* time_string, + bool is_local, + Time* parsed_time) { + DCHECK((time_string != nullptr) && (parsed_time != nullptr)); + + if (time_string[0] == '\0') + return false; +@@ -301,16 +302,17 @@ bool Time::FromStringInternal(const char + &result_time); + if (PR_SUCCESS != result) + return false; + + result_time += kTimeTToMicrosecondsOffset; + *parsed_time = Time(result_time); + return true; + } ++#endif + + // static + bool Time::ExplodedMostlyEquals(const Exploded& lhs, const Exploded& rhs) { + return lhs.year == rhs.year && lhs.month == rhs.month && + lhs.day_of_month == rhs.day_of_month && lhs.hour == rhs.hour && + lhs.minute == rhs.minute && lhs.second == rhs.second && + lhs.millisecond == rhs.millisecond; + } diff --git a/security/sandbox/chromium-shim/patches/with_update/ifdef_out_SequenceChecker_code.patch b/security/sandbox/chromium-shim/patches/with_update/ifdef_out_SequenceChecker_code.patch new file mode 100644 index 0000000000..62216e9af7 --- /dev/null +++ b/security/sandbox/chromium-shim/patches/with_update/ifdef_out_SequenceChecker_code.patch @@ -0,0 +1,36 @@ +# HG changeset patch +# User Bob Owen <bobowencode@gmail.com> +# Date 1509027043 -3600 +# Thu Oct 26 15:10:43 2017 +0100 +# Node ID cbe274e5b95c1c207597a0fbb4a80905d6d4dacc +# Parent bbbba04e693f3819bcb6dd70ea27d3cab194e4cb +This removes sequence checking on RefCountedBase in DEBUG builds. r=aklotz + +We don't currently make use of it and it brings in many dependencies. + +diff --git a/security/sandbox/chromium/base/memory/ref_counted.cc b/security/sandbox/chromium/base/memory/ref_counted.cc +--- a/security/sandbox/chromium/base/memory/ref_counted.cc ++++ b/security/sandbox/chromium/base/memory/ref_counted.cc +@@ -53,18 +53,22 @@ bool RefCountedThreadSafeBase::Release() + } + void RefCountedThreadSafeBase::AddRefWithCheck() const { + AddRefWithCheckImpl(); + } + #endif + + #if DCHECK_IS_ON() + bool RefCountedBase::CalledOnValidSequence() const { ++#if defined(MOZ_SANDBOX) ++ return true; ++#else + return sequence_checker_.CalledOnValidSequence() || + g_cross_thread_ref_count_access_allow_count.load() != 0; ++#endif + } + #endif + + } // namespace subtle + + #if DCHECK_IS_ON() + ScopedAllowCrossThreadRefCountAccess::ScopedAllowCrossThreadRefCountAccess() { + ++g_cross_thread_ref_count_access_allow_count; diff --git a/security/sandbox/chromium-shim/patches/with_update/include_atomic_header_in_platform_thread.patch b/security/sandbox/chromium-shim/patches/with_update/include_atomic_header_in_platform_thread.patch new file mode 100644 index 0000000000..e088e99680 --- /dev/null +++ b/security/sandbox/chromium-shim/patches/with_update/include_atomic_header_in_platform_thread.patch @@ -0,0 +1,27 @@ +# HG changeset patch +# User Bob Owen <bobowencode@gmail.com> +# Date 1560260570 -3600 +# Tue Jun 11 14:42:50 2019 +0100 +# Node ID 7baa38185938e45ab128ec3975ae139753c8ad67 +# Parent cb568f9b29f8c2c84c72c49b7a565d8081929f04 +Bug 1552160: Fix missing atomic include in chromium platform_thread.cc. r=jld + +diff --git a/security/sandbox/chromium/base/threading/platform_thread.cc b/security/sandbox/chromium/base/threading/platform_thread.cc +--- a/security/sandbox/chromium/base/threading/platform_thread.cc ++++ b/security/sandbox/chromium/base/threading/platform_thread.cc +@@ -1,14 +1,15 @@ + // 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/threading/platform_thread.h" + ++#include <atomic> + #include <memory> + + #include "base/feature_list.h" + + namespace base { + + namespace { + diff --git a/security/sandbox/chromium-shim/patches/with_update/lower_SDK_version_requirement.patch b/security/sandbox/chromium-shim/patches/with_update/lower_SDK_version_requirement.patch new file mode 100644 index 0000000000..185e128d83 --- /dev/null +++ b/security/sandbox/chromium-shim/patches/with_update/lower_SDK_version_requirement.patch @@ -0,0 +1,34 @@ +# 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 diff --git a/security/sandbox/chromium-shim/patches/with_update/mingw_capitalization.patch b/security/sandbox/chromium-shim/patches/with_update/mingw_capitalization.patch new file mode 100644 index 0000000000..0c27032307 --- /dev/null +++ b/security/sandbox/chromium-shim/patches/with_update/mingw_capitalization.patch @@ -0,0 +1,74 @@ +# HG changeset patch +# User Tom Ritter <tom@mozilla.com> +# Date 1516825559 21600 +# Wed Jan 24 14:25:59 2018 -0600 +# Node ID 9ce534c9f572dfb5abd3e409d9cfec069ccee0cd +# Parent 6413cb580dccd986c61e6dbdc72fc370765b8f10 +Bug 1431797 Correct the capitalization of headers inside the chromium code so MinGW can compile + +diff --git a/security/sandbox/chromium/base/rand_util_win.cc b/security/sandbox/chromium/base/rand_util_win.cc +--- a/security/sandbox/chromium/base/rand_util_win.cc ++++ b/security/sandbox/chromium/base/rand_util_win.cc +@@ -7,17 +7,17 @@ + #include <windows.h> + #include <stddef.h> + #include <stdint.h> + + // #define needed to link in RtlGenRandom(), a.k.a. SystemFunction036. See the + // "Community Additions" comment on MSDN here: + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa387694.aspx + #define SystemFunction036 NTAPI SystemFunction036 +-#include <NTSecAPI.h> ++#include <ntsecapi.h> + #undef SystemFunction036 + + #include <algorithm> + #include <limits> + + #include "base/logging.h" + + namespace base { +diff --git a/security/sandbox/chromium/base/win/pe_image.h b/security/sandbox/chromium/base/win/pe_image.h +--- 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> + + #if defined(_WIN32_WINNT_WIN8) + // The Windows 8 SDK defines FACILITY_VISUALCPP in winerror.h. + #undef FACILITY_VISUALCPP + #endif +-#include <DelayIMP.h> ++#include <delayimp.h> + + namespace base { + namespace win { + + // This class is a wrapper for the Portable Executable File Format (PE). + // Its main purpose is to provide an easy way to work with imports and exports + // from a file, mapped in memory as image. + class PEImage { +diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_rand.cc b/security/sandbox/chromium/sandbox/win/src/sandbox_rand.cc +--- a/security/sandbox/chromium/sandbox/win/src/sandbox_rand.cc ++++ b/security/sandbox/chromium/sandbox/win/src/sandbox_rand.cc +@@ -5,17 +5,17 @@ + #include "sandbox/win/src/sandbox_rand.h" + + #include <windows.h> + + // #define needed to link in RtlGenRandom(), a.k.a. SystemFunction036. See the + // "Community Additions" comment on MSDN here: + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa387694.aspx + #define SystemFunction036 NTAPI SystemFunction036 +-#include <NTSecAPI.h> ++#include <ntsecapi.h> + #undef SystemFunction036 + + namespace sandbox { + + bool GetRandom(unsigned int* random_value) { + return RtlGenRandom(random_value, sizeof(unsigned int)) != false; + } + diff --git a/security/sandbox/chromium-shim/patches/with_update/mingw_cast_getprocaddress.patch b/security/sandbox/chromium-shim/patches/with_update/mingw_cast_getprocaddress.patch new file mode 100644 index 0000000000..1251be114f --- /dev/null +++ b/security/sandbox/chromium-shim/patches/with_update/mingw_cast_getprocaddress.patch @@ -0,0 +1,34 @@ +# HG changeset patch +# User Tom Ritter <tom@mozilla.com> +# Date 1516720544 21600 +# Tue Jan 23 09:15:44 2018 -0600 +# Node ID 2b4556cb7407c196522e52cfd286ee88c3bb6e72 +# Parent 60aa47b111918d4e30f7e363359d1dcc3a3f277d +Bug 1432295 Cast GetProcAddress to (void*) r?bobowen + +error: invalid conversion from 'FARPROC {aka int (__attribute__((__stdcall__)) *)()}' to 'void*' [-fpermissive] + +According to http://stackoverflow.com/questions/13958081/, msvc does the fixup + +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 +@@ -231,17 +231,17 @@ ResultCode TargetProcess::TransferVariab + + void* child_var = address; + + #if SANDBOX_EXPORTS + HMODULE module = ::LoadLibrary(exe_name_.get()); + if (!module) + return SBOX_ERROR_CANNOT_LOADLIBRARY_EXECUTABLE; + +- 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; + + size_t offset = + reinterpret_cast<char*>(child_var) - reinterpret_cast<char*>(module); + child_var = reinterpret_cast<char*>(MainModule()) + offset; diff --git a/security/sandbox/chromium-shim/patches/with_update/mingw_copy_s.patch b/security/sandbox/chromium-shim/patches/with_update/mingw_copy_s.patch new file mode 100644 index 0000000000..12e62e8b15 --- /dev/null +++ b/security/sandbox/chromium-shim/patches/with_update/mingw_copy_s.patch @@ -0,0 +1,34 @@ +# HG changeset patch +# User Tom Ritter <tom@mozilla.com> +# Date 1516394893 21600 +# Fri Jan 19 14:48:13 2018 -0600 +# Node ID bd0817bb5b0c5681c4c49817363e6ddd6efac82c +# Parent c64ea5b2e26b203eff2f0b9d85fef99ae3a094f9 +Bug 1431825 Map _Copy_s to copy for basic_string compatibility on MinGW r?bobowen + +diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_types.h b/security/sandbox/chromium/sandbox/win/src/sandbox_types.h +--- a/security/sandbox/chromium/sandbox/win/src/sandbox_types.h ++++ b/security/sandbox/chromium/sandbox/win/src/sandbox_types.h +@@ -5,16 +5,22 @@ + #ifndef SANDBOX_WIN_SRC_SANDBOX_TYPES_H_ + #define SANDBOX_WIN_SRC_SANDBOX_TYPES_H_ + + #include "base/process/kill.h" + #include "base/process/launch.h" + + namespace sandbox { + ++#ifdef __MINGW32__ ++// Map Microsoft's proprietary more-safe version of copy() back to ++// the std::basic_string method ++#define _Copy_s copy ++#endif ++ + // Operation result codes returned by the sandbox API. + // + // Note: These codes are listed in a histogram and any new codes should be added + // at the end. If the underlying type is changed then the forward declaration in + // sandbox_init.h must be updated. + // + enum ResultCode : int { + SBOX_ALL_OK = 0, diff --git a/security/sandbox/chromium-shim/patches/with_update/mingw_disable_one_try.patch b/security/sandbox/chromium-shim/patches/with_update/mingw_disable_one_try.patch new file mode 100644 index 0000000000..d5b700ea8f --- /dev/null +++ b/security/sandbox/chromium-shim/patches/with_update/mingw_disable_one_try.patch @@ -0,0 +1,51 @@ +# HG changeset patch +# User Tom Ritter <tom@mozilla.com> +# Date 1516389982 21600 +# Fri Jan 19 13:26:22 2018 -0600 +# Node ID 3ca7306d73ebc1ce47ccdc62ee8cbb69a9bfbb2c +# Parent 6aa6c7d894609140ccde2e9e50eba8c25a9caeb5 +Bug 1431803 Disable a specific __try block on MinGW r?bobowen + +This function is a technique to name a thread for debugging purposes, +and it always throws an exception (and then continues). On MinGW +we don't want it to throw an exception, so we do nothing. + +This means on MinGW we won't get nice thread naming during debugging, +but we'll limp along. + +MozReview-Commit-ID: JRKY4wp7sdu + +diff --git a/security/sandbox/chromium/base/threading/platform_thread_win.cc b/security/sandbox/chromium/base/threading/platform_thread_win.cc +--- a/security/sandbox/chromium/base/threading/platform_thread_win.cc ++++ b/security/sandbox/chromium/base/threading/platform_thread_win.cc +@@ -32,27 +32,30 @@ typedef struct tagTHREADNAME_INFO { + } THREADNAME_INFO; + + // The SetThreadDescription API was brought in version 1607 of Windows 10. + typedef HRESULT(WINAPI* SetThreadDescription)(HANDLE hThread, + PCWSTR lpThreadDescription); + + // This function has try handling, so it is separated out of its caller. + void SetNameInternal(PlatformThreadId thread_id, const char* name) { ++ //This function is only used for debugging purposes, as you can find by its caller ++#ifndef __MINGW32__ + THREADNAME_INFO info; + info.dwType = 0x1000; + info.szName = name; + info.dwThreadID = thread_id; + info.dwFlags = 0; + + __try { + RaiseException(kVCThreadNameException, 0, sizeof(info)/sizeof(DWORD), + reinterpret_cast<DWORD_PTR*>(&info)); + } __except(EXCEPTION_CONTINUE_EXECUTION) { + } ++#endif + } + + struct ThreadParams { + PlatformThread::Delegate* delegate; + bool joinable; + ThreadPriority priority; + }; + diff --git a/security/sandbox/chromium-shim/patches/with_update/mingw_missing_windows_types_defines.patch b/security/sandbox/chromium-shim/patches/with_update/mingw_missing_windows_types_defines.patch new file mode 100644 index 0000000000..30220a0660 --- /dev/null +++ b/security/sandbox/chromium-shim/patches/with_update/mingw_missing_windows_types_defines.patch @@ -0,0 +1,37 @@ +# HG changeset patch +# User Bob Owen <bobowencode@gmail.com> +# Date 1558294860 -3600 +# Sun May 19 20:41:00 2019 +0100 +# Node ID 331daa6926b2d495959a0aebbf034958a9bc1e2a +# Parent e71e4e7a914c2d2515bf84be6ad045febabb6dfc +Bug 1552160: Add missing defines from concurrencysal.h and specstrings.h in windows_type.h on MinGW. + +diff --git a/security/sandbox/chromium/base/win/windows_types.h b/security/sandbox/chromium/base/win/windows_types.h +--- a/security/sandbox/chromium/base/win/windows_types.h ++++ b/security/sandbox/chromium/base/win/windows_types.h +@@ -4,17 +4,25 @@ + + // This file contains defines and typedefs that allow popular Windows types to + // be used without the overhead of including windows.h. + + #ifndef BASE_WIN_WINDOWS_TYPES_H + #define BASE_WIN_WINDOWS_TYPES_H + + // Needed for function prototypes. ++#if defined(__MINGW32__) ++// MinGW doesn't have this file yet, but we only need this define. ++// Bug 1552706 tracks removing this and the one below. ++#define _Releases_exclusive_lock_(lock) ++// MinGW doesn't appear to have this in specstrings.h either. ++#define _Post_equals_last_error_ ++#else + #include <concurrencysal.h> ++#endif + #include <sal.h> + #include <specstrings.h> + + #ifdef __cplusplus + extern "C" { + #endif + + // typedef and define the most commonly used Windows integer types. diff --git a/security/sandbox/chromium-shim/patches/with_update/mingw_offsetof.patch b/security/sandbox/chromium-shim/patches/with_update/mingw_offsetof.patch new file mode 100644 index 0000000000..89072da69b --- /dev/null +++ b/security/sandbox/chromium-shim/patches/with_update/mingw_offsetof.patch @@ -0,0 +1,182 @@ +# HG changeset patch +# User Tom Ritter <tom@mozilla.com> +# Date 1528394907 18000 +# Thu Jun 07 13:08:27 2018 -0500 +# Node ID ffb6c5c06905538fb887464e9553e7b47cdf7575 +# Parent 1987e062f1e5bf2998bb8e9d96353c5ccb0cc281 +Bug 1461421 Use OffsetOf to calculate the location of parameters_ rather than making assumptions about the parent class r?bobowen + +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 { + ULONG_PTR ulong_ptr; + }; + + // Maximum number of IPC parameters currently supported. + // To increase this value, we have to: + // - Add another Callback typedef to Dispatcher. + // - Add another case to the switch on SharedMemIPCServer::InvokeCallback. + // - Add another case to the switch in GetActualAndMaxBufferSize ++// - Add another case to the switch in GetMinDeclaredActualCallParamsSize + const int kMaxIpcParams = 9; + + // Contains the information about a parameter in the ipc buffer. + struct ParamInfo { + ArgType type_; + uint32_t offset_; + uint32_t size_; + }; +@@ -287,16 +288,18 @@ class ActualCallParams : public CrossCal + protected: + ActualCallParams() : CrossCallParams(IpcTag::UNUSED, NUMBER_PARAMS) {} + + private: + ParamInfo param_info_[NUMBER_PARAMS + 1]; + char parameters_[BLOCK_SIZE - sizeof(CrossCallParams) - + sizeof(ParamInfo) * (NUMBER_PARAMS + 1)]; + DISALLOW_COPY_AND_ASSIGN(ActualCallParams); ++ ++ friend uint32_t GetMinDeclaredActualCallParamsSize(uint32_t param_count); + }; + + static_assert(sizeof(ActualCallParams<1, 1024>) == 1024, "bad size buffer"); + static_assert(sizeof(ActualCallParams<2, 1024>) == 1024, "bad size buffer"); + static_assert(sizeof(ActualCallParams<3, 1024>) == 1024, "bad size buffer"); + + } // namespace sandbox + +diff --git a/security/sandbox/chromium/sandbox/win/src/crosscall_server.cc b/security/sandbox/chromium/sandbox/win/src/crosscall_server.cc +--- a/security/sandbox/chromium/sandbox/win/src/crosscall_server.cc ++++ b/security/sandbox/chromium/sandbox/win/src/crosscall_server.cc +@@ -28,30 +28,31 @@ namespace { + + // The buffer for a message must match the max channel size. + const size_t kMaxBufferSize = sandbox::kIPCChannelSize; + + } // namespace + + namespace sandbox { + ++// The template types are used to calculate the maximum expected size. ++typedef ActualCallParams<0, kMaxBufferSize> ActualCP0; ++typedef ActualCallParams<1, kMaxBufferSize> ActualCP1; ++typedef ActualCallParams<2, kMaxBufferSize> ActualCP2; ++typedef ActualCallParams<3, kMaxBufferSize> ActualCP3; ++typedef ActualCallParams<4, kMaxBufferSize> ActualCP4; ++typedef ActualCallParams<5, kMaxBufferSize> ActualCP5; ++typedef ActualCallParams<6, kMaxBufferSize> ActualCP6; ++typedef ActualCallParams<7, kMaxBufferSize> ActualCP7; ++typedef ActualCallParams<8, kMaxBufferSize> ActualCP8; ++typedef ActualCallParams<9, kMaxBufferSize> ActualCP9; ++ + // Returns the actual size for the parameters in an IPC buffer. Returns + // zero if the |param_count| is zero or too big. + uint32_t GetActualBufferSize(uint32_t param_count, void* buffer_base) { +- // The template types are used to calculate the maximum expected size. +- typedef ActualCallParams<1, kMaxBufferSize> ActualCP1; +- typedef ActualCallParams<2, kMaxBufferSize> ActualCP2; +- typedef ActualCallParams<3, kMaxBufferSize> ActualCP3; +- typedef ActualCallParams<4, kMaxBufferSize> ActualCP4; +- typedef ActualCallParams<5, kMaxBufferSize> ActualCP5; +- typedef ActualCallParams<6, kMaxBufferSize> ActualCP6; +- typedef ActualCallParams<7, kMaxBufferSize> ActualCP7; +- typedef ActualCallParams<8, kMaxBufferSize> ActualCP8; +- typedef ActualCallParams<9, kMaxBufferSize> ActualCP9; +- + // Retrieve the actual size and the maximum size of the params buffer. + switch (param_count) { + case 0: + return 0; + case 1: + return reinterpret_cast<ActualCP1*>(buffer_base)->GetSize(); + case 2: + return reinterpret_cast<ActualCP2*>(buffer_base)->GetSize(); +@@ -69,16 +70,45 @@ uint32_t GetActualBufferSize(uint32_t pa + return reinterpret_cast<ActualCP8*>(buffer_base)->GetSize(); + case 9: + return reinterpret_cast<ActualCP9*>(buffer_base)->GetSize(); + default: + return 0; + } + } + ++// Returns the minimum size for the parameters in an IPC buffer. Returns ++// zero if the |param_count| is less than zero or too big. ++uint32_t GetMinDeclaredActualCallParamsSize(uint32_t param_count) { ++ switch (param_count) { ++ case 0: ++ return offsetof(ActualCP0, parameters_); ++ case 1: ++ return offsetof(ActualCP1, parameters_); ++ case 2: ++ return offsetof(ActualCP2, parameters_); ++ case 3: ++ return offsetof(ActualCP3, parameters_); ++ case 4: ++ return offsetof(ActualCP4, parameters_); ++ case 5: ++ return offsetof(ActualCP5, parameters_); ++ case 6: ++ return offsetof(ActualCP6, parameters_); ++ case 7: ++ return offsetof(ActualCP7, parameters_); ++ case 8: ++ return offsetof(ActualCP8, parameters_); ++ case 9: ++ return offsetof(ActualCP9, parameters_); ++ default: ++ return 0; ++ } ++} ++ + // Verifies that the declared sizes of an IPC buffer are within range. + bool IsSizeWithinRange(uint32_t buffer_size, + uint32_t min_declared_size, + uint32_t declared_size) { + if ((buffer_size < min_declared_size) || + (sizeof(CrossCallParamsEx) > min_declared_size)) { + // Minimal computed size bigger than existing buffer or param_count + // integer overflow. +@@ -133,18 +163,17 @@ CrossCallParamsEx* CrossCallParamsEx::Cr + // will catch memory access violations so we don't crash. + __try { + CrossCallParams* call_params = + reinterpret_cast<CrossCallParams*>(buffer_base); + + // Check against the minimum size given the number of stated params + // if too small we bail out. + param_count = call_params->GetParamsCount(); +- min_declared_size = +- sizeof(CrossCallParams) + ((param_count + 1) * sizeof(ParamInfo)); ++ min_declared_size = GetMinDeclaredActualCallParamsSize(param_count); + + // Initial check for the buffer being big enough to determine the actual + // buffer size. + if (buffer_size < min_declared_size) + return nullptr; + + // Retrieve the declared size which if it fails returns 0. + declared_size = GetActualBufferSize(param_count, buffer_base); +@@ -158,18 +187,17 @@ CrossCallParamsEx* CrossCallParamsEx::Cr + copied_params = reinterpret_cast<CrossCallParamsEx*>(backing_mem); + memcpy(backing_mem, call_params, declared_size); + + // 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); + +- min_declared_size = +- sizeof(CrossCallParams) + ((param_count + 1) * sizeof(ParamInfo)); ++ min_declared_size = GetMinDeclaredActualCallParamsSize(param_count); + + // Check that the copied buffer is still valid. + if (copied_params->GetParamsCount() != param_count || + GetActualBufferSize(param_count, backing_mem) != declared_size || + !IsSizeWithinRange(buffer_size, min_declared_size, declared_size)) { + delete[] backing_mem; + return nullptr; + } diff --git a/security/sandbox/chromium-shim/patches/with_update/mingw_operator_new.patch b/security/sandbox/chromium-shim/patches/with_update/mingw_operator_new.patch new file mode 100644 index 0000000000..ab223901ed --- /dev/null +++ b/security/sandbox/chromium-shim/patches/with_update/mingw_operator_new.patch @@ -0,0 +1,58 @@ +# HG changeset patch +# User Tom Ritter <tom@mozilla.com> +# Date 1489000606 0 +# Wed Mar 08 19:16:46 2017 +0000 +# Node ID 522c35c24e2a46d97430b5f15e7703bc1c33784c +# Parent a99512c712f6580537e3133e5fd1adc091583e95 +Bug 1230910 Declare operator new [](size_t, sandbox::AllocationType, void*) + +MozReview-Commit-ID: GCKj5Ao2Y2n + +diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_nt_util.cc b/security/sandbox/chromium/sandbox/win/src/sandbox_nt_util.cc +--- a/security/sandbox/chromium/sandbox/win/src/sandbox_nt_util.cc ++++ b/security/sandbox/chromium/sandbox/win/src/sandbox_nt_util.cc +@@ -663,16 +663,21 @@ void* operator new(size_t size, sandbox: + + // TODO: Returning nullptr from operator new has undefined behavior, but + // the Allocate() functions called above can return nullptr. Consider checking + // for nullptr here and crashing or throwing. + + return result; + } + ++void* operator new [](size_t size, sandbox::AllocationType type, ++ void* near_to) { ++ return operator new(size, type, near_to); ++} ++ + void operator delete(void* memory, sandbox::AllocationType type) { + if (type == sandbox::NT_ALLOC) { + // Use default flags. + VERIFY(sandbox::g_nt.RtlFreeHeap(sandbox::g_heap, 0, memory)); + } else if (type == sandbox::NT_PAGE) { + void* base = memory; + SIZE_T size = 0; + VERIFY_SUCCESS(sandbox::g_nt.FreeVirtualMemory(NtCurrentProcess, &base, +diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_nt_util.h b/security/sandbox/chromium/sandbox/win/src/sandbox_nt_util.h +--- a/security/sandbox/chromium/sandbox/win/src/sandbox_nt_util.h ++++ b/security/sandbox/chromium/sandbox/win/src/sandbox_nt_util.h +@@ -13,16 +13,19 @@ + #include "base/macros.h" + #include "sandbox/win/src/nt_internals.h" + #include "sandbox/win/src/sandbox_nt_types.h" + + // Placement new and delete to be used from ntdll interception code. + void* __cdecl operator new(size_t size, + sandbox::AllocationType type, + void* near_to = nullptr); ++void* __cdecl operator new[](size_t size, ++ sandbox::AllocationType type, ++ void* near_to = nullptr); + void __cdecl operator delete(void* memory, sandbox::AllocationType type); + // Add operator delete that matches the placement form of the operator new + // above. This is required by compiler to generate code to call operator delete + // in case the object's constructor throws an exception. + // See http://msdn.microsoft.com/en-us/library/cxdxz3x6.aspx + void __cdecl operator delete(void* memory, + sandbox::AllocationType type, + void* near_to); diff --git a/security/sandbox/chromium-shim/patches/with_update/more_chromium_linux_x86_x64_syscalls.patch b/security/sandbox/chromium-shim/patches/with_update/more_chromium_linux_x86_x64_syscalls.patch new file mode 100644 index 0000000000..4b32171d04 --- /dev/null +++ b/security/sandbox/chromium-shim/patches/with_update/more_chromium_linux_x86_x64_syscalls.patch @@ -0,0 +1,91 @@ +# HG changeset patch +# User Gian-Carlo Pascutto <gcp@mozilla.com> +# Date 1573118511 0 +# Thu Nov 07 09:21:51 2019 +0000 +# Node ID a0be746532f437055e4190cc8db802ad1239405e +# Parent f5df610ae207f14f233874e2f1502c137b4f94ab +Bug 1591117 - Report ENOSYS on statx, but allow membarrier. r=jld + +Differential Revision: https://phabricator.services.mozilla.com/D50623 + +diff --git a/security/sandbox/chromium/sandbox/linux/system_headers/x86_64_linux_syscalls.h b/security/sandbox/chromium/sandbox/linux/system_headers/x86_64_linux_syscalls.h +--- a/security/sandbox/chromium/sandbox/linux/system_headers/x86_64_linux_syscalls.h ++++ b/security/sandbox/chromium/sandbox/linux/system_headers/x86_64_linux_syscalls.h +@@ -1,13 +1,17 @@ + // 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. + +-// Generated from the Linux kernel's syscall_64.tbl. ++/* Constructed by running a vim macro over ++ linux-kernel/arch/x86/entry/syscalls/syscall_64.tbl ++ version 39a38bcba4ab6e5285b07675b0e42c96eec35e67 ++ which is close to Linux 5.4. ++*/ + #ifndef SANDBOX_LINUX_SYSTEM_HEADERS_X86_64_LINUX_SYSCALLS_H_ + #define SANDBOX_LINUX_SYSTEM_HEADERS_X86_64_LINUX_SYSCALLS_H_ + + #if !defined(__x86_64__) + #error "Including header on wrong architecture" + #endif + + #if !defined(__NR_read) +@@ -1345,10 +1349,57 @@ + #if !defined(__NR_io_pgetevents) + #define __NR_io_pgetevents 333 + #endif + + #if !defined(__NR_rseq) + #define __NR_rseq 334 + #endif + ++#if !defined(__NR_pidfd_send_signal) ++#define __NR_pidfd_send_signal 424 ++#endif ++ ++#if !defined(__NR_io_uring_setup) ++#define __NR_io_uring_setup 425 ++#endif ++ ++#if !defined(__NR_io_uring_enter) ++#define __NR_io_uring_enter 426 ++#endif ++ ++#if !defined(__NR_io_uring_register) ++#define __NR_io_uring_register 427 ++#endif ++ ++#if !defined(__NR_open_tree) ++#define __NR_open_tree 428 ++#endif ++ ++#if !defined(__NR_move_mount) ++#define __NR_move_mount 429 ++#endif ++ ++#if !defined(__NR_fsopen) ++#define __NR_fsopen 430 ++#endif ++ ++#if !defined(__NR_fsconfig) ++#define __NR_fsconfig 431 ++#endif ++ ++#if !defined(__NR_fsmount) ++#define __NR_fsmount 432 ++#endif ++ ++#if !defined(__NR_fspick) ++#define __NR_fspick 433 ++#endif ++ ++#if !defined(__NR_pidfd_open) ++#define __NR_pidfd_open 434 ++#endif ++ ++#if !defined(__NR_clone3) ++#define __NR_clone3 435 ++#endif ++ + #endif // SANDBOX_LINUX_SYSTEM_HEADERS_X86_64_LINUX_SYSCALLS_H_ +- diff --git a/security/sandbox/chromium-shim/patches/with_update/patch_order.txt b/security/sandbox/chromium-shim/patches/with_update/patch_order.txt new file mode 100755 index 0000000000..8d40aeaa7f --- /dev/null +++ b/security/sandbox/chromium-shim/patches/with_update/patch_order.txt @@ -0,0 +1,34 @@ +revert_remove_AddTargetPeer.patch +revert_remove_BrokerDuplicateHandle.patch +replace_ScopedNativeLibrary_in_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 +mingw_copy_s.patch +mingw_operator_new.patch +mingw_cast_getprocaddress.patch +mingw_capitalization.patch +mingw_disable_one_try.patch +mingw_offsetof.patch +allow_env_changes.patch +ifdef_out_AppContainerProfileBase_testing_functions.patch +mingw_missing_windows_types_defines.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_extraneous_backslash_introduced_by_clang_tidy.patch +use_mfbt_double_conversion.patch +remove_include_delayimp_h_from_pe_image_cc.patch +lower_SDK_version_requirement.patch +add_CET_STRICT_MODE.patch +broker_complex_line_breaks.patch +allow_reparse_points.patch +derive_sid_from_name.patch +add_loongarch_defines.patch +block_NtImpersonateAnonymousToken_before_LowerToken.patch +fix_broker_alive_mutex.patch diff --git a/security/sandbox/chromium-shim/patches/with_update/remove_extraneous_backslash_introduced_by_clang_tidy.patch b/security/sandbox/chromium-shim/patches/with_update/remove_extraneous_backslash_introduced_by_clang_tidy.patch new file mode 100644 index 0000000000..431a5e102c --- /dev/null +++ b/security/sandbox/chromium-shim/patches/with_update/remove_extraneous_backslash_introduced_by_clang_tidy.patch @@ -0,0 +1,34 @@ +# 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: diff --git a/security/sandbox/chromium-shim/patches/with_update/remove_include_delayimp_h_from_pe_image_cc.patch b/security/sandbox/chromium-shim/patches/with_update/remove_include_delayimp_h_from_pe_image_cc.patch new file mode 100644 index 0000000000..4f08f57011 --- /dev/null +++ b/security/sandbox/chromium-shim/patches/with_update/remove_include_delayimp_h_from_pe_image_cc.patch @@ -0,0 +1,32 @@ +# 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 { diff --git a/security/sandbox/chromium-shim/patches/with_update/replace_ScopedNativeLibrary_in_ApplyMitigationsToCurrentThread.patch b/security/sandbox/chromium-shim/patches/with_update/replace_ScopedNativeLibrary_in_ApplyMitigationsToCurrentThread.patch new file mode 100644 index 0000000000..47418009d6 --- /dev/null +++ b/security/sandbox/chromium-shim/patches/with_update/replace_ScopedNativeLibrary_in_ApplyMitigationsToCurrentThread.patch @@ -0,0 +1,59 @@ +# 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; + } diff --git a/security/sandbox/chromium-shim/patches/with_update/revert_Token_serialization_and_deserialization.patch b/security/sandbox/chromium-shim/patches/with_update/revert_Token_serialization_and_deserialization.patch new file mode 100644 index 0000000000..c2d96dda78 --- /dev/null +++ b/security/sandbox/chromium-shim/patches/with_update/revert_Token_serialization_and_deserialization.patch @@ -0,0 +1,100 @@ +# 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_ diff --git a/security/sandbox/chromium-shim/patches/with_update/revert_removal_of_app_dir_for_DLL_load.patch b/security/sandbox/chromium-shim/patches/with_update/revert_removal_of_app_dir_for_DLL_load.patch new file mode 100644 index 0000000000..c5de8c9041 --- /dev/null +++ b/security/sandbox/chromium-shim/patches/with_update/revert_removal_of_app_dir_for_DLL_load.patch @@ -0,0 +1,74 @@ +# HG changeset patch +# User Bob Owen <bobowencode@gmail.com> +# Date 1564062993 -3600 +# Thu Jul 25 14:56:33 2019 +0100 +# Node ID aa8f8da7b00f1f751bf4a7c8a2cc58b290a328e0 +# Parent 69ac304560c98a733d44a0245fe9782dc6a465e2 +Bug 1565848: Revert latest change to MITIGATION_DLL_SEARCH_ORDER. r=handyman! + +This is until any regressions can be fixed, see bug 1568850. + +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 +@@ -72,26 +72,17 @@ bool ApplyProcessMitigationsToCurrentPro + + if (flags & MITIGATION_DLL_SEARCH_ORDER) { + SetDefaultDllDirectoriesFunction set_default_dll_directories = + reinterpret_cast<SetDefaultDllDirectoriesFunction>( + ::GetProcAddress(module, "SetDefaultDllDirectories")); + + // Check for SetDefaultDllDirectories since it requires KB2533623. + if (set_default_dll_directories) { +-#if defined(COMPONENT_BUILD) +- const DWORD directory_flags = LOAD_LIBRARY_SEARCH_DEFAULT_DIRS; +-#else +- // In a non-component build, all DLLs will be loaded manually, or via +- // manifest definition, so these flags can be stronger. This prevents DLL +- // planting in the application directory. +- const DWORD directory_flags = +- LOAD_LIBRARY_SEARCH_SYSTEM32 | LOAD_LIBRARY_SEARCH_USER_DIRS; +-#endif +- if (!set_default_dll_directories(directory_flags) && ++ if (!set_default_dll_directories(LOAD_LIBRARY_SEARCH_DEFAULT_DIRS) && + ERROR_ACCESS_DENIED != ::GetLastError()) { + return false; + } + } + } + + // Set the heap to terminate on corruption + if (flags & MITIGATION_HEAP_TERMINATE) { +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 +@@ -192,25 +192,20 @@ const MitigationFlags MITIGATION_BOTTOM_ + // PROCESS_CREATION_MITIGATION_POLICY_HIGH_ENTROPY_ASLR_ALWAYS_ON + const MitigationFlags MITIGATION_HIGH_ENTROPY_ASLR = 0x00000080; + + // Immediately raises an exception on a bad handle reference. Must be + // enabled after startup. Corresponds to + // PROCESS_CREATION_MITIGATION_POLICY_STRICT_HANDLE_CHECKS_ALWAYS_ON. + const MitigationFlags MITIGATION_STRICT_HANDLE_CHECKS = 0x00000100; + +-// Strengthens the DLL search order. See +-// http://msdn.microsoft.com/en-us/library/windows/desktop/hh310515. In a +-// component build - sets this to LOAD_LIBRARY_SEARCH_DEFAULT_DIRS allowing +-// additional directories to be added via Windows AddDllDirectory() function, +-// but preserving current load order. In a non-component build, all DLLs should +-// be loaded manually, so strenthen to LOAD_LIBRARY_SEARCH_SYSTEM32 | +-// LOAD_LIBRARY_SEARCH_USER_DIRS, removing LOAD_LIBRARY_SEARCH_APPLICATION_DIR, +-// preventing DLLs being implicitly loaded from the application path. Must be +-// enabled after startup. ++// Sets the DLL search order to LOAD_LIBRARY_SEARCH_DEFAULT_DIRS. Additional
++// directories can be added via the Windows AddDllDirectory() function.
++// http://msdn.microsoft.com/en-us/library/windows/desktop/hh310515
++// Must be enabled after startup. + const MitigationFlags MITIGATION_DLL_SEARCH_ORDER = 0x00000200; + + // Changes the mandatory integrity level policy on the current process' token + // to enable no-read and no-execute up. This prevents a lower IL process from + // opening the process token for impersonate/duplicate/assignment. + const MitigationFlags MITIGATION_HARDEN_TOKEN_IL_POLICY = 0x00000400; + + // Prevents the process from making Win32k calls. Corresponds to diff --git a/security/sandbox/chromium-shim/patches/with_update/revert_remove_AddTargetPeer.patch b/security/sandbox/chromium-shim/patches/with_update/revert_remove_AddTargetPeer.patch new file mode 100644 index 0000000000..04020b60b7 --- /dev/null +++ b/security/sandbox/chromium-shim/patches/with_update/revert_remove_AddTargetPeer.patch @@ -0,0 +1,310 @@ +# 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 + +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 + +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 { + 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)) { + // Cannot clean broker services. + NOTREACHED(); + return; + } + thread_pool_.reset(); ++ ::DeleteCriticalSection(&lock_); + } + + scoped_refptr<TargetPolicy> BrokerServicesBase::CreatePolicy() { + // If you change the type of the object being created here you must also + // 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); + } + 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; + } + 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; + } +- 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)); + } + + *target_info = process_info.Take(); + return result; + } + + ResultCode BrokerServicesBase::WaitForAllTargets() { + ::WaitForSingleObject(no_targets_.Get(), INFINITE); + return SBOX_ALL_OK; + } + ++bool BrokerServicesBase::IsSafeDuplicationTarget(DWORD process_id) { ++ AutoLock lock(&lock_); ++ return active_targets_.find(process_id) != active_targets_.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; ++} ++ ++ResultCode BrokerServicesBase::AddTargetPeer(HANDLE peer_process) { ++ DWORD last_error; ++ return AddTargetPeerInternal(peer_process, ::GetProcessId(peer_process), ++ nullptr, &last_error); ++} ++ + 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); +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" + #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 sandbox { + + // BrokerServicesBase --------------------------------------------------------- + // Broker implementation version 0 +@@ -43,16 +44,24 @@ class BrokerServicesBase final : public + scoped_refptr<TargetPolicy> CreatePolicy() override; + ResultCode SpawnTarget(const wchar_t* exe_path, + const wchar_t* command_line, + scoped_refptr<TargetPolicy> policy, + ResultCode* last_warning, + DWORD* last_error, + 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; + + private: + // 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 + base::win::ScopedHandle no_targets_; + + // Handle to the worker thread that reacts to job notifications. + base::win::ScopedHandle job_thread_; + + // 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); ++ + 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 { + + // This call blocks (waits) for all the targets to terminate. + // Returns: + // ALL_OK if successful. All other return values imply failure. + // 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: ++ // ALL_OK if successful. All other return values imply failure. ++ // 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 diff --git a/security/sandbox/chromium-shim/patches/with_update/revert_remove_BrokerDuplicateHandle.patch b/security/sandbox/chromium-shim/patches/with_update/revert_remove_BrokerDuplicateHandle.patch new file mode 100644 index 0000000000..970c0d1db2 --- /dev/null +++ b/security/sandbox/chromium-shim/patches/with_update/revert_remove_BrokerDuplicateHandle.patch @@ -0,0 +1,743 @@ +# 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 + +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 + +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 @@ ++// Copyright (c) 2012 The Chromium Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style license that can be ++// found in the LICENSE file. ++ ++#include "sandbox/win/src/handle_dispatcher.h" ++ ++#include <stdint.h> ++ ++#include "base/win/scoped_handle.h" ++#include "sandbox/win/src/handle_interception.h" ++#include "sandbox/win/src/handle_policy.h" ++#include "sandbox/win/src/ipc_tags.h" ++#include "sandbox/win/src/policy_broker.h" ++#include "sandbox/win/src/policy_params.h" ++#include "sandbox/win/src/sandbox.h" ++#include "sandbox/win/src/sandbox_nt_util.h" ++#include "sandbox/win/src/sandbox_types.h" ++#include "sandbox/win/src/sandbox_utils.h" ++ ++namespace sandbox { ++ ++HandleDispatcher::HandleDispatcher(PolicyBase* policy_base) ++ : policy_base_(policy_base) { ++ static const IPCCall duplicate_handle_proxy = { ++ {IpcTag::DUPLICATEHANDLEPROXY, ++ {VOIDPTR_TYPE, UINT32_TYPE, UINT32_TYPE, UINT32_TYPE}}, ++ reinterpret_cast<CallbackGeneric>( ++ &HandleDispatcher::DuplicateHandleProxy)}; ++ ++ ipc_calls_.push_back(duplicate_handle_proxy); ++} ++ ++bool HandleDispatcher::SetupService(InterceptionManager* manager, ++ IpcTag service) { ++ // We perform no interceptions for handles right now. ++ switch (service) { ++ case IpcTag::DUPLICATEHANDLEPROXY: ++ return true; ++ ++ default: ++ return false; ++ } ++} ++ ++bool HandleDispatcher::DuplicateHandleProxy(IPCInfo* ipc, ++ HANDLE source_handle, ++ uint32_t target_process_id, ++ uint32_t desired_access, ++ uint32_t options) { ++ static NtQueryObject QueryObject = NULL; ++ if (!QueryObject) ++ ResolveNTFunctionPtr("NtQueryObject", &QueryObject); ++ ++ // Get a copy of the handle for use in the broker process. ++ HANDLE handle_temp; ++ if (!::DuplicateHandle(ipc->client_info->process, source_handle, ++ ::GetCurrentProcess(), &handle_temp, ++ 0, FALSE, DUPLICATE_SAME_ACCESS | options)) { ++ ipc->return_info.win32_result = ::GetLastError(); ++ return false; ++ } ++ options &= ~DUPLICATE_CLOSE_SOURCE; ++ base::win::ScopedHandle handle(handle_temp); ++ ++ // Get the object type (32 characters is safe; current max is 14). ++ BYTE buffer[sizeof(OBJECT_TYPE_INFORMATION) + 32 * sizeof(wchar_t)]; ++ OBJECT_TYPE_INFORMATION* type_info = ++ reinterpret_cast<OBJECT_TYPE_INFORMATION*>(buffer); ++ ULONG size = sizeof(buffer) - sizeof(wchar_t); ++ NTSTATUS error = ++ QueryObject(handle.Get(), ObjectTypeInformation, type_info, size, &size); ++ if (!NT_SUCCESS(error)) { ++ ipc->return_info.nt_status = error; ++ return false; ++ } ++ type_info->Name.Buffer[type_info->Name.Length / sizeof(wchar_t)] = L'\0'; ++ ++ CountedParameterSet<HandleTarget> params; ++ params[HandleTarget::NAME] = ParamPickerMake(type_info->Name.Buffer); ++ params[HandleTarget::TARGET] = ParamPickerMake(target_process_id); ++ ++ EvalResult eval = policy_base_->EvalPolicy(IpcTag::DUPLICATEHANDLEPROXY, ++ params.GetBase()); ++ ipc->return_info.win32_result = ++ HandlePolicy::DuplicateHandleProxyAction(eval, handle.Get(), ++ target_process_id, ++ &ipc->return_info.handle, ++ desired_access, options); ++ return true; ++} ++ ++} // namespace sandbox ++ +diff --git a/security/sandbox/chromium/sandbox/win/src/handle_dispatcher.h b/security/sandbox/chromium/sandbox/win/src/handle_dispatcher.h +new file mode 100644 +--- /dev/null ++++ b/security/sandbox/chromium/sandbox/win/src/handle_dispatcher.h +@@ -0,0 +1,41 @@ ++// 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 SANDBOX_SRC_HANDLE_DISPATCHER_H_ ++#define SANDBOX_SRC_HANDLE_DISPATCHER_H_ ++ ++#include <stdint.h> ++ ++#include "base/macros.h" ++#include "sandbox/win/src/crosscall_server.h" ++#include "sandbox/win/src/sandbox_policy_base.h" ++ ++namespace sandbox { ++ ++// This class handles handle-related IPC calls. ++class HandleDispatcher : public Dispatcher { ++ public: ++ explicit HandleDispatcher(PolicyBase* policy_base); ++ ~HandleDispatcher() override {} ++ ++ // Dispatcher interface. ++ bool SetupService(InterceptionManager* manager, IpcTag service) override; ++ ++ private: ++ // Processes IPC requests coming from calls to ++ // TargetServices::DuplicateHandle() in the target. ++ bool DuplicateHandleProxy(IPCInfo* ipc, ++ HANDLE source_handle, ++ uint32_t target_process_id, ++ uint32_t desired_access, ++ uint32_t options); ++ ++ PolicyBase* policy_base_; ++ DISALLOW_COPY_AND_ASSIGN(HandleDispatcher); ++}; ++ ++} // namespace sandbox ++ ++#endif // SANDBOX_SRC_HANDLE_DISPATCHER_H_ ++ +diff --git a/security/sandbox/chromium/sandbox/win/src/handle_interception.cc b/security/sandbox/chromium/sandbox/win/src/handle_interception.cc +new file mode 100644 +--- /dev/null ++++ b/security/sandbox/chromium/sandbox/win/src/handle_interception.cc +@@ -0,0 +1,45 @@ ++// Copyright (c) 2012 The Chromium Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style license that can be ++// found in the LICENSE file. ++ ++#include "sandbox/win/src/handle_interception.h" ++ ++#include "sandbox/win/src/crosscall_client.h" ++#include "sandbox/win/src/ipc_tags.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" ++ ++namespace sandbox { ++ ++ResultCode DuplicateHandleProxy(HANDLE source_handle, ++ DWORD target_process_id, ++ HANDLE* target_handle, ++ DWORD desired_access, ++ DWORD options) { ++ *target_handle = NULL; ++ ++ void* memory = GetGlobalIPCMemory(); ++ if (NULL == memory) ++ return SBOX_ERROR_NO_SPACE; ++ ++ SharedMemIPCClient ipc(memory); ++ CrossCallReturn answer = {0}; ++ ResultCode code = CrossCall(ipc, IpcTag::DUPLICATEHANDLEPROXY, ++ source_handle, target_process_id, ++ desired_access, options, &answer); ++ if (SBOX_ALL_OK != code) ++ return code; ++ ++ if (answer.win32_result) { ++ ::SetLastError(answer.win32_result); ++ return SBOX_ERROR_GENERIC; ++ } ++ ++ *target_handle = answer.handle; ++ return SBOX_ALL_OK; ++} ++ ++} // namespace sandbox ++ +diff --git a/security/sandbox/chromium/sandbox/win/src/handle_interception.h b/security/sandbox/chromium/sandbox/win/src/handle_interception.h +new file mode 100644 +--- /dev/null ++++ b/security/sandbox/chromium/sandbox/win/src/handle_interception.h +@@ -0,0 +1,24 @@ ++// Copyright (c) 2012 The Chromium Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style license that can be ++// found in the LICENSE file. ++ ++#include "sandbox/win/src/nt_internals.h" ++#include "sandbox/win/src/sandbox_types.h" ++ ++#ifndef SANDBOX_SRC_HANDLE_INTERCEPTION_H_ ++#define SANDBOX_SRC_HANDLE_INTERCEPTION_H_ ++ ++namespace sandbox { ++ ++// TODO(jschuh) Add an interception to catch dangerous DuplicateHandle calls. ++ ++ResultCode DuplicateHandleProxy(HANDLE source_handle, ++ DWORD target_process_id, ++ HANDLE* target_handle, ++ DWORD desired_access, ++ DWORD options); ++ ++} // namespace sandbox ++ ++#endif // SANDBOX_SRC_HANDLE_INTERCEPTION_H_ ++ +diff --git a/security/sandbox/chromium/sandbox/win/src/handle_policy.cc b/security/sandbox/chromium/sandbox/win/src/handle_policy.cc +new file mode 100644 +--- /dev/null ++++ b/security/sandbox/chromium/sandbox/win/src/handle_policy.cc +@@ -0,0 +1,93 @@ ++// Copyright (c) 2012 The Chromium Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style license that can be ++// found in the LICENSE file. ++ ++#include "sandbox/win/src/handle_policy.h" ++ ++#include <string> ++ ++#include "base/win/scoped_handle.h" ++#include "sandbox/win/src/broker_services.h" ++#include "sandbox/win/src/ipc_tags.h" ++#include "sandbox/win/src/policy_engine_opcodes.h" ++#include "sandbox/win/src/policy_params.h" ++#include "sandbox/win/src/sandbox_types.h" ++#include "sandbox/win/src/sandbox_utils.h" ++ ++namespace sandbox { ++ ++bool HandlePolicy::GenerateRules(const wchar_t* type_name, ++ TargetPolicy::Semantics semantics, ++ LowLevelPolicy* policy) { ++ PolicyRule duplicate_rule(ASK_BROKER); ++ ++ switch (semantics) { ++ case TargetPolicy::HANDLES_DUP_ANY: { ++ if (!duplicate_rule.AddNumberMatch(IF_NOT, HandleTarget::TARGET, ++ ::GetCurrentProcessId(), EQUAL)) { ++ return false; ++ } ++ break; ++ } ++ ++ case TargetPolicy::HANDLES_DUP_BROKER: { ++ if (!duplicate_rule.AddNumberMatch(IF, HandleTarget::TARGET, ++ ::GetCurrentProcessId(), EQUAL)) { ++ return false; ++ } ++ break; ++ } ++ ++ default: ++ return false; ++ } ++ if (!duplicate_rule.AddStringMatch(IF, HandleTarget::NAME, type_name, ++ CASE_INSENSITIVE)) { ++ return false; ++ } ++ if (!policy->AddRule(IpcTag::DUPLICATEHANDLEPROXY, &duplicate_rule)) { ++ return false; ++ } ++ return true; ++} ++ ++DWORD HandlePolicy::DuplicateHandleProxyAction(EvalResult eval_result, ++ HANDLE source_handle, ++ DWORD target_process_id, ++ HANDLE* target_handle, ++ DWORD desired_access, ++ DWORD options) { ++ // The only action supported is ASK_BROKER which means duplicate the handle. ++ if (ASK_BROKER != eval_result) { ++ return ERROR_ACCESS_DENIED; ++ } ++ ++ 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)) { ++ return ERROR_ACCESS_DENIED; ++ } ++ ++ remote_target_process.Set(::OpenProcess(PROCESS_DUP_HANDLE, FALSE, ++ target_process_id)); ++ if (!remote_target_process.IsValid()) ++ return ::GetLastError(); ++ } ++ ++ // If the policy didn't block us and we have no valid target, then the broker ++ // (this process) is the valid target. ++ HANDLE target_process = remote_target_process.IsValid() ? ++ remote_target_process.Get() : ::GetCurrentProcess(); ++ if (!::DuplicateHandle(::GetCurrentProcess(), source_handle, target_process, ++ target_handle, desired_access, FALSE, ++ options)) { ++ return ::GetLastError(); ++ } ++ ++ return ERROR_SUCCESS; ++} ++ ++} // namespace sandbox ++ +diff --git a/security/sandbox/chromium/sandbox/win/src/handle_policy.h b/security/sandbox/chromium/sandbox/win/src/handle_policy.h +new file mode 100644 +--- /dev/null ++++ b/security/sandbox/chromium/sandbox/win/src/handle_policy.h +@@ -0,0 +1,39 @@ ++// 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 SANDBOX_SRC_HANDLE_POLICY_H_ ++#define SANDBOX_SRC_HANDLE_POLICY_H_ ++ ++#include <string> ++ ++#include "sandbox/win/src/crosscall_server.h" ++#include "sandbox/win/src/policy_low_level.h" ++#include "sandbox/win/src/sandbox_policy.h" ++ ++namespace sandbox { ++ ++enum EvalResult; ++ ++// This class centralizes most of the knowledge related to handle policy. ++class HandlePolicy { ++ public: ++ // Creates the required low-level policy rules to evaluate a high-level ++ // policy rule for handles, in particular duplicate action. ++ static bool GenerateRules(const wchar_t* type_name, ++ TargetPolicy::Semantics semantics, ++ LowLevelPolicy* policy); ++ ++ // Processes a 'TargetPolicy::DuplicateHandle()' request from the target. ++ static DWORD DuplicateHandleProxyAction(EvalResult eval_result, ++ HANDLE source_handle, ++ DWORD target_process_id, ++ HANDLE* target_handle, ++ DWORD desired_access, ++ DWORD options); ++}; ++ ++} // namespace sandbox ++ ++#endif // SANDBOX_SRC_HANDLE_POLICY_H_ ++ +diff --git a/security/sandbox/chromium/sandbox/win/src/handle_policy_test.cc b/security/sandbox/chromium/sandbox/win/src/handle_policy_test.cc +new file mode 100644 +--- /dev/null ++++ b/security/sandbox/chromium/sandbox/win/src/handle_policy_test.cc +@@ -0,0 +1,114 @@ ++// Copyright (c) 2012 The Chromium Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style license that can be ++// found in the LICENSE file. ++ ++#include "base/strings/stringprintf.h" ++#include "sandbox/win/src/handle_policy.h" ++#include "sandbox/win/src/nt_internals.h" ++#include "sandbox/win/src/sandbox.h" ++#include "sandbox/win/src/sandbox_factory.h" ++#include "sandbox/win/src/sandbox_policy.h" ++#include "sandbox/win/src/win_utils.h" ++#include "sandbox/win/tests/common/controller.h" ++#include "testing/gtest/include/gtest/gtest.h" ++ ++namespace sandbox { ++ ++// Just waits for the supplied number of milliseconds. ++SBOX_TESTS_COMMAND int Handle_WaitProcess(int argc, wchar_t **argv) { ++ if (argc != 1) ++ return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; ++ ++ ::Sleep(::wcstoul(argv[0], NULL, 10)); ++ return SBOX_TEST_TIMED_OUT; ++} ++ ++// Attempts to duplicate an event handle into the target process. ++SBOX_TESTS_COMMAND int Handle_DuplicateEvent(int argc, wchar_t **argv) { ++ if (argc != 1) ++ return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; ++ ++ // Create a test event to use as a handle. ++ base::win::ScopedHandle test_event; ++ test_event.Set(::CreateEvent(NULL, TRUE, TRUE, NULL)); ++ if (!test_event.IsValid()) ++ return SBOX_TEST_FIRST_ERROR; ++ ++ // Get the target process ID. ++ DWORD target_process_id = ::wcstoul(argv[0], NULL, 10); ++ ++ HANDLE handle = NULL; ++ ResultCode result = SandboxFactory::GetTargetServices()->DuplicateHandle( ++ test_event.Get(), target_process_id, &handle, 0, DUPLICATE_SAME_ACCESS); ++ ++ return (result == SBOX_ALL_OK) ? SBOX_TEST_SUCCEEDED : SBOX_TEST_DENIED; ++} ++ ++// Tests that duplicating an object works only when the policy allows it. ++TEST(HandlePolicyTest, DuplicateHandle) { ++ TestRunner target; ++ TestRunner runner; ++ ++ // Kick off an asynchronous target process for testing. ++ target.SetAsynchronous(true); ++ EXPECT_EQ(SBOX_TEST_SUCCEEDED, target.RunTest(L"Handle_WaitProcess 30000")); ++ ++ // First test that we fail to open the event. ++ base::string16 cmd_line = base::StringPrintf(L"Handle_DuplicateEvent %d", ++ target.process_id()); ++ EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(cmd_line.c_str())); ++ ++ // Now successfully open the event after adding a duplicate handle rule. ++ EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_HANDLES, ++ TargetPolicy::HANDLES_DUP_ANY, ++ L"Event")); ++ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(cmd_line.c_str())); ++} ++ ++// Tests that duplicating an object works only when the policy allows it. ++TEST(HandlePolicyTest, DuplicatePeerHandle) { ++ TestRunner target; ++ TestRunner runner; ++ ++ // Kick off an asynchronous target process for testing. ++ target.SetAsynchronous(true); ++ target.SetUnsandboxed(true); ++ EXPECT_EQ(SBOX_TEST_SUCCEEDED, target.RunTest(L"Handle_WaitProcess 30000")); ++ ++ // First test that we fail to open the event. ++ base::string16 cmd_line = base::StringPrintf(L"Handle_DuplicateEvent %d", ++ target.process_id()); ++ EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(cmd_line.c_str())); ++ ++ // Now successfully open the event after adding a duplicate handle rule. ++ EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_HANDLES, ++ TargetPolicy::HANDLES_DUP_ANY, ++ L"Event")); ++ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(cmd_line.c_str())); ++} ++ ++// Tests that duplicating an object works only when the policy allows it. ++TEST(HandlePolicyTest, DuplicateBrokerHandle) { ++ TestRunner runner; ++ ++ // First test that we fail to open the event. ++ base::string16 cmd_line = base::StringPrintf(L"Handle_DuplicateEvent %d", ++ ::GetCurrentProcessId()); ++ EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(cmd_line.c_str())); ++ ++ // Add the peer rule and make sure we fail again. ++ EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_HANDLES, ++ TargetPolicy::HANDLES_DUP_ANY, ++ L"Event")); ++ EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(cmd_line.c_str())); ++ ++ ++ // Now successfully open the event after adding a broker handle rule. ++ EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_HANDLES, ++ TargetPolicy::HANDLES_DUP_BROKER, ++ L"Event")); ++ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(cmd_line.c_str())); ++} ++ ++} // namespace sandbox ++ +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, +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 { + // fails the current process could be terminated immediately. + virtual void LowerToken() = 0; + + // Returns the ProcessState object. Through that object it's possible to have + // 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 ++ // handle duplication for this object type. ++ // Returns: ++ // ALL_OK if successful. All other return values imply failure. ++ // If the return is ERROR_GENERIC, you can call ::GetLastError() to get ++ // more information. ++ virtual ResultCode DuplicateHandle(HANDLE source_handle, ++ DWORD target_process_id, ++ 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. +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 { + // 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. + }; + + // Allowable semantics when a rule is matched. + enum Semantics { + FILES_ALLOW_ANY, // Allows open or create for any kind of access that + // the file system supports. + FILES_ALLOW_READONLY, // Allows open or create with read access only. + FILES_ALLOW_QUERY, // Allows access to query the attributes of a file. + FILES_ALLOW_DIR_ANY, // Allows open or create with directory semantics + // only. ++ HANDLES_DUP_ANY, // Allows duplicating handles opened with any ++ // access permissions. ++ HANDLES_DUP_BROKER, // Allows duplicating handles to the broker process. + NAMEDPIPES_ALLOW_ANY, // Allows creation of a named pipe. + PROCESS_MIN_EXEC, // Allows to create a process with minimal rights + // over the resulting process and thread handles. + // No other parameters besides the command line are + // passed to the child process. + PROCESS_ALL_EXEC, // Allows the creation of a process and return full + // access on the returned handles. + // This flag can be used only when the main token of +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 @@ + #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" + #include "sandbox/win/src/job.h" + #include "sandbox/win/src/named_pipe_policy.h" + #include "sandbox/win/src/policy_broker.h" + #include "sandbox/win/src/policy_engine_processor.h" + #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 + } + case SUBSYS_REGISTRY: { + if (!RegistryPolicy::GenerateRules(pattern, semantics, policy_maker_)) { + NOTREACHED(); + return SBOX_ERROR_BAD_PARAMS; + } + break; + } ++ case SUBSYS_HANDLES: { ++ if (!HandlePolicy::GenerateRules(pattern, semantics, policy_maker_)) { ++ NOTREACHED(); ++ return SBOX_ERROR_BAD_PARAMS; ++ } ++ break; ++ } ++ + 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."; +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 +@@ -7,16 +7,17 @@ + #include <new> + + #include <process.h> + #include <stdint.h> + + #include "base/win/windows_version.h" + #include "sandbox/win/src/crosscall_client.h" + #include "sandbox/win/src/handle_closer_agent.h" ++#include "sandbox/win/src/handle_interception.h" + #include "sandbox/win/src/heap_helper.h" + #include "sandbox/win/src/ipc_tags.h" + #include "sandbox/win/src/process_mitigations.h" + #include "sandbox/win/src/restricted_token_utils.h" + #include "sandbox/win/src/sandbox.h" + #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; + } + + void ProcessState::SetCsrssConnected(bool csrss_connected) { + csrss_connected_ = csrss_connected; + } + ++ ++ResultCode TargetServicesBase::DuplicateHandle(HANDLE source_handle, ++ DWORD target_process_id, ++ HANDLE* target_handle, ++ DWORD desired_access, ++ DWORD options) { ++ return sandbox::DuplicateHandleProxy(source_handle, target_process_id, ++ target_handle, desired_access, options); ++} ++ + } // namespace sandbox +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 { + class TargetServicesBase : public TargetServices { + public: + TargetServicesBase(); + + // Public interface of TargetServices. + ResultCode Init() override; + void LowerToken() override; + ProcessState* GetState() override; ++ ResultCode DuplicateHandle(HANDLE source_handle, ++ DWORD target_process_id, ++ HANDLE* target_handle, ++ DWORD desired_access, ++ DWORD options) override; + + // Factory method. + static TargetServicesBase* GetInstance(); + + // Sends a simple IPC Message that has a well-known answer. Returns true + // if the IPC was successful and false otherwise. There are 2 versions of + // this test: 1 and 2. The first one send a simple message while the + // second one send a message with an in/out param. +diff --git a/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.cc b/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.cc +--- a/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.cc ++++ b/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.cc +@@ -5,16 +5,17 @@ + #include "sandbox/win/src/top_level_dispatcher.h" + + #include <stdint.h> + #include <string.h> + + #include "base/logging.h" + #include "sandbox/win/src/crosscall_server.h" + #include "sandbox/win/src/filesystem_dispatcher.h" ++#include "sandbox/win/src/handle_dispatcher.h" + #include "sandbox/win/src/interception.h" + #include "sandbox/win/src/internal_types.h" + #include "sandbox/win/src/ipc_tags.h" + #include "sandbox/win/src/named_pipe_dispatcher.h" + #include "sandbox/win/src/process_mitigations_win32k_dispatcher.h" + #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; + 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; + registry_dispatcher_.reset(dispatcher); + ++ dispatcher = new HandleDispatcher(policy_); ++ ipc_targets_[static_cast<size_t>(IpcTag::DUPLICATEHANDLEPROXY)] = 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; diff --git a/security/sandbox/chromium-shim/patches/with_update/use_mfbt_double_conversion.patch b/security/sandbox/chromium-shim/patches/with_update/use_mfbt_double_conversion.patch new file mode 100644 index 0000000000..e6367793f1 --- /dev/null +++ b/security/sandbox/chromium-shim/patches/with_update/use_mfbt_double_conversion.patch @@ -0,0 +1,13 @@ +diff --git a/security/sandbox/chromium/base/strings/string_number_conversions.cc b/security/sandbox/chromium/base/strings/string_number_conversions.cc +index 8b71b0ae11363..3b5eda1fe3eb6 100644 +--- a/security/sandbox/chromium/base/strings/string_number_conversions.cc ++++ b/security/sandbox/chromium/base/strings/string_number_conversions.cc +@@ -17,7 +17,7 @@ + #include "base/numerics/safe_math.h" + #include "base/strings/string_util.h" + #include "base/strings/utf_string_conversions.h" +-#include "base/third_party/double_conversion/double-conversion/double-conversion.h" ++#include "double-conversion/double-conversion.h" + + namespace base { + diff --git a/security/sandbox/chromium-shim/sandbox/win/loggingCallbacks.h b/security/sandbox/chromium-shim/sandbox/win/loggingCallbacks.h new file mode 100644 index 0000000000..3c5f8eea89 --- /dev/null +++ b/security/sandbox/chromium-shim/sandbox/win/loggingCallbacks.h @@ -0,0 +1,101 @@ +/* -*- 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/. */ + +#ifndef security_sandbox_loggingCallbacks_h__ +#define security_sandbox_loggingCallbacks_h__ + +#include <sstream> + +#include "mozilla/Logging.h" +#include "mozilla/Preferences.h" +#include "mozilla/StaticPrefs_security.h" +#include "mozilla/sandboxing/loggingTypes.h" +#include "nsContentUtils.h" + +#include "mozilla/StackWalk.h" + +namespace mozilla { + +static LazyLogModule sSandboxTargetLog("SandboxTarget"); + +#define LOG_D(...) MOZ_LOG(sSandboxTargetLog, LogLevel::Debug, (__VA_ARGS__)) + +namespace sandboxing { + +// NS_WalkStackCallback to write a formatted stack frame to an ostringstream. +static void +StackFrameToOStringStream(uint32_t aFrameNumber, void* aPC, void* aSP, + void* aClosure) +{ + std::ostringstream* stream = static_cast<std::ostringstream*>(aClosure); + MozCodeAddressDetails details; + char buf[1024]; + MozDescribeCodeAddress(aPC, &details); + MozFormatCodeAddressDetails(buf, sizeof(buf), aFrameNumber, aPC, &details); + *stream << std::endl << "--" << buf; + stream->flush(); +} + +// Log to the browser console and, if DEBUG build, stderr. +static void +Log(const char* aMessageType, + const char* aFunctionName, + const char* aContext, + const bool aShouldLogStackTrace = false, + const void* aFirstFramePC = nullptr) +{ + std::ostringstream msgStream; + msgStream << "Process Sandbox " << aMessageType << ": " << aFunctionName; + if (aContext) { + msgStream << " for : " << aContext; + } + +#if defined(MOZ_SANDBOX) + // We can only log the stack trace on process types where we know that the + // sandbox won't prevent it. + if (XRE_IsContentProcess() && aShouldLogStackTrace) { + auto stackTraceDepth = + StaticPrefs::security_sandbox_windows_log_stackTraceDepth(); + if (stackTraceDepth) { + msgStream << std::endl << "Stack Trace:"; + MozStackWalk(StackFrameToOStringStream, aFirstFramePC, stackTraceDepth, + &msgStream); + } + } +#endif + std::string msg = msgStream.str(); +#if defined(DEBUG) + // Use NS_DebugBreak directly as we want child process prefix, but not source + // file or line number. + NS_DebugBreak(NS_DEBUG_WARNING, nullptr, msg.c_str(), nullptr, -1); +#endif + + if (nsContentUtils::IsInitialized()) { + nsContentUtils::LogMessageToConsole(msg.c_str()); + } + + // As we don't always have the facility to log to console use MOZ_LOG as well. + LOG_D("%s", msg.c_str()); +} + +// Initialize sandbox logging if required. +static void +InitLoggingIfRequired(ProvideLogFunctionCb aProvideLogFunctionCb) +{ + if (!aProvideLogFunctionCb) { + return; + } + + if (Preferences::GetBool("security.sandbox.logging.enabled") || + PR_GetEnv("MOZ_SANDBOX_LOGGING")) { + aProvideLogFunctionCb(Log); + } +} + +} // sandboxing +} // mozilla + +#endif // security_sandbox_loggingCallbacks_h__ diff --git a/security/sandbox/chromium-shim/sandbox/win/loggingTypes.h b/security/sandbox/chromium-shim/sandbox/win/loggingTypes.h new file mode 100644 index 0000000000..7b75648fc9 --- /dev/null +++ b/security/sandbox/chromium-shim/sandbox/win/loggingTypes.h @@ -0,0 +1,27 @@ +/* -*- 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/. */ + +#ifndef security_sandbox_loggingTypes_h__ +#define security_sandbox_loggingTypes_h__ + +#include <stdint.h> + +namespace mozilla { +namespace sandboxing { + +// We are using callbacks here that are passed in from the core code to prevent +// a circular dependency in the linking during the build. +typedef void (*LogFunction) (const char* aMessageType, + const char* aFunctionName, + const char* aContext, + const bool aShouldLogStackTrace, + const void* aFirstFramePC); +typedef void (*ProvideLogFunctionCb) (LogFunction aLogFunction); + +} // sandboxing +} // mozilla + +#endif // security_sandbox_loggingTypes_h__ diff --git a/security/sandbox/chromium-shim/sandbox/win/sandboxLogging.cpp b/security/sandbox/chromium-shim/sandbox/win/sandboxLogging.cpp new file mode 100644 index 0000000000..a556f9e772 --- /dev/null +++ b/security/sandbox/chromium-shim/sandbox/win/sandboxLogging.cpp @@ -0,0 +1,89 @@ +/* -*- 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 "sandboxLogging.h" + +#include "base/strings/utf_string_conversions.h" +#include "sandbox/win/src/sandbox_policy.h" +#include "mozilla/Attributes.h" +#include "mozilla/StackWalk.h" + +namespace mozilla { +namespace sandboxing { + +static LogFunction sLogFunction = nullptr; + +void +ProvideLogFunction(LogFunction aLogFunction) +{ + sLogFunction = aLogFunction; +} + +static void +LogBlocked(const char* aFunctionName, const char* aContext, const void* aFirstFramePC) +{ + if (sLogFunction) { + sLogFunction("BLOCKED", aFunctionName, aContext, + /* aShouldLogStackTrace */ true, aFirstFramePC); + } +} + +MOZ_NEVER_INLINE void +LogBlocked(const char* aFunctionName, const char* aContext) +{ + if (sLogFunction) { + LogBlocked(aFunctionName, aContext, CallerPC()); + } +} + +MOZ_NEVER_INLINE void +LogBlocked(const char* aFunctionName, const wchar_t* aContext) +{ + if (sLogFunction) { + LogBlocked(aFunctionName, base::WideToUTF8(aContext).c_str(), CallerPC()); + } +} + +MOZ_NEVER_INLINE void +LogBlocked(const char* aFunctionName, const wchar_t* aContext, + uint16_t aLengthInBytes) +{ + if (sLogFunction) { + LogBlocked(aFunctionName, + base::WideToUTF8(std::wstring(aContext, aLengthInBytes / sizeof(wchar_t))).c_str(), + CallerPC()); + } +} + +void +LogAllowed(const char* aFunctionName, const char* aContext) +{ + if (sLogFunction) { + sLogFunction("Broker ALLOWED", aFunctionName, aContext, + /* aShouldLogStackTrace */ false, nullptr); + } +} + +void +LogAllowed(const char* aFunctionName, const wchar_t* aContext) +{ + if (sLogFunction) { + LogAllowed(aFunctionName, base::WideToUTF8(aContext).c_str()); + } +} + +void +LogAllowed(const char* aFunctionName, const wchar_t* aContext, + uint16_t aLengthInBytes) +{ + if (sLogFunction) { + LogAllowed(aFunctionName, + base::WideToUTF8(std::wstring(aContext, aLengthInBytes / sizeof(wchar_t))).c_str()); + } +} + +} // sandboxing +} // mozilla diff --git a/security/sandbox/chromium-shim/sandbox/win/sandboxLogging.h b/security/sandbox/chromium-shim/sandbox/win/sandboxLogging.h new file mode 100644 index 0000000000..31c4ddb076 --- /dev/null +++ b/security/sandbox/chromium-shim/sandbox/win/sandboxLogging.h @@ -0,0 +1,50 @@ +/* -*- 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/. */ + +/* + * Set of helper methods to implement logging for Windows sandbox. + */ + +#ifndef security_sandbox_sandboxLogging_h__ +#define security_sandbox_sandboxLogging_h__ + +#include "loggingTypes.h" + +namespace sandbox { +class TargetPolicy; +} + +namespace mozilla { +namespace sandboxing { + +// This is used to pass a LogCallback to the sandboxing code, as the logging +// requires code to which we cannot link directly. +void ProvideLogFunction(LogFunction aLogFunction); + +// Log a "BLOCKED" msg to the browser console and, if DEBUG build, stderr. +// If the logging of a stack trace is enabled then a trace starting from the +// caller of the relevant LogBlocked overload will be logged, which should +// normally be the function that triggered the interception. +void LogBlocked(const char* aFunctionName, const char* aContext = nullptr); + +// Convenience functions to convert to char*. +void LogBlocked(const char* aFunctionName, const wchar_t* aContext); +void LogBlocked(const char* aFunctionName, const wchar_t* aContext, + uint16_t aLengthInBytes); + +// Log a "ALLOWED" msg to the browser console and, if DEBUG build, stderr. +void LogAllowed(const char* aFunctionName, const char* aContext = nullptr); + +// Convenience functions to convert to char*. +void LogAllowed(const char* aFunctionName, const wchar_t* aContext); +void LogAllowed(const char* aFunctionName, const wchar_t* aContext, + uint16_t aLengthInBytes); + + +} // sandboxing +} // mozilla + +#endif // security_sandbox_sandboxLogging_h__ diff --git a/security/sandbox/chromium-shim/sandbox/win/src/line_break_common.h b/security/sandbox/chromium-shim/sandbox/win/src/line_break_common.h new file mode 100644 index 0000000000..b712239dde --- /dev/null +++ b/security/sandbox/chromium-shim/sandbox/win/src/line_break_common.h @@ -0,0 +1,31 @@ +/* -*- 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/. */ + +#ifndef SANDBOX_SRC_LINE_BREAK_COMMON_H_ +#define SANDBOX_SRC_LINE_BREAK_COMMON_H_ + +#include "sandbox/win/src/crosscall_params.h" + +namespace sandbox { + +#if defined(MOZ_DEBUG) +// Set a low max brokered length for testing to exercise the chunking code. +static const std::ptrdiff_t kMaxBrokeredLen = 50; + +#else +// Parameters are stored aligned to sizeof(int64_t). +// So to calculate the maximum length we can use when brokering to the parent, +// we take the max params buffer size, take off 8 for the aligned length and 6 +// and 7 to allow for the maximum padding that can be added to the text and +// break before buffers. We then divide by three, because the text characters +// are wchar_t and the break before elements are uint8_t. +static const std::ptrdiff_t kMaxBrokeredLen = + (ActualCallParams<3, kIPCChannelSize>::MaxParamsSize() - 8 - 6 - 7) / 3; +#endif + +} // namespace sandbox + +#endif // SANDBOX_SRC_LINE_BREAK_COMMON_H_ diff --git a/security/sandbox/chromium-shim/sandbox/win/src/line_break_dispatcher.cc b/security/sandbox/chromium-shim/sandbox/win/src/line_break_dispatcher.cc new file mode 100644 index 0000000000..94401d18fa --- /dev/null +++ b/security/sandbox/chromium-shim/sandbox/win/src/line_break_dispatcher.cc @@ -0,0 +1,58 @@ +/* -*- 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 "sandbox/win/src/line_break_dispatcher.h" + +#include "sandbox/win/src/line_break_common.h" +#include "sandbox/win/src/line_break_policy.h" +#include "sandbox/win/src/ipc_tags.h" +#include "sandbox/win/src/policy_params.h" + +namespace sandbox { + +LineBreakDispatcher::LineBreakDispatcher(PolicyBase* policy_base) + : policy_base_(policy_base) { + static const IPCCall get_complex_line_breaks = { + {IpcTag::GETCOMPLEXLINEBREAKS, {INPTR_TYPE, UINT32_TYPE, INOUTPTR_TYPE}}, + reinterpret_cast<CallbackGeneric>( + &LineBreakDispatcher::GetComplexLineBreaksCall)}; + + ipc_calls_.push_back(get_complex_line_breaks); +} + +bool LineBreakDispatcher::SetupService(InterceptionManager* manager, + IpcTag service) { + // We perform no interceptions for line breaking right now. + switch (service) { + case IpcTag::GETCOMPLEXLINEBREAKS: + return true; + + default: + return false; + } +} + +bool LineBreakDispatcher::GetComplexLineBreaksCall( + IPCInfo* ipc, CountedBuffer* text_buf, uint32_t length, + CountedBuffer* break_before_buf) { + if (length > kMaxBrokeredLen || + text_buf->Size() != length * sizeof(wchar_t) || + break_before_buf->Size() != length) { + return false; + } + + CountedParameterSet<EmptyParams> params; + EvalResult eval = + policy_base_->EvalPolicy(IpcTag::GETCOMPLEXLINEBREAKS, params.GetBase()); + auto* text = static_cast<wchar_t*>(text_buf->Buffer()); + auto* break_before = static_cast<uint8_t*>(break_before_buf->Buffer()); + ipc->return_info.win32_result = + LineBreakPolicy::GetComplexLineBreaksProxyAction(eval, text, length, + break_before); + return true; +} + +} // namespace sandbox diff --git a/security/sandbox/chromium-shim/sandbox/win/src/line_break_dispatcher.h b/security/sandbox/chromium-shim/sandbox/win/src/line_break_dispatcher.h new file mode 100644 index 0000000000..774b5c5b56 --- /dev/null +++ b/security/sandbox/chromium-shim/sandbox/win/src/line_break_dispatcher.h @@ -0,0 +1,38 @@ +/* -*- 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/. */ + +#ifndef SANDBOX_SRC_LINE_BREAK_DISPATCHER_H_ +#define SANDBOX_SRC_LINE_BREAK_DISPATCHER_H_ + +#include "base/macros.h" +#include "sandbox/win/src/crosscall_server.h" +#include "sandbox/win/src/sandbox_policy_base.h" + +namespace sandbox { + +// This class handles line break related IPC calls. +class LineBreakDispatcher final : public Dispatcher { + public: + explicit LineBreakDispatcher(PolicyBase* policy_base); + ~LineBreakDispatcher() final {} + + // Dispatcher interface. + bool SetupService(InterceptionManager* manager, IpcTag service) final; + + private: + // Processes IPC requests coming from calls to + // TargetServices::GetComplexLineBreaks() in the target. + bool GetComplexLineBreaksCall(IPCInfo* ipc, CountedBuffer* text_buf, + uint32_t length, + CountedBuffer* break_before_buf); + + PolicyBase* policy_base_; + DISALLOW_COPY_AND_ASSIGN(LineBreakDispatcher); +}; + +} // namespace sandbox + +#endif // SANDBOX_SRC_LINE_BREAK_DISPATCHER_H_ diff --git a/security/sandbox/chromium-shim/sandbox/win/src/line_break_interception.cc b/security/sandbox/chromium-shim/sandbox/win/src/line_break_interception.cc new file mode 100644 index 0000000000..f2dcda0dc9 --- /dev/null +++ b/security/sandbox/chromium-shim/sandbox/win/src/line_break_interception.cc @@ -0,0 +1,108 @@ +/* -*- 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 "sandbox/win/src/line_break_interception.h" + +#include <winnls.h> + +#include "sandbox/win/src/crosscall_client.h" +#include "sandbox/win/src/ipc_tags.h" +#include "sandbox/win/src/line_break_common.h" +#include "sandbox/win/src/sandbox_nt_util.h" +#include "sandbox/win/src/sharedmem_ipc_client.h" + +namespace sandbox { + +static const int kBreakSearchRange = 32; + +ResultCode GetComplexLineBreaksProxy(const wchar_t* aText, uint32_t aLength, + uint8_t* aBreakBefore) { + // Make sure that a test length for kMaxBrokeredLen hasn't been set too small + // allowing for a surrogate pair at the end of a chunk as well. + DCHECK(kMaxBrokeredLen > kBreakSearchRange + 1); + + void* memory = GetGlobalIPCMemory(); + if (!memory) { + return SBOX_ERROR_NO_SPACE; + } + + memset(aBreakBefore, false, aLength); + + SharedMemIPCClient ipc(memory); + + uint8_t* breakBeforeIter = aBreakBefore; + const wchar_t* textIterEnd = aText + aLength; + do { + // Next chunk is either the remaining text or kMaxBrokeredLen long. + const wchar_t* textIter = aText + (breakBeforeIter - aBreakBefore); + const wchar_t* chunkEnd = textIter + kMaxBrokeredLen; + if (chunkEnd < textIterEnd) { + // Make sure we don't split a surrogate pair. + if (IS_HIGH_SURROGATE(*(chunkEnd - 1))) { + --chunkEnd; + } + } else { + // This chunk handles all the (remaining) text. + chunkEnd = textIterEnd; + } + + // Uniscribe seems to often (perhaps always) set the first element to a + // break, so we use chunk_start_reset to hold the known value of the first + // element of a chunk and reset it after Uniscribe processing. The only time + // we don't start from an already processed element is the first call, but + // resetting this to false is correct because whether we can break before + // the first character is decided by our caller. + uint8_t chunk_start_reset = *breakBeforeIter; + + uint32_t len = chunkEnd - textIter; + // CountedBuffer takes a wchar_t* even though it doesn't change the buffer. + CountedBuffer textBuf(const_cast<wchar_t*>(textIter), + sizeof(wchar_t) * len); + InOutCountedBuffer breakBeforeBuf(breakBeforeIter, len); + CrossCallReturn answer = {0}; + ResultCode code = CrossCall(ipc, IpcTag::GETCOMPLEXLINEBREAKS, textBuf, len, + breakBeforeBuf, &answer); + if (SBOX_ALL_OK != code) { + return code; + } + + if (answer.win32_result) { + ::SetLastError(answer.win32_result); + return SBOX_ERROR_GENERIC; + } + + *breakBeforeIter = chunk_start_reset; + + if (chunkEnd == textIterEnd) { + break; + } + + // We couldn't process all of the text in one go, so back up by 32 chars and + // look for a break, then continue from that position. We back up 32 chars + // to try to avoid any false breaks at the end of the buffer caused by us + // splitting it into chunks. + uint8_t* processedToEnd = breakBeforeIter + len; + breakBeforeIter = processedToEnd - kBreakSearchRange; + while (!*breakBeforeIter) { + if (++breakBeforeIter == processedToEnd) { + // We haven't found a break in the search range, so go back to the start + // of our search range to try and ensure we don't get any false breaks + // at the start of the new chunk. + breakBeforeIter = processedToEnd - kBreakSearchRange; + // Make sure we don't split a surrogate pair. + if (IS_LOW_SURROGATE( + *(aText + (breakBeforeIter - aBreakBefore)))) { + ++breakBeforeIter; + } + break; + } + } + } while (true); + + return SBOX_ALL_OK; +} + +} // namespace sandbox diff --git a/security/sandbox/chromium-shim/sandbox/win/src/line_break_interception.h b/security/sandbox/chromium-shim/sandbox/win/src/line_break_interception.h new file mode 100644 index 0000000000..87681e2e90 --- /dev/null +++ b/security/sandbox/chromium-shim/sandbox/win/src/line_break_interception.h @@ -0,0 +1,19 @@ +/* -*- 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/. */ + +#ifndef SANDBOX_SRC_LINE_BREAK_INTERCEPTION_H_ +#define SANDBOX_SRC_LINE_BREAK_INTERCEPTION_H_ + +#include "sandbox/win/src/sandbox_types.h" + +namespace sandbox { + +ResultCode GetComplexLineBreaksProxy(const wchar_t* text, uint32_t length, + uint8_t* break_before); + +} // namespace sandbox + +#endif // SANDBOX_SRC_LINE_BREAK_INTERCEPTION_H_ diff --git a/security/sandbox/chromium-shim/sandbox/win/src/line_break_policy.cc b/security/sandbox/chromium-shim/sandbox/win/src/line_break_policy.cc new file mode 100644 index 0000000000..5533232643 --- /dev/null +++ b/security/sandbox/chromium-shim/sandbox/win/src/line_break_policy.cc @@ -0,0 +1,66 @@ +/* -*- 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 "sandbox/win/src/line_break_policy.h" + +#include <algorithm> +#include <array> +#include <usp10.h> + +#include "sandbox/win/src/ipc_tags.h" +#include "sandbox/win/src/line_break_common.h" +#include "sandbox/win/src/policy_engine_opcodes.h" +#include "sandbox/win/src/policy_params.h" + +namespace sandbox { + +bool LineBreakPolicy::GenerateRules(const wchar_t* null, + TargetPolicy::Semantics semantics, + LowLevelPolicy* policy) { + if (TargetPolicy::LINE_BREAK_ALLOW != semantics) { + return false; + } + + PolicyRule line_break_rule(ASK_BROKER); + if (!policy->AddRule(IpcTag::GETCOMPLEXLINEBREAKS, &line_break_rule)) { + return false; + } + return true; +} + +/* static */ DWORD LineBreakPolicy::GetComplexLineBreaksProxyAction( + EvalResult eval_result, const wchar_t* text, uint32_t length, + uint8_t* break_before) { + // The only action supported is ASK_BROKER which means call the line breaker. + if (ASK_BROKER != eval_result) { + return ERROR_ACCESS_DENIED; + } + + int outItems = 0; + std::array<SCRIPT_ITEM, kMaxBrokeredLen + 1> items; + HRESULT result = ::ScriptItemize(text, length, kMaxBrokeredLen, nullptr, + nullptr, items.data(), &outItems); + if (result != 0) { + return ERROR_ACCESS_DENIED; + } + + std::array<SCRIPT_LOGATTR, kMaxBrokeredLen> slas; + for (int iItem = 0; iItem < outItems; ++iItem) { + uint32_t endOffset = items[iItem + 1].iCharPos; + uint32_t startOffset = items[iItem].iCharPos; + if (FAILED(::ScriptBreak(text + startOffset, endOffset - startOffset, + &items[iItem].a, &slas[startOffset]))) { + return ERROR_ACCESS_DENIED; + } + } + + std::transform(slas.data(), slas.data() + length, break_before, + [](const SCRIPT_LOGATTR& sla) { return sla.fSoftBreak; }); + + return ERROR_SUCCESS; +} + +} // namespace sandbox diff --git a/security/sandbox/chromium-shim/sandbox/win/src/line_break_policy.h b/security/sandbox/chromium-shim/sandbox/win/src/line_break_policy.h new file mode 100644 index 0000000000..89fbf9b207 --- /dev/null +++ b/security/sandbox/chromium-shim/sandbox/win/src/line_break_policy.h @@ -0,0 +1,35 @@ +/* -*- 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/. */ + +#ifndef SANDBOX_SRC_LINE_BREAK_POLICY_H_ +#define SANDBOX_SRC_LINE_BREAK_POLICY_H_ + +#include "base/win/windows_types.h" +#include "sandbox/win/src/policy_low_level.h" +#include "sandbox/win/src/sandbox_policy.h" + +namespace sandbox { + +enum EvalResult; + +class LineBreakPolicy { + public: + // Creates the required low-level policy rules to evaluate a high-level + // policy rule for complex line breaks. + static bool GenerateRules(const wchar_t* type_name, + TargetPolicy::Semantics semantics, + LowLevelPolicy* policy); + + // Processes a TargetServices::GetComplexLineBreaks() request from the target. + static DWORD GetComplexLineBreaksProxyAction(EvalResult eval_result, + const wchar_t* text, + uint32_t length, + uint8_t* break_before); +}; + +} // namespace sandbox + +#endif // SANDBOX_SRC_LINE_BREAK_POLICY_H_ diff --git a/security/sandbox/chromium-shim/sandbox/win/src/sandbox_policy_diagnostic.h b/security/sandbox/chromium-shim/sandbox/win/src/sandbox_policy_diagnostic.h new file mode 100644 index 0000000000..5b37ccc556 --- /dev/null +++ b/security/sandbox/chromium-shim/sandbox/win/src/sandbox_policy_diagnostic.h @@ -0,0 +1,31 @@ +/* -*- 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_ diff --git a/security/sandbox/chromium-shim/sandbox/win/src/sidestep_resolver.h b/security/sandbox/chromium-shim/sandbox/win/src/sidestep_resolver.h new file mode 100644 index 0000000000..fe38484b0e --- /dev/null +++ b/security/sandbox/chromium-shim/sandbox/win/src/sidestep_resolver.h @@ -0,0 +1,58 @@ +/* -*- 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 https://mozilla.org/MPL/2.0/. */ + +// This is a dummy version of the Chromium source file +// sandbox/win/src/sidestep_resolver.h, which contains classes that are never +// actually used. We crash in the member functions to ensure this. +// Formatting and guards closely match original file for easy comparison. + +#ifndef SANDBOX_SRC_SIDESTEP_RESOLVER_H__ +#define SANDBOX_SRC_SIDESTEP_RESOLVER_H__ + +#include <stddef.h> + +#include "base/macros.h" +#include "sandbox/win/src/nt_internals.h" +#include "sandbox/win/src/resolver.h" + +#include "mozilla/Assertions.h" + +namespace sandbox { + +class SidestepResolverThunk : public ResolverThunk { + public: + SidestepResolverThunk() {} + ~SidestepResolverThunk() override {} + + // Implementation of Resolver::Setup. + NTSTATUS Setup(const void* target_module, + const void* interceptor_module, + const char* target_name, + const char* interceptor_name, + const void* interceptor_entry_point, + void* thunk_storage, + size_t storage_bytes, + size_t* storage_used) override { MOZ_CRASH(); } + + size_t GetThunkSize() const override { MOZ_CRASH(); } + + private: + DISALLOW_COPY_AND_ASSIGN(SidestepResolverThunk); +}; + +class SmartSidestepResolverThunk : public SidestepResolverThunk { + public: + SmartSidestepResolverThunk() {} + ~SmartSidestepResolverThunk() override {} + + private: + DISALLOW_COPY_AND_ASSIGN(SmartSidestepResolverThunk); +}; + +} // namespace sandbox + + +#endif // SANDBOX_SRC_SIDESTEP_RESOLVER_H__ |