From 2db5ff3913f67336c4b8f31ad14de788498ec421 Mon Sep 17 00:00:00 2001 From: Bob Owen <bobowencode@gmail.com> Date: Tue, 26 Oct 2021 09:58:51 +0000 Subject: [PATCH] Bug 1713973 p2: Add Uniscribe Line Breaking via chromium-sandbox IPC. r=tkikuchi,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. Depends on D129125 Differential Revision: https://phabricator.services.mozilla.com/D126809 --- browser/app/moz.build | 1 + .../broker_complex_line_breaks.patch | 502 ++++++++++++++++++ .../patches/with_update/patch_order.txt | 1 + .../sandbox/win/src/line_break_common.h | 25 + .../sandbox/win/src/line_break_dispatcher.cc | 58 ++ .../sandbox/win/src/line_break_dispatcher.h | 38 ++ .../win/src/line_break_interception.cc | 90 ++++ .../sandbox/win/src/line_break_interception.h | 19 + .../sandbox/win/src/line_break_policy.cc | 66 +++ .../sandbox/win/src/line_break_policy.h | 35 ++ .../sandbox/win/src/crosscall_client.h | 30 +- .../sandbox/win/src/crosscall_params.h | 9 + .../sandbox/win/src/crosscall_server.cc | 2 +- .../chromium/sandbox/win/src/ipc_args.cc | 2 + .../chromium/sandbox/win/src/ipc_tags.h | 1 + .../sandbox/win/src/policy_engine_opcodes.cc | 2 +- .../chromium/sandbox/win/src/policy_params.h | 4 + .../chromium/sandbox/win/src/sandbox.h | 3 + .../chromium/sandbox/win/src/sandbox_policy.h | 6 +- .../sandbox/win/src/sandbox_policy_base.cc | 8 + .../sandbox/win/src/target_services.cc | 8 +- .../sandbox/win/src/target_services.h | 2 + .../sandbox/win/src/top_level_dispatcher.cc | 5 + .../sandbox/win/src/top_level_dispatcher.h | 1 + security/sandbox/moz.build | 5 + .../win/src/sandboxbroker/sandboxBroker.cpp | 7 + .../win/src/sandboxtarget/sandboxTarget.cpp | 10 + .../win/src/sandboxtarget/sandboxTarget.h | 3 + 28 files changed, 934 insertions(+), 9 deletions(-) create mode 100644 security/sandbox/chromium-shim/patches/with_update/broker_complex_line_breaks.patch create mode 100644 security/sandbox/chromium-shim/sandbox/win/src/line_break_common.h create mode 100644 security/sandbox/chromium-shim/sandbox/win/src/line_break_dispatcher.cc create mode 100644 security/sandbox/chromium-shim/sandbox/win/src/line_break_dispatcher.h create mode 100644 security/sandbox/chromium-shim/sandbox/win/src/line_break_interception.cc create mode 100644 security/sandbox/chromium-shim/sandbox/win/src/line_break_interception.h create mode 100644 security/sandbox/chromium-shim/sandbox/win/src/line_break_policy.cc create mode 100644 security/sandbox/chromium-shim/sandbox/win/src/line_break_policy.h diff --git a/browser/app/moz.build b/browser/app/moz.build index 07f01b911f032..ba8e780dacd59 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 0000000000000..4d350fa8bca0b --- /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 433460cb67423..736d6eef176e5 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 0000000000000..a6fe342262576 --- /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 0000000000000..94401d18faec8 --- /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 0000000000000..774b5c5b5689f --- /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 0000000000000..c01aab59a5099 --- /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 0000000000000..87681e2e90a23 --- /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 0000000000000..55332326438f4 --- /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 0000000000000..89fbf9b2076c9 --- /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 84fd090a72a92..a346aeb753a72 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 a4ffc05997562..6971b55cb72d1 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 415ad27eac793..27bfdfbd65edb 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 c961ad809edd1..c0c64f1864ec9 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 ad69706258b85..ec6de4a66ad51 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 4bac801f9bce5..02c636f4aa81c 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 dbab8307d42fc..aeec6d7edc494 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 8c1ad7aa194f0..92d40c755c5c9 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 3ed6561589e5d..75514ef595d84 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 ddaea73ab36af..194f4e9353a1f 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 52a29e2df3ad7..a80e0106ef952 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 6a1d31464652e..1d70d4cd34e6d 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 31af52e99f84e..3c8f8e25e5983 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 b440d86f1df5b..a80ce1ef5d3ad 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 e10f1afe91af3..27a0eb6bd83a1 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 d95bc5cf3d30c..c58888bfc35b6 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 b5c71e8762651..b0b0876bcaabe 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 b60881dd3faad..7867f0bb33a33 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) {} -- GitLab