diff --git a/browser/app/moz.build b/browser/app/moz.build index 07f01b911f0323de87836a6b49be0e1397614e0d..ba8e780dacd5934a110bf22adba8c104e6ea5acc 100644 --- a/browser/app/moz.build +++ b/browser/app/moz.build @@ -117,6 +117,7 @@ if CONFIG["MOZ_SANDBOX"] and CONFIG["OS_ARCH"] == "WINNT": DELAYLOAD_DLLS += [ "winmm.dll", "user32.dll", + "usp10.dll", ] # Control the default heap size. 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 0000000000000000000000000000000000000000..4d350fa8bca0b7310e7e4472cb2751c7c37b71e0 --- /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/patch_order.txt b/security/sandbox/chromium-shim/patches/with_update/patch_order.txt index 433460cb6742392fc8413442c2cf0d2b8c2a1288..736d6eef176e5acbd5aa02dea5cc87883bf9bd5d 100755 --- a/security/sandbox/chromium-shim/patches/with_update/patch_order.txt +++ b/security/sandbox/chromium-shim/patches/with_update/patch_order.txt @@ -27,3 +27,4 @@ remove_extraneous_backslash_introduced_by_clang_tidy.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 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 0000000000000000000000000000000000000000..a6fe342262576c07777e00f5e03a24a4b0f22f51 --- /dev/null +++ b/security/sandbox/chromium-shim/sandbox/win/src/line_break_common.h @@ -0,0 +1,25 @@ +/* -*- 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 { + +// 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; + +} // 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 0000000000000000000000000000000000000000..94401d18faec84fb4fa45aa300dd6bb180013c90 --- /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 0000000000000000000000000000000000000000..774b5c5b5689fc3238b51823b61673229b559d72 --- /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 0000000000000000000000000000000000000000..c01aab59a50998abde278c0f7377b89c6dde786f --- /dev/null +++ b/security/sandbox/chromium-shim/sandbox/win/src/line_break_interception.cc @@ -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/. */ + +#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; + } + + 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; + } + + 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. + uint8_t* processedToEnd = breakBeforeIter + len; + breakBeforeIter = processedToEnd - kBreakSearchRange; + while (!*breakBeforeIter) { + if (++breakBeforeIter == processedToEnd) { + break; + } + } + } while (true); + + // Whether we can break before the first character is decided by our caller + aBreakBefore[0] = false; + + 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 0000000000000000000000000000000000000000..87681e2e90a23877671f9ae7715206d3172db969 --- /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 0000000000000000000000000000000000000000..55332326438f4a9fce509a34dec1c7cc3130e674 --- /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 0000000000000000000000000000000000000000..89fbf9b2076c933a00052db64470ec23ae630eba --- /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/sandbox/win/src/crosscall_client.h b/security/sandbox/chromium/sandbox/win/src/crosscall_client.h index 84fd090a72a92d8950cef92f385613266a15cbdc..a346aeb753a726fa1d1474a055f9f9f2ed33b6f6 100644 --- a/security/sandbox/chromium/sandbox/win/src/crosscall_client.h +++ b/security/sandbox/chromium/sandbox/win/src/crosscall_client.h @@ -44,10 +44,6 @@ 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. @@ -211,6 +207,32 @@ class InOutCountedBuffer : public CountedBuffer { : 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 <> diff --git a/security/sandbox/chromium/sandbox/win/src/crosscall_params.h b/security/sandbox/chromium/sandbox/win/src/crosscall_params.h index a4ffc05997562b51cb788c440e7312fda78afa83..6971b55cb72d175b50c0ec60da660bbed369da82 100644 --- a/security/sandbox/chromium/sandbox/win/src/crosscall_params.h +++ b/security/sandbox/chromium/sandbox/win/src/crosscall_params.h @@ -46,6 +46,10 @@ 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; @@ -221,6 +225,11 @@ class ActualCallParams : public CrossCallParams { 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) { diff --git a/security/sandbox/chromium/sandbox/win/src/crosscall_server.cc b/security/sandbox/chromium/sandbox/win/src/crosscall_server.cc index 415ad27eac793ad24c09bde826e21214297860af..27bfdfbd65edb0e08eda9d5747629ba5bba184ac 100644 --- a/security/sandbox/chromium/sandbox/win/src/crosscall_server.cc +++ b/security/sandbox/chromium/sandbox/win/src/crosscall_server.cc @@ -306,7 +306,7 @@ bool CrossCallParamsEx::GetParameterPtr(uint32_t index, 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) diff --git a/security/sandbox/chromium/sandbox/win/src/ipc_args.cc b/security/sandbox/chromium/sandbox/win/src/ipc_args.cc index c961ad809edd126274af2c11acc3ef2269e9fcbe..c0c64f1864ec951e3d22f05de57aa8ed27fcf0ec 100644 --- a/security/sandbox/chromium/sandbox/win/src/ipc_args.cc +++ b/security/sandbox/chromium/sandbox/win/src/ipc_args.cc @@ -20,6 +20,7 @@ void ReleaseArgs(const IPCParams* ipc_params, void* args[kMaxIpcParams]) { args[i] = nullptr; break; } + case INPTR_TYPE: case INOUTPTR_TYPE: { delete reinterpret_cast<CountedBuffer*>(args[i]); args[i] = nullptr; @@ -74,6 +75,7 @@ bool GetArgs(CrossCallParamsEx* params, args[i] = data; break; } + case INPTR_TYPE: case INOUTPTR_TYPE: { if (!args[i]) { ReleaseArgs(ipc_params, args); diff --git a/security/sandbox/chromium/sandbox/win/src/ipc_tags.h b/security/sandbox/chromium/sandbox/win/src/ipc_tags.h index ad69706258b85090ee5809482b7affd7787e604e..ec6de4a66ad513ef48eaf615367463238ba21078 100644 --- a/security/sandbox/chromium/sandbox/win/src/ipc_tags.h +++ b/security/sandbox/chromium/sandbox/win/src/ipc_tags.h @@ -46,6 +46,7 @@ enum class IpcTag { GDI_GETSUGGESTEDOPMPROTECTEDOUTPUTARRAYSIZE, GDI_SETOPMSIGNINGKEYANDSEQUENCENUMBERS, NTCREATESECTION, + GETCOMPLEXLINEBREAKS, LAST }; diff --git a/security/sandbox/chromium/sandbox/win/src/policy_engine_opcodes.cc b/security/sandbox/chromium/sandbox/win/src/policy_engine_opcodes.cc index 4bac801f9bce53b457e70f992b716d3739fb4a8e..02c636f4aa81cdd5a01829c921a2a1212c313919 100644 --- a/security/sandbox/chromium/sandbox/win/src/policy_engine_opcodes.cc +++ b/security/sandbox/chromium/sandbox/win/src/policy_engine_opcodes.cc @@ -83,7 +83,7 @@ EvalResult OpcodeEval<OP_ALWAYS_TRUE>(PolicyOpcode* opcode, // 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); diff --git a/security/sandbox/chromium/sandbox/win/src/policy_params.h b/security/sandbox/chromium/sandbox/win/src/policy_params.h index dbab8307d42fc617ddc74c7691b56d926f7eee19..aeec6d7edc494bb2a6e0c33170a44b4496c795c7 100644 --- a/security/sandbox/chromium/sandbox/win/src/policy_params.h +++ b/security/sandbox/chromium/sandbox/win/src/policy_params.h @@ -61,6 +61,10 @@ POLPARAMS_BEGIN(HandleTarget) 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 index 8c1ad7aa194f02947c6943e417930c128f669e01..92d40c755c5c9b27f97c422cd775ddcf707ee346 100644 --- a/security/sandbox/chromium/sandbox/win/src/sandbox.h +++ b/security/sandbox/chromium/sandbox/win/src/sandbox.h @@ -181,6 +181,9 @@ class TargetServices { DWORD desired_access, DWORD options) = 0; + virtual ResultCode GetComplexLineBreaks(const WCHAR* text, uint32_t length, + uint8_t* break_before) = 0; + protected: ~TargetServices() {} }; diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_policy.h b/security/sandbox/chromium/sandbox/win/src/sandbox_policy.h index 3ed6561589e5dda456e9b66e7441fc2fb33a01e6..75514ef595d849b33ffd56d058559485add96933 100644 --- a/security/sandbox/chromium/sandbox/win/src/sandbox_policy.h +++ b/security/sandbox/chromium/sandbox/win/src/sandbox_policy.h @@ -32,7 +32,8 @@ class TargetPolicy { 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. @@ -65,7 +66,8 @@ class TargetPolicy { 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 diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc b/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc index ddaea73ab36afad4d8b81ba50bc1f58437c8b592..194f4e9353a1f029bf2e3c62a4ccd6b4fdcb3b51 100644 --- a/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc +++ b/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc @@ -20,6 +20,7 @@ #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" @@ -814,6 +815,13 @@ ResultCode PolicyBase::AddRuleInternal(SubSystem subsystem, } break; } + case SUBSYS_LINE_BREAK: { + if (!LineBreakPolicy::GenerateRules(pattern, semantics, policy_maker_)) { + NOTREACHED(); + return SBOX_ERROR_BAD_PARAMS; + } + break; + } default: { return SBOX_ERROR_UNSUPPORTED; } } diff --git a/security/sandbox/chromium/sandbox/win/src/target_services.cc b/security/sandbox/chromium/sandbox/win/src/target_services.cc index 52a29e2df3ad793ad1ee8594a75b275aeee53698..a80e0106ef952dfb665835b014cda7837610409d 100644 --- a/security/sandbox/chromium/sandbox/win/src/target_services.cc +++ b/security/sandbox/chromium/sandbox/win/src/target_services.cc @@ -14,6 +14,7 @@ #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" @@ -245,7 +246,6 @@ void ProcessState::SetCsrssConnected(bool csrss_connected) { csrss_connected_ = csrss_connected; } - ResultCode TargetServicesBase::DuplicateHandle(HANDLE source_handle, DWORD target_process_id, HANDLE* target_handle, @@ -255,4 +255,10 @@ ResultCode TargetServicesBase::DuplicateHandle(HANDLE source_handle, 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 index 6a1d31464652e95c17e9d98dabd9ebf875c6d636..1d70d4cd34e6def3a3deab39e29730cd65c4bf46 100644 --- a/security/sandbox/chromium/sandbox/win/src/target_services.h +++ b/security/sandbox/chromium/sandbox/win/src/target_services.h @@ -50,6 +50,8 @@ class TargetServicesBase : public TargetServices { 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(); diff --git a/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.cc b/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.cc index 31af52e99f84ecdd1380d30902021bfe9f9085eb..3c8f8e25e5983f232faaf1ff1f5226e36524a22e 100644 --- a/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.cc +++ b/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.cc @@ -14,6 +14,7 @@ #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" @@ -95,6 +96,10 @@ TopLevelDispatcher::TopLevelDispatcher(PolicyBase* policy) : policy_(policy) { 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() {} diff --git a/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.h b/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.h index b440d86f1df5be51d12041f1063c27f0ffea72a8..a80ce1ef5d3ad7ae61fccc9189e9fc0ce28974f8 100644 --- a/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.h +++ b/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.h @@ -43,6 +43,7 @@ class TopLevelDispatcher : public 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); diff --git a/security/sandbox/moz.build b/security/sandbox/moz.build index e10f1afe91af3dfc44e98b7b5f31b96644fcfe30..27a0eb6bd83a11a874afb5a6b7b5faaee4a96f78 100755 --- a/security/sandbox/moz.build +++ b/security/sandbox/moz.build @@ -49,6 +49,9 @@ elif CONFIG["OS_ARCH"] == "WINNT": "chromium-shim/base/win/win_util.cpp", "chromium-shim/sandbox/win/permissionsService.cpp", "chromium-shim/sandbox/win/sandboxLogging.cpp", + "chromium-shim/sandbox/win/src/line_break_dispatcher.cc", + "chromium-shim/sandbox/win/src/line_break_interception.cc", + "chromium-shim/sandbox/win/src/line_break_policy.cc", "chromium/base/at_exit.cc", "chromium/base/base_switches.cc", "chromium/base/callback_internal.cc", @@ -204,6 +207,8 @@ elif CONFIG["OS_ARCH"] == "WINNT": LOCAL_INCLUDES += ["/security/sandbox/chromium"] LOCAL_INCLUDES += ["/nsprpub"] + OS_LIBS += ["usp10"] + DisableStlWrapping() # Suppress warnings in third-party code. diff --git a/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp b/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp index d95bc5cf3d30ccf59e1f96787b06ec42521e865d..c58888bfc35b64c7100ddfdbcb09f6bc95ac38d6 100644 --- a/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp +++ b/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp @@ -783,6 +783,13 @@ void SandboxBroker::SetSecurityLevelForContentProcess(int32_t aSandboxLevel, sandbox::SBOX_ALL_OK == result, "With these static arguments AddRule should never fail, what happened?"); + // Allow content processes to use complex line breaking brokering. + result = mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_LINE_BREAK, + sandbox::TargetPolicy::LINE_BREAK_ALLOW, nullptr); + MOZ_RELEASE_ASSERT( + sandbox::SBOX_ALL_OK == result, + "With these static arguments AddRule should never fail, what happened?"); + if (aSandboxLevel >= 20) { // Content process still needs to be able to read fonts. wchar_t* fontsPath; diff --git a/security/sandbox/win/src/sandboxtarget/sandboxTarget.cpp b/security/sandbox/win/src/sandboxtarget/sandboxTarget.cpp index b5c71e87626517728024063b4165249e9892c437..b0b0876bcaabed9830ba3416284d0d24878ee1ac 100644 --- a/security/sandbox/win/src/sandboxtarget/sandboxTarget.cpp +++ b/security/sandbox/win/src/sandboxtarget/sandboxTarget.cpp @@ -50,5 +50,15 @@ bool SandboxTarget::BrokerDuplicateHandle(HANDLE aSourceHandle, aSourceHandle, aTargetProcessId, aTargetHandle, aDesiredAccess, aOptions); return (sandbox::SBOX_ALL_OK == result); } +bool SandboxTarget::GetComplexLineBreaks(const WCHAR* text, uint32_t length, + uint8_t* break_before) { + if (!mTargetServices) { + return false; + } + + sandbox::ResultCode result = + mTargetServices->GetComplexLineBreaks(text, length, break_before); + return (sandbox::SBOX_ALL_OK == result); +} } // namespace mozilla diff --git a/security/sandbox/win/src/sandboxtarget/sandboxTarget.h b/security/sandbox/win/src/sandboxtarget/sandboxTarget.h index b60881dd3faadaaed5788124c164f98706e0062e..7867f0bb33a33fc944b5de0d7b66229de7f243ae 100644 --- a/security/sandbox/win/src/sandboxtarget/sandboxTarget.h +++ b/security/sandbox/win/src/sandboxtarget/sandboxTarget.h @@ -62,6 +62,9 @@ class SandboxTarget { HANDLE* aTargetHandle, DWORD aDesiredAccess, DWORD aOptions); + bool GetComplexLineBreaks(const WCHAR* text, uint32_t length, + uint8_t* break_before); + protected: SandboxTarget() : mTargetServices(nullptr) {}