diff options
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.patch | 743 |
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; |