forked from mirrors/gecko-dev
Bug 1878638 p3: Remove sandbox DuplicateHandle brokering. r=handyman
This was removed from chromium and we no longer need to add it back. Differential Revision: https://phabricator.services.mozilla.com/D200904
This commit is contained in:
parent
30b777cfd9
commit
bf1aba0029
19 changed files with 1 additions and 1250 deletions
2
CLOBBER
2
CLOBBER
|
|
@ -22,4 +22,4 @@
|
|||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
Modified build files in third_party/libwebrtc - Bug 1876843 - Vendor libwebrtc from 24510d43dc
|
||||
Removed proxying objects - Bug 1878638: Remove handle duplication rules for Windows process sandboxes
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
revert_remove_AddTargetPeer.patch
|
||||
revert_remove_BrokerDuplicateHandle.patch
|
||||
replace_ScopedNativeLibrary_in_ApplyMitigationsToCurrentThread.patch
|
||||
ifdef_out_FromStringInternal.patch
|
||||
add_option_to_not_use_restricting_sids.patch
|
||||
|
|
|
|||
|
|
@ -1,743 +0,0 @@
|
|||
# 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;
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
// 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
|
||||
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
// 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_
|
||||
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
// 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"
|
||||
#include "mozilla/sandboxing/sandboxLogging.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);
|
||||
mozilla::sandboxing::LogBlocked("DuplicateHandle");
|
||||
return SBOX_ERROR_GENERIC;
|
||||
}
|
||||
|
||||
*target_handle = answer.handle;
|
||||
mozilla::sandboxing::LogAllowed("DuplicateHandle");
|
||||
return SBOX_ALL_OK;
|
||||
}
|
||||
|
||||
} // namespace sandbox
|
||||
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
// 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_
|
||||
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
// 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
|
||||
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
// 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_
|
||||
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
// 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
|
||||
|
||||
|
|
@ -28,7 +28,6 @@ enum class IpcTag {
|
|||
OPENEVENT,
|
||||
NTCREATEKEY,
|
||||
NTOPENKEY,
|
||||
DUPLICATEHANDLEPROXY,
|
||||
GDI_GDIDLLINITIALIZE,
|
||||
GDI_GETSTOCKOBJECT,
|
||||
USER_REGISTERCLASSW,
|
||||
|
|
|
|||
|
|
@ -172,20 +172,6 @@ class TargetServices {
|
|||
// 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;
|
||||
|
||||
virtual ResultCode GetComplexLineBreaks(const WCHAR* text, uint32_t length,
|
||||
uint8_t* break_before) = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ class TargetPolicy {
|
|||
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_LINE_BREAK // Complex line break policy.
|
||||
|
|
@ -44,9 +43,6 @@ class TargetPolicy {
|
|||
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.
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@
|
|||
#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"
|
||||
|
|
@ -775,14 +774,6 @@ ResultCode PolicyBase::AddRuleInternal(SubSystem subsystem,
|
|||
}
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@
|
|||
#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"
|
||||
|
|
@ -246,15 +245,6 @@ 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) {
|
||||
|
|
|
|||
|
|
@ -45,11 +45,6 @@ class TargetServicesBase : public 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;
|
||||
ResultCode GetComplexLineBreaks(const WCHAR* text, uint32_t length,
|
||||
uint8_t* break_before) final;
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@
|
|||
#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"
|
||||
|
|
@ -62,10 +61,6 @@ TopLevelDispatcher::TopLevelDispatcher(PolicyBase* policy) : policy_(policy) {
|
|||
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;
|
||||
|
|
|
|||
|
|
@ -113,9 +113,6 @@ elif CONFIG["OS_ARCH"] == "WINNT":
|
|||
"chromium/sandbox/win/src/filesystem_policy.cc",
|
||||
"chromium/sandbox/win/src/handle_closer.cc",
|
||||
"chromium/sandbox/win/src/handle_closer_agent.cc",
|
||||
"chromium/sandbox/win/src/handle_dispatcher.cc",
|
||||
"chromium/sandbox/win/src/handle_interception.cc",
|
||||
"chromium/sandbox/win/src/handle_policy.cc",
|
||||
"chromium/sandbox/win/src/heap_helper.cc",
|
||||
"chromium/sandbox/win/src/interception.cc",
|
||||
"chromium/sandbox/win/src/interception_agent.cc",
|
||||
|
|
|
|||
|
|
@ -1833,8 +1833,6 @@ void SandboxBroker::ApplyLoggingPolicy() {
|
|||
L"HKEY_CURRENT_USER\\dummy");
|
||||
mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_SYNC,
|
||||
sandbox::TargetPolicy::EVENTS_ALLOW_READONLY, L"dummy");
|
||||
mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_HANDLES,
|
||||
sandbox::TargetPolicy::HANDLES_DUP_BROKER, L"dummy");
|
||||
}
|
||||
|
||||
SandboxBroker::~SandboxBroker() {
|
||||
|
|
|
|||
Loading…
Reference in a new issue