# HG changeset patch # User Toshihito Kikuchi # 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 + +#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( + &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(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 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 + +#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 + +#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 + +#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 #include #include #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 #include #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(IpcTag::OPENEVENT)] = dispatcher; sync_dispatcher_.reset(dispatcher); dispatcher = new RegistryDispatcher(policy_); ipc_targets_[static_cast(IpcTag::NTCREATEKEY)] = dispatcher; ipc_targets_[static_cast(IpcTag::NTOPENKEY)] = dispatcher; registry_dispatcher_.reset(dispatcher); + dispatcher = new HandleDispatcher(policy_); + ipc_targets_[static_cast(IpcTag::DUPLICATEHANDLEPROXY)] = dispatcher; + handle_dispatcher_.reset(dispatcher); + dispatcher = new ProcessMitigationsWin32KDispatcher(policy_); ipc_targets_[static_cast(IpcTag::GDI_GDIDLLINITIALIZE)] = dispatcher; ipc_targets_[static_cast(IpcTag::GDI_GETSTOCKOBJECT)] = dispatcher; ipc_targets_[static_cast(IpcTag::USER_REGISTERCLASSW)] = dispatcher; ipc_targets_[static_cast(IpcTag::USER_ENUMDISPLAYMONITORS)] = dispatcher; ipc_targets_[static_cast(IpcTag::USER_ENUMDISPLAYDEVICES)] = dispatcher;