summaryrefslogtreecommitdiffstats
path: root/security/sandbox/chromium-shim/patches/with_update/revert_remove_BrokerDuplicateHandle.patch
diff options
context:
space:
mode:
Diffstat (limited to 'security/sandbox/chromium-shim/patches/with_update/revert_remove_BrokerDuplicateHandle.patch')
-rw-r--r--security/sandbox/chromium-shim/patches/with_update/revert_remove_BrokerDuplicateHandle.patch743
1 files changed, 743 insertions, 0 deletions
diff --git a/security/sandbox/chromium-shim/patches/with_update/revert_remove_BrokerDuplicateHandle.patch b/security/sandbox/chromium-shim/patches/with_update/revert_remove_BrokerDuplicateHandle.patch
new file mode 100644
index 0000000000..970c0d1db2
--- /dev/null
+++ b/security/sandbox/chromium-shim/patches/with_update/revert_remove_BrokerDuplicateHandle.patch
@@ -0,0 +1,743 @@
+# HG changeset patch
+# User Toshihito Kikuchi <tkikuchi@mozilla.com>
+# Date 1589671733 25200
+# Sat May 16 16:28:53 2020 -0700
+# Node ID 91bb5c3807cfe657cc24c9a3c217dd1f57db6d5c
+# Parent 22eb0bf7180801edf775be44cf299a50e01eb7bf
+Reinstate sandbox::TargetServices::BrokerDuplicateHandle. r=bobowen
+
+This patch reverts the commit removing sandbox::TargetServices::BrokerDuplicateHandle
+and applies the new IpcTag type.
+
+https://chromium.googlesource.com/chromium/src.git/+/569193665184525ca366e65d0735f5c851106e43
+https://chromium.googlesource.com/chromium/src.git/+/c8cff7f9663ce6d1ef35e5c717f43c867c3906eb
+
+diff --git a/security/sandbox/chromium/sandbox/win/src/handle_dispatcher.cc b/security/sandbox/chromium/sandbox/win/src/handle_dispatcher.cc
+new file mode 100644
+--- /dev/null
++++ b/security/sandbox/chromium/sandbox/win/src/handle_dispatcher.cc
+@@ -0,0 +1,93 @@
++// Copyright (c) 2012 The Chromium Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style license that can be
++// found in the LICENSE file.
++
++#include "sandbox/win/src/handle_dispatcher.h"
++
++#include <stdint.h>
++
++#include "base/win/scoped_handle.h"
++#include "sandbox/win/src/handle_interception.h"
++#include "sandbox/win/src/handle_policy.h"
++#include "sandbox/win/src/ipc_tags.h"
++#include "sandbox/win/src/policy_broker.h"
++#include "sandbox/win/src/policy_params.h"
++#include "sandbox/win/src/sandbox.h"
++#include "sandbox/win/src/sandbox_nt_util.h"
++#include "sandbox/win/src/sandbox_types.h"
++#include "sandbox/win/src/sandbox_utils.h"
++
++namespace sandbox {
++
++HandleDispatcher::HandleDispatcher(PolicyBase* policy_base)
++ : policy_base_(policy_base) {
++ static const IPCCall duplicate_handle_proxy = {
++ {IpcTag::DUPLICATEHANDLEPROXY,
++ {VOIDPTR_TYPE, UINT32_TYPE, UINT32_TYPE, UINT32_TYPE}},
++ reinterpret_cast<CallbackGeneric>(
++ &HandleDispatcher::DuplicateHandleProxy)};
++
++ ipc_calls_.push_back(duplicate_handle_proxy);
++}
++
++bool HandleDispatcher::SetupService(InterceptionManager* manager,
++ IpcTag service) {
++ // We perform no interceptions for handles right now.
++ switch (service) {
++ case IpcTag::DUPLICATEHANDLEPROXY:
++ return true;
++
++ default:
++ return false;
++ }
++}
++
++bool HandleDispatcher::DuplicateHandleProxy(IPCInfo* ipc,
++ HANDLE source_handle,
++ uint32_t target_process_id,
++ uint32_t desired_access,
++ uint32_t options) {
++ static NtQueryObject QueryObject = NULL;
++ if (!QueryObject)
++ ResolveNTFunctionPtr("NtQueryObject", &QueryObject);
++
++ // Get a copy of the handle for use in the broker process.
++ HANDLE handle_temp;
++ if (!::DuplicateHandle(ipc->client_info->process, source_handle,
++ ::GetCurrentProcess(), &handle_temp,
++ 0, FALSE, DUPLICATE_SAME_ACCESS | options)) {
++ ipc->return_info.win32_result = ::GetLastError();
++ return false;
++ }
++ options &= ~DUPLICATE_CLOSE_SOURCE;
++ base::win::ScopedHandle handle(handle_temp);
++
++ // Get the object type (32 characters is safe; current max is 14).
++ BYTE buffer[sizeof(OBJECT_TYPE_INFORMATION) + 32 * sizeof(wchar_t)];
++ OBJECT_TYPE_INFORMATION* type_info =
++ reinterpret_cast<OBJECT_TYPE_INFORMATION*>(buffer);
++ ULONG size = sizeof(buffer) - sizeof(wchar_t);
++ NTSTATUS error =
++ QueryObject(handle.Get(), ObjectTypeInformation, type_info, size, &size);
++ if (!NT_SUCCESS(error)) {
++ ipc->return_info.nt_status = error;
++ return false;
++ }
++ type_info->Name.Buffer[type_info->Name.Length / sizeof(wchar_t)] = L'\0';
++
++ CountedParameterSet<HandleTarget> params;
++ params[HandleTarget::NAME] = ParamPickerMake(type_info->Name.Buffer);
++ params[HandleTarget::TARGET] = ParamPickerMake(target_process_id);
++
++ EvalResult eval = policy_base_->EvalPolicy(IpcTag::DUPLICATEHANDLEPROXY,
++ params.GetBase());
++ ipc->return_info.win32_result =
++ HandlePolicy::DuplicateHandleProxyAction(eval, handle.Get(),
++ target_process_id,
++ &ipc->return_info.handle,
++ desired_access, options);
++ return true;
++}
++
++} // namespace sandbox
++
+diff --git a/security/sandbox/chromium/sandbox/win/src/handle_dispatcher.h b/security/sandbox/chromium/sandbox/win/src/handle_dispatcher.h
+new file mode 100644
+--- /dev/null
++++ b/security/sandbox/chromium/sandbox/win/src/handle_dispatcher.h
+@@ -0,0 +1,41 @@
++// Copyright (c) 2012 The Chromium Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style license that can be
++// found in the LICENSE file.
++
++#ifndef SANDBOX_SRC_HANDLE_DISPATCHER_H_
++#define SANDBOX_SRC_HANDLE_DISPATCHER_H_
++
++#include <stdint.h>
++
++#include "base/macros.h"
++#include "sandbox/win/src/crosscall_server.h"
++#include "sandbox/win/src/sandbox_policy_base.h"
++
++namespace sandbox {
++
++// This class handles handle-related IPC calls.
++class HandleDispatcher : public Dispatcher {
++ public:
++ explicit HandleDispatcher(PolicyBase* policy_base);
++ ~HandleDispatcher() override {}
++
++ // Dispatcher interface.
++ bool SetupService(InterceptionManager* manager, IpcTag service) override;
++
++ private:
++ // Processes IPC requests coming from calls to
++ // TargetServices::DuplicateHandle() in the target.
++ bool DuplicateHandleProxy(IPCInfo* ipc,
++ HANDLE source_handle,
++ uint32_t target_process_id,
++ uint32_t desired_access,
++ uint32_t options);
++
++ PolicyBase* policy_base_;
++ DISALLOW_COPY_AND_ASSIGN(HandleDispatcher);
++};
++
++} // namespace sandbox
++
++#endif // SANDBOX_SRC_HANDLE_DISPATCHER_H_
++
+diff --git a/security/sandbox/chromium/sandbox/win/src/handle_interception.cc b/security/sandbox/chromium/sandbox/win/src/handle_interception.cc
+new file mode 100644
+--- /dev/null
++++ b/security/sandbox/chromium/sandbox/win/src/handle_interception.cc
+@@ -0,0 +1,45 @@
++// Copyright (c) 2012 The Chromium Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style license that can be
++// found in the LICENSE file.
++
++#include "sandbox/win/src/handle_interception.h"
++
++#include "sandbox/win/src/crosscall_client.h"
++#include "sandbox/win/src/ipc_tags.h"
++#include "sandbox/win/src/sandbox_factory.h"
++#include "sandbox/win/src/sandbox_nt_util.h"
++#include "sandbox/win/src/sharedmem_ipc_client.h"
++#include "sandbox/win/src/target_services.h"
++
++namespace sandbox {
++
++ResultCode DuplicateHandleProxy(HANDLE source_handle,
++ DWORD target_process_id,
++ HANDLE* target_handle,
++ DWORD desired_access,
++ DWORD options) {
++ *target_handle = NULL;
++
++ void* memory = GetGlobalIPCMemory();
++ if (NULL == memory)
++ return SBOX_ERROR_NO_SPACE;
++
++ SharedMemIPCClient ipc(memory);
++ CrossCallReturn answer = {0};
++ ResultCode code = CrossCall(ipc, IpcTag::DUPLICATEHANDLEPROXY,
++ source_handle, target_process_id,
++ desired_access, options, &answer);
++ if (SBOX_ALL_OK != code)
++ return code;
++
++ if (answer.win32_result) {
++ ::SetLastError(answer.win32_result);
++ return SBOX_ERROR_GENERIC;
++ }
++
++ *target_handle = answer.handle;
++ return SBOX_ALL_OK;
++}
++
++} // namespace sandbox
++
+diff --git a/security/sandbox/chromium/sandbox/win/src/handle_interception.h b/security/sandbox/chromium/sandbox/win/src/handle_interception.h
+new file mode 100644
+--- /dev/null
++++ b/security/sandbox/chromium/sandbox/win/src/handle_interception.h
+@@ -0,0 +1,24 @@
++// Copyright (c) 2012 The Chromium Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style license that can be
++// found in the LICENSE file.
++
++#include "sandbox/win/src/nt_internals.h"
++#include "sandbox/win/src/sandbox_types.h"
++
++#ifndef SANDBOX_SRC_HANDLE_INTERCEPTION_H_
++#define SANDBOX_SRC_HANDLE_INTERCEPTION_H_
++
++namespace sandbox {
++
++// TODO(jschuh) Add an interception to catch dangerous DuplicateHandle calls.
++
++ResultCode DuplicateHandleProxy(HANDLE source_handle,
++ DWORD target_process_id,
++ HANDLE* target_handle,
++ DWORD desired_access,
++ DWORD options);
++
++} // namespace sandbox
++
++#endif // SANDBOX_SRC_HANDLE_INTERCEPTION_H_
++
+diff --git a/security/sandbox/chromium/sandbox/win/src/handle_policy.cc b/security/sandbox/chromium/sandbox/win/src/handle_policy.cc
+new file mode 100644
+--- /dev/null
++++ b/security/sandbox/chromium/sandbox/win/src/handle_policy.cc
+@@ -0,0 +1,93 @@
++// Copyright (c) 2012 The Chromium Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style license that can be
++// found in the LICENSE file.
++
++#include "sandbox/win/src/handle_policy.h"
++
++#include <string>
++
++#include "base/win/scoped_handle.h"
++#include "sandbox/win/src/broker_services.h"
++#include "sandbox/win/src/ipc_tags.h"
++#include "sandbox/win/src/policy_engine_opcodes.h"
++#include "sandbox/win/src/policy_params.h"
++#include "sandbox/win/src/sandbox_types.h"
++#include "sandbox/win/src/sandbox_utils.h"
++
++namespace sandbox {
++
++bool HandlePolicy::GenerateRules(const wchar_t* type_name,
++ TargetPolicy::Semantics semantics,
++ LowLevelPolicy* policy) {
++ PolicyRule duplicate_rule(ASK_BROKER);
++
++ switch (semantics) {
++ case TargetPolicy::HANDLES_DUP_ANY: {
++ if (!duplicate_rule.AddNumberMatch(IF_NOT, HandleTarget::TARGET,
++ ::GetCurrentProcessId(), EQUAL)) {
++ return false;
++ }
++ break;
++ }
++
++ case TargetPolicy::HANDLES_DUP_BROKER: {
++ if (!duplicate_rule.AddNumberMatch(IF, HandleTarget::TARGET,
++ ::GetCurrentProcessId(), EQUAL)) {
++ return false;
++ }
++ break;
++ }
++
++ default:
++ return false;
++ }
++ if (!duplicate_rule.AddStringMatch(IF, HandleTarget::NAME, type_name,
++ CASE_INSENSITIVE)) {
++ return false;
++ }
++ if (!policy->AddRule(IpcTag::DUPLICATEHANDLEPROXY, &duplicate_rule)) {
++ return false;
++ }
++ return true;
++}
++
++DWORD HandlePolicy::DuplicateHandleProxyAction(EvalResult eval_result,
++ HANDLE source_handle,
++ DWORD target_process_id,
++ HANDLE* target_handle,
++ DWORD desired_access,
++ DWORD options) {
++ // The only action supported is ASK_BROKER which means duplicate the handle.
++ if (ASK_BROKER != eval_result) {
++ return ERROR_ACCESS_DENIED;
++ }
++
++ base::win::ScopedHandle remote_target_process;
++ if (target_process_id != ::GetCurrentProcessId()) {
++ // Sandboxed children are dynamic, so we check that manually.
++ if (!BrokerServicesBase::GetInstance()->IsSafeDuplicationTarget(
++ target_process_id)) {
++ return ERROR_ACCESS_DENIED;
++ }
++
++ remote_target_process.Set(::OpenProcess(PROCESS_DUP_HANDLE, FALSE,
++ target_process_id));
++ if (!remote_target_process.IsValid())
++ return ::GetLastError();
++ }
++
++ // If the policy didn't block us and we have no valid target, then the broker
++ // (this process) is the valid target.
++ HANDLE target_process = remote_target_process.IsValid() ?
++ remote_target_process.Get() : ::GetCurrentProcess();
++ if (!::DuplicateHandle(::GetCurrentProcess(), source_handle, target_process,
++ target_handle, desired_access, FALSE,
++ options)) {
++ return ::GetLastError();
++ }
++
++ return ERROR_SUCCESS;
++}
++
++} // namespace sandbox
++
+diff --git a/security/sandbox/chromium/sandbox/win/src/handle_policy.h b/security/sandbox/chromium/sandbox/win/src/handle_policy.h
+new file mode 100644
+--- /dev/null
++++ b/security/sandbox/chromium/sandbox/win/src/handle_policy.h
+@@ -0,0 +1,39 @@
++// Copyright (c) 2012 The Chromium Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style license that can be
++// found in the LICENSE file.
++
++#ifndef SANDBOX_SRC_HANDLE_POLICY_H_
++#define SANDBOX_SRC_HANDLE_POLICY_H_
++
++#include <string>
++
++#include "sandbox/win/src/crosscall_server.h"
++#include "sandbox/win/src/policy_low_level.h"
++#include "sandbox/win/src/sandbox_policy.h"
++
++namespace sandbox {
++
++enum EvalResult;
++
++// This class centralizes most of the knowledge related to handle policy.
++class HandlePolicy {
++ public:
++ // Creates the required low-level policy rules to evaluate a high-level
++ // policy rule for handles, in particular duplicate action.
++ static bool GenerateRules(const wchar_t* type_name,
++ TargetPolicy::Semantics semantics,
++ LowLevelPolicy* policy);
++
++ // Processes a 'TargetPolicy::DuplicateHandle()' request from the target.
++ static DWORD DuplicateHandleProxyAction(EvalResult eval_result,
++ HANDLE source_handle,
++ DWORD target_process_id,
++ HANDLE* target_handle,
++ DWORD desired_access,
++ DWORD options);
++};
++
++} // namespace sandbox
++
++#endif // SANDBOX_SRC_HANDLE_POLICY_H_
++
+diff --git a/security/sandbox/chromium/sandbox/win/src/handle_policy_test.cc b/security/sandbox/chromium/sandbox/win/src/handle_policy_test.cc
+new file mode 100644
+--- /dev/null
++++ b/security/sandbox/chromium/sandbox/win/src/handle_policy_test.cc
+@@ -0,0 +1,114 @@
++// Copyright (c) 2012 The Chromium Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style license that can be
++// found in the LICENSE file.
++
++#include "base/strings/stringprintf.h"
++#include "sandbox/win/src/handle_policy.h"
++#include "sandbox/win/src/nt_internals.h"
++#include "sandbox/win/src/sandbox.h"
++#include "sandbox/win/src/sandbox_factory.h"
++#include "sandbox/win/src/sandbox_policy.h"
++#include "sandbox/win/src/win_utils.h"
++#include "sandbox/win/tests/common/controller.h"
++#include "testing/gtest/include/gtest/gtest.h"
++
++namespace sandbox {
++
++// Just waits for the supplied number of milliseconds.
++SBOX_TESTS_COMMAND int Handle_WaitProcess(int argc, wchar_t **argv) {
++ if (argc != 1)
++ return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
++
++ ::Sleep(::wcstoul(argv[0], NULL, 10));
++ return SBOX_TEST_TIMED_OUT;
++}
++
++// Attempts to duplicate an event handle into the target process.
++SBOX_TESTS_COMMAND int Handle_DuplicateEvent(int argc, wchar_t **argv) {
++ if (argc != 1)
++ return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND;
++
++ // Create a test event to use as a handle.
++ base::win::ScopedHandle test_event;
++ test_event.Set(::CreateEvent(NULL, TRUE, TRUE, NULL));
++ if (!test_event.IsValid())
++ return SBOX_TEST_FIRST_ERROR;
++
++ // Get the target process ID.
++ DWORD target_process_id = ::wcstoul(argv[0], NULL, 10);
++
++ HANDLE handle = NULL;
++ ResultCode result = SandboxFactory::GetTargetServices()->DuplicateHandle(
++ test_event.Get(), target_process_id, &handle, 0, DUPLICATE_SAME_ACCESS);
++
++ return (result == SBOX_ALL_OK) ? SBOX_TEST_SUCCEEDED : SBOX_TEST_DENIED;
++}
++
++// Tests that duplicating an object works only when the policy allows it.
++TEST(HandlePolicyTest, DuplicateHandle) {
++ TestRunner target;
++ TestRunner runner;
++
++ // Kick off an asynchronous target process for testing.
++ target.SetAsynchronous(true);
++ EXPECT_EQ(SBOX_TEST_SUCCEEDED, target.RunTest(L"Handle_WaitProcess 30000"));
++
++ // First test that we fail to open the event.
++ base::string16 cmd_line = base::StringPrintf(L"Handle_DuplicateEvent %d",
++ target.process_id());
++ EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(cmd_line.c_str()));
++
++ // Now successfully open the event after adding a duplicate handle rule.
++ EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_HANDLES,
++ TargetPolicy::HANDLES_DUP_ANY,
++ L"Event"));
++ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(cmd_line.c_str()));
++}
++
++// Tests that duplicating an object works only when the policy allows it.
++TEST(HandlePolicyTest, DuplicatePeerHandle) {
++ TestRunner target;
++ TestRunner runner;
++
++ // Kick off an asynchronous target process for testing.
++ target.SetAsynchronous(true);
++ target.SetUnsandboxed(true);
++ EXPECT_EQ(SBOX_TEST_SUCCEEDED, target.RunTest(L"Handle_WaitProcess 30000"));
++
++ // First test that we fail to open the event.
++ base::string16 cmd_line = base::StringPrintf(L"Handle_DuplicateEvent %d",
++ target.process_id());
++ EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(cmd_line.c_str()));
++
++ // Now successfully open the event after adding a duplicate handle rule.
++ EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_HANDLES,
++ TargetPolicy::HANDLES_DUP_ANY,
++ L"Event"));
++ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(cmd_line.c_str()));
++}
++
++// Tests that duplicating an object works only when the policy allows it.
++TEST(HandlePolicyTest, DuplicateBrokerHandle) {
++ TestRunner runner;
++
++ // First test that we fail to open the event.
++ base::string16 cmd_line = base::StringPrintf(L"Handle_DuplicateEvent %d",
++ ::GetCurrentProcessId());
++ EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(cmd_line.c_str()));
++
++ // Add the peer rule and make sure we fail again.
++ EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_HANDLES,
++ TargetPolicy::HANDLES_DUP_ANY,
++ L"Event"));
++ EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(cmd_line.c_str()));
++
++
++ // Now successfully open the event after adding a broker handle rule.
++ EXPECT_TRUE(runner.AddRule(TargetPolicy::SUBSYS_HANDLES,
++ TargetPolicy::HANDLES_DUP_BROKER,
++ L"Event"));
++ EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(cmd_line.c_str()));
++}
++
++} // namespace sandbox
++
+diff --git a/security/sandbox/chromium/sandbox/win/src/ipc_tags.h b/security/sandbox/chromium/sandbox/win/src/ipc_tags.h
+--- a/security/sandbox/chromium/sandbox/win/src/ipc_tags.h
++++ b/security/sandbox/chromium/sandbox/win/src/ipc_tags.h
+@@ -23,16 +23,17 @@ enum class IpcTag {
+ NTOPENPROCESS,
+ NTOPENPROCESSTOKEN,
+ NTOPENPROCESSTOKENEX,
+ CREATEPROCESSW,
+ CREATEEVENT,
+ OPENEVENT,
+ NTCREATEKEY,
+ NTOPENKEY,
++ DUPLICATEHANDLEPROXY,
+ GDI_GDIDLLINITIALIZE,
+ GDI_GETSTOCKOBJECT,
+ USER_REGISTERCLASSW,
+ CREATETHREAD,
+ USER_ENUMDISPLAYMONITORS,
+ USER_ENUMDISPLAYDEVICES,
+ USER_GETMONITORINFO,
+ GDI_CREATEOPMPROTECTEDOUTPUTS,
+diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox.h b/security/sandbox/chromium/sandbox/win/src/sandbox.h
+--- a/security/sandbox/chromium/sandbox/win/src/sandbox.h
++++ b/security/sandbox/chromium/sandbox/win/src/sandbox.h
+@@ -161,16 +161,30 @@ class TargetServices {
+ // fails the current process could be terminated immediately.
+ virtual void LowerToken() = 0;
+
+ // Returns the ProcessState object. Through that object it's possible to have
+ // information about the current state of the process, such as whether
+ // LowerToken has been called or not.
+ virtual ProcessState* GetState() = 0;
+
++ // Requests the broker to duplicate the supplied handle into the target
++ // process. The target process must be an active sandbox child process
++ // and the source process must have a corresponding policy allowing
++ // handle duplication for this object type.
++ // Returns:
++ // ALL_OK if successful. All other return values imply failure.
++ // If the return is ERROR_GENERIC, you can call ::GetLastError() to get
++ // more information.
++ virtual ResultCode DuplicateHandle(HANDLE source_handle,
++ DWORD target_process_id,
++ HANDLE* target_handle,
++ DWORD desired_access,
++ DWORD options) = 0;
++
+ protected:
+ ~TargetServices() {}
+ };
+
+ class PolicyInfo {
+ public:
+ // Returns a JSON representation of the policy snapshot.
+ // This pointer has the same lifetime as this PolicyInfo object.
+diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_policy.h b/security/sandbox/chromium/sandbox/win/src/sandbox_policy.h
+--- a/security/sandbox/chromium/sandbox/win/src/sandbox_policy.h
++++ b/security/sandbox/chromium/sandbox/win/src/sandbox_policy.h
+@@ -25,28 +25,32 @@ class TargetPolicy {
+ // exactly like the CreateProcess API does. See the comment at the top of
+ // process_thread_dispatcher.cc for more details.
+ enum SubSystem {
+ SUBSYS_FILES, // Creation and opening of files and pipes.
+ SUBSYS_NAMED_PIPES, // Creation of named pipes.
+ SUBSYS_PROCESS, // Creation of child processes.
+ SUBSYS_REGISTRY, // Creation and opening of registry keys.
+ SUBSYS_SYNC, // Creation of named sync objects.
++ SUBSYS_HANDLES, // Duplication of handles to other processes.
+ SUBSYS_WIN32K_LOCKDOWN, // Win32K Lockdown related policy.
+ SUBSYS_SIGNED_BINARY // Signed binary policy.
+ };
+
+ // Allowable semantics when a rule is matched.
+ enum Semantics {
+ FILES_ALLOW_ANY, // Allows open or create for any kind of access that
+ // the file system supports.
+ FILES_ALLOW_READONLY, // Allows open or create with read access only.
+ FILES_ALLOW_QUERY, // Allows access to query the attributes of a file.
+ FILES_ALLOW_DIR_ANY, // Allows open or create with directory semantics
+ // only.
++ HANDLES_DUP_ANY, // Allows duplicating handles opened with any
++ // access permissions.
++ HANDLES_DUP_BROKER, // Allows duplicating handles to the broker process.
+ NAMEDPIPES_ALLOW_ANY, // Allows creation of a named pipe.
+ PROCESS_MIN_EXEC, // Allows to create a process with minimal rights
+ // over the resulting process and thread handles.
+ // No other parameters besides the command line are
+ // passed to the child process.
+ PROCESS_ALL_EXEC, // Allows the creation of a process and return full
+ // access on the returned handles.
+ // This flag can be used only when the main token of
+diff --git a/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc b/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc
+--- a/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc
++++ b/security/sandbox/chromium/sandbox/win/src/sandbox_policy_base.cc
+@@ -12,16 +12,17 @@
+ #include "base/logging.h"
+ #include "base/macros.h"
+ #include "base/stl_util.h"
+ #include "base/strings/stringprintf.h"
+ #include "base/win/win_util.h"
+ #include "base/win/windows_version.h"
+ #include "sandbox/win/src/acl.h"
+ #include "sandbox/win/src/filesystem_policy.h"
++#include "sandbox/win/src/handle_policy.h"
+ #include "sandbox/win/src/interception.h"
+ #include "sandbox/win/src/job.h"
+ #include "sandbox/win/src/named_pipe_policy.h"
+ #include "sandbox/win/src/policy_broker.h"
+ #include "sandbox/win/src/policy_engine_processor.h"
+ #include "sandbox/win/src/policy_low_level.h"
+ #include "sandbox/win/src/process_mitigations.h"
+ #include "sandbox/win/src/process_mitigations_win32k_policy.h"
+@@ -754,16 +755,24 @@ ResultCode PolicyBase::AddRuleInternal(S
+ }
+ case SUBSYS_REGISTRY: {
+ if (!RegistryPolicy::GenerateRules(pattern, semantics, policy_maker_)) {
+ NOTREACHED();
+ return SBOX_ERROR_BAD_PARAMS;
+ }
+ break;
+ }
++ case SUBSYS_HANDLES: {
++ if (!HandlePolicy::GenerateRules(pattern, semantics, policy_maker_)) {
++ NOTREACHED();
++ return SBOX_ERROR_BAD_PARAMS;
++ }
++ break;
++ }
++
+ case SUBSYS_WIN32K_LOCKDOWN: {
+ // Win32k intercept rules only supported on Windows 8 and above. This must
+ // match the version checks in process_mitigations.cc for consistency.
+ if (base::win::GetVersion() >= base::win::Version::WIN8) {
+ DCHECK_EQ(MITIGATION_WIN32K_DISABLE,
+ mitigations_ & MITIGATION_WIN32K_DISABLE)
+ << "Enable MITIGATION_WIN32K_DISABLE before adding win32k policy "
+ "rules.";
+diff --git a/security/sandbox/chromium/sandbox/win/src/target_services.cc b/security/sandbox/chromium/sandbox/win/src/target_services.cc
+--- a/security/sandbox/chromium/sandbox/win/src/target_services.cc
++++ b/security/sandbox/chromium/sandbox/win/src/target_services.cc
+@@ -7,16 +7,17 @@
+ #include <new>
+
+ #include <process.h>
+ #include <stdint.h>
+
+ #include "base/win/windows_version.h"
+ #include "sandbox/win/src/crosscall_client.h"
+ #include "sandbox/win/src/handle_closer_agent.h"
++#include "sandbox/win/src/handle_interception.h"
+ #include "sandbox/win/src/heap_helper.h"
+ #include "sandbox/win/src/ipc_tags.h"
+ #include "sandbox/win/src/process_mitigations.h"
+ #include "sandbox/win/src/restricted_token_utils.h"
+ #include "sandbox/win/src/sandbox.h"
+ #include "sandbox/win/src/sandbox_nt_util.h"
+ #include "sandbox/win/src/sandbox_types.h"
+ #include "sandbox/win/src/sharedmem_ipc_client.h"
+@@ -239,9 +240,19 @@ void ProcessState::SetRevertedToSelf() {
+ if (process_state_ < ProcessStateInternal::REVERTED_TO_SELF)
+ process_state_ = ProcessStateInternal::REVERTED_TO_SELF;
+ }
+
+ void ProcessState::SetCsrssConnected(bool csrss_connected) {
+ csrss_connected_ = csrss_connected;
+ }
+
++
++ResultCode TargetServicesBase::DuplicateHandle(HANDLE source_handle,
++ DWORD target_process_id,
++ HANDLE* target_handle,
++ DWORD desired_access,
++ DWORD options) {
++ return sandbox::DuplicateHandleProxy(source_handle, target_process_id,
++ target_handle, desired_access, options);
++}
++
+ } // namespace sandbox
+diff --git a/security/sandbox/chromium/sandbox/win/src/target_services.h b/security/sandbox/chromium/sandbox/win/src/target_services.h
+--- a/security/sandbox/chromium/sandbox/win/src/target_services.h
++++ b/security/sandbox/chromium/sandbox/win/src/target_services.h
+@@ -40,16 +40,21 @@ class ProcessState {
+ class TargetServicesBase : public TargetServices {
+ public:
+ TargetServicesBase();
+
+ // Public interface of TargetServices.
+ ResultCode Init() override;
+ void LowerToken() override;
+ ProcessState* GetState() override;
++ ResultCode DuplicateHandle(HANDLE source_handle,
++ DWORD target_process_id,
++ HANDLE* target_handle,
++ DWORD desired_access,
++ DWORD options) override;
+
+ // Factory method.
+ static TargetServicesBase* GetInstance();
+
+ // Sends a simple IPC Message that has a well-known answer. Returns true
+ // if the IPC was successful and false otherwise. There are 2 versions of
+ // this test: 1 and 2. The first one send a simple message while the
+ // second one send a message with an in/out param.
+diff --git a/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.cc b/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.cc
+--- a/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.cc
++++ b/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.cc
+@@ -5,16 +5,17 @@
+ #include "sandbox/win/src/top_level_dispatcher.h"
+
+ #include <stdint.h>
+ #include <string.h>
+
+ #include "base/logging.h"
+ #include "sandbox/win/src/crosscall_server.h"
+ #include "sandbox/win/src/filesystem_dispatcher.h"
++#include "sandbox/win/src/handle_dispatcher.h"
+ #include "sandbox/win/src/interception.h"
+ #include "sandbox/win/src/internal_types.h"
+ #include "sandbox/win/src/ipc_tags.h"
+ #include "sandbox/win/src/named_pipe_dispatcher.h"
+ #include "sandbox/win/src/process_mitigations_win32k_dispatcher.h"
+ #include "sandbox/win/src/process_thread_dispatcher.h"
+ #include "sandbox/win/src/registry_dispatcher.h"
+ #include "sandbox/win/src/sandbox_policy_base.h"
+@@ -55,16 +56,20 @@ TopLevelDispatcher::TopLevelDispatcher(P
+ ipc_targets_[static_cast<size_t>(IpcTag::OPENEVENT)] = dispatcher;
+ sync_dispatcher_.reset(dispatcher);
+
+ dispatcher = new RegistryDispatcher(policy_);
+ ipc_targets_[static_cast<size_t>(IpcTag::NTCREATEKEY)] = dispatcher;
+ ipc_targets_[static_cast<size_t>(IpcTag::NTOPENKEY)] = dispatcher;
+ registry_dispatcher_.reset(dispatcher);
+
++ dispatcher = new HandleDispatcher(policy_);
++ ipc_targets_[static_cast<size_t>(IpcTag::DUPLICATEHANDLEPROXY)] = dispatcher;
++ handle_dispatcher_.reset(dispatcher);
++
+ dispatcher = new ProcessMitigationsWin32KDispatcher(policy_);
+ ipc_targets_[static_cast<size_t>(IpcTag::GDI_GDIDLLINITIALIZE)] = dispatcher;
+ ipc_targets_[static_cast<size_t>(IpcTag::GDI_GETSTOCKOBJECT)] = dispatcher;
+ ipc_targets_[static_cast<size_t>(IpcTag::USER_REGISTERCLASSW)] = dispatcher;
+ ipc_targets_[static_cast<size_t>(IpcTag::USER_ENUMDISPLAYMONITORS)] =
+ dispatcher;
+ ipc_targets_[static_cast<size_t>(IpcTag::USER_ENUMDISPLAYDEVICES)] =
+ dispatcher;