diff options
Diffstat (limited to '')
-rw-r--r-- | security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.cc | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.cc b/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.cc new file mode 100644 index 0000000000..3c8f8e25e5 --- /dev/null +++ b/security/sandbox/chromium/sandbox/win/src/top_level_dispatcher.cc @@ -0,0 +1,178 @@ +// Copyright 2015 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/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/line_break_dispatcher.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" +#include "sandbox/win/src/signed_dispatcher.h" +#include "sandbox/win/src/sync_dispatcher.h" + +namespace sandbox { + +TopLevelDispatcher::TopLevelDispatcher(PolicyBase* policy) : policy_(policy) { + // Initialize the IPC dispatcher array. + memset(ipc_targets_, 0, sizeof(ipc_targets_)); + Dispatcher* dispatcher; + + dispatcher = new FilesystemDispatcher(policy_); + ipc_targets_[static_cast<size_t>(IpcTag::NTCREATEFILE)] = dispatcher; + ipc_targets_[static_cast<size_t>(IpcTag::NTOPENFILE)] = dispatcher; + ipc_targets_[static_cast<size_t>(IpcTag::NTSETINFO_RENAME)] = dispatcher; + ipc_targets_[static_cast<size_t>(IpcTag::NTQUERYATTRIBUTESFILE)] = dispatcher; + ipc_targets_[static_cast<size_t>(IpcTag::NTQUERYFULLATTRIBUTESFILE)] = + dispatcher; + filesystem_dispatcher_.reset(dispatcher); + + dispatcher = new NamedPipeDispatcher(policy_); + ipc_targets_[static_cast<size_t>(IpcTag::CREATENAMEDPIPEW)] = dispatcher; + named_pipe_dispatcher_.reset(dispatcher); + + dispatcher = new ThreadProcessDispatcher(policy_); + ipc_targets_[static_cast<size_t>(IpcTag::NTOPENTHREAD)] = dispatcher; + ipc_targets_[static_cast<size_t>(IpcTag::NTOPENPROCESS)] = dispatcher; + ipc_targets_[static_cast<size_t>(IpcTag::CREATEPROCESSW)] = dispatcher; + ipc_targets_[static_cast<size_t>(IpcTag::NTOPENPROCESSTOKEN)] = dispatcher; + ipc_targets_[static_cast<size_t>(IpcTag::NTOPENPROCESSTOKENEX)] = dispatcher; + ipc_targets_[static_cast<size_t>(IpcTag::CREATETHREAD)] = dispatcher; + thread_process_dispatcher_.reset(dispatcher); + + dispatcher = new SyncDispatcher(policy_); + ipc_targets_[static_cast<size_t>(IpcTag::CREATEEVENT)] = dispatcher; + 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; + ipc_targets_[static_cast<size_t>(IpcTag::USER_GETMONITORINFO)] = dispatcher; + ipc_targets_[static_cast<size_t>(IpcTag::GDI_CREATEOPMPROTECTEDOUTPUTS)] = + dispatcher; + ipc_targets_[static_cast<size_t>(IpcTag::GDI_GETCERTIFICATE)] = dispatcher; + ipc_targets_[static_cast<size_t>(IpcTag::GDI_GETCERTIFICATESIZE)] = + dispatcher; + ipc_targets_[static_cast<size_t>(IpcTag::GDI_DESTROYOPMPROTECTEDOUTPUT)] = + dispatcher; + ipc_targets_[static_cast<size_t>(IpcTag::GDI_CONFIGUREOPMPROTECTEDOUTPUT)] = + dispatcher; + ipc_targets_[static_cast<size_t>(IpcTag::GDI_GETOPMINFORMATION)] = dispatcher; + ipc_targets_[static_cast<size_t>(IpcTag::GDI_GETOPMRANDOMNUMBER)] = + dispatcher; + ipc_targets_[static_cast<size_t>( + IpcTag::GDI_GETSUGGESTEDOPMPROTECTEDOUTPUTARRAYSIZE)] = dispatcher; + ipc_targets_[static_cast<size_t>( + IpcTag::GDI_SETOPMSIGNINGKEYANDSEQUENCENUMBERS)] = dispatcher; + process_mitigations_win32k_dispatcher_.reset(dispatcher); + + dispatcher = new SignedDispatcher(policy_); + ipc_targets_[static_cast<size_t>(IpcTag::NTCREATESECTION)] = dispatcher; + signed_dispatcher_.reset(dispatcher); + + dispatcher = new LineBreakDispatcher(policy_); + ipc_targets_[static_cast<size_t>(IpcTag::GETCOMPLEXLINEBREAKS)] = dispatcher; + line_break_dispatcher_.reset(dispatcher); +} + +TopLevelDispatcher::~TopLevelDispatcher() {} + +// When an IPC is ready in any of the targets we get called. We manage an array +// of IPC dispatchers which are keyed on the IPC tag so we normally delegate +// to the appropriate dispatcher unless we can handle the IPC call ourselves. +Dispatcher* TopLevelDispatcher::OnMessageReady(IPCParams* ipc, + CallbackGeneric* callback) { + DCHECK(callback); + static const IPCParams ping1 = {IpcTag::PING1, {UINT32_TYPE}}; + static const IPCParams ping2 = {IpcTag::PING2, {INOUTPTR_TYPE}}; + + if (ping1.Matches(ipc) || ping2.Matches(ipc)) { + *callback = reinterpret_cast<CallbackGeneric>( + static_cast<Callback1>(&TopLevelDispatcher::Ping)); + return this; + } + + Dispatcher* dispatcher = GetDispatcher(ipc->ipc_tag); + if (!dispatcher) { + NOTREACHED(); + return nullptr; + } + return dispatcher->OnMessageReady(ipc, callback); +} + +// Delegate to the appropriate dispatcher. +bool TopLevelDispatcher::SetupService(InterceptionManager* manager, + IpcTag service) { + if (IpcTag::PING1 == service || IpcTag::PING2 == service) + return true; + + Dispatcher* dispatcher = GetDispatcher(service); + if (!dispatcher) { + NOTREACHED(); + return false; + } + return dispatcher->SetupService(manager, service); +} + +// We service PING message which is a way to test a round trip of the +// IPC subsystem. We receive a integer cookie and we are expected to return the +// cookie times two (or three) and the current tick count. +bool TopLevelDispatcher::Ping(IPCInfo* ipc, void* arg1) { + switch (ipc->ipc_tag) { + case IpcTag::PING1: { + IPCInt ipc_int(arg1); + uint32_t cookie = ipc_int.As32Bit(); + ipc->return_info.extended_count = 2; + ipc->return_info.extended[0].unsigned_int = ::GetTickCount(); + ipc->return_info.extended[1].unsigned_int = 2 * cookie; + return true; + } + case IpcTag::PING2: { + CountedBuffer* io_buffer = reinterpret_cast<CountedBuffer*>(arg1); + if (sizeof(uint32_t) != io_buffer->Size()) + return false; + + uint32_t* cookie = reinterpret_cast<uint32_t*>(io_buffer->Buffer()); + *cookie = (*cookie) * 3; + return true; + } + default: + return false; + } +} + +Dispatcher* TopLevelDispatcher::GetDispatcher(IpcTag ipc_tag) { + if (ipc_tag >= IpcTag::LAST || ipc_tag <= IpcTag::UNUSED) + return nullptr; + + return ipc_targets_[static_cast<size_t>(ipc_tag)]; +} + +} // namespace sandbox |