diff options
Diffstat (limited to 'sandbox/win/src/handle_dispatcher.cc')
-rw-r--r-- | sandbox/win/src/handle_dispatcher.cc | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/sandbox/win/src/handle_dispatcher.cc b/sandbox/win/src/handle_dispatcher.cc new file mode 100644 index 0000000..7a18cee --- /dev/null +++ b/sandbox/win/src/handle_dispatcher.cc @@ -0,0 +1,90 @@ +// 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/src/handle_dispatcher.h" + +#include "base/win/scoped_handle.h" +#include "sandbox/src/handle_interception.h" +#include "sandbox/src/handle_policy.h" +#include "sandbox/src/ipc_tags.h" +#include "sandbox/src/policy_broker.h" +#include "sandbox/src/policy_params.h" +#include "sandbox/src/sandbox.h" +#include "sandbox/src/sandbox_nt_util.h" +#include "sandbox/src/sandbox_types.h" +#include "sandbox/src/sandbox_utils.h" + +namespace sandbox { + +HandleDispatcher::HandleDispatcher(PolicyBase* policy_base) + : policy_base_(policy_base) { + static const IPCCall duplicate_handle_proxy = { + {IPC_DUPLICATEHANDLEPROXY_TAG, VOIDPTR_TYPE, ULONG_TYPE, ULONG_TYPE, + ULONG_TYPE}, + reinterpret_cast<CallbackGeneric>(&HandleDispatcher::DuplicateHandleProxy) + }; + + ipc_calls_.push_back(duplicate_handle_proxy); +} + +bool HandleDispatcher::SetupService(InterceptionManager* manager, + int service) { + // We perform no interceptions for handles right now. + switch (service) { + case IPC_DUPLICATEHANDLEPROXY_TAG: + return true; + } + + return false; +} + +bool HandleDispatcher::DuplicateHandleProxy(IPCInfo* ipc, + HANDLE source_handle, + DWORD target_process_id, + DWORD desired_access, + DWORD options) { + NTSTATUS error; + 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)) { + ipc->return_info.win32_result = ::GetLastError(); + return false; + } + 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); + error = QueryObject(handle, ObjectTypeInformation, type_info, size, &size); + if (!NT_SUCCESS(error)) { + ipc->return_info.win32_result = 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(IPC_DUPLICATEHANDLEPROXY_TAG, + params.GetBase()); + ipc->return_info.win32_result = + HandlePolicy::DuplicateHandleProxyAction(eval, *ipc->client_info, + source_handle, + target_process_id, + &ipc->return_info.handle, + desired_access, options); + return true; +} + +} // namespace sandbox + |