| OLD | NEW |
| (Empty) |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "sandbox/win/src/top_level_dispatcher.h" | |
| 6 | |
| 7 #include <stdint.h> | |
| 8 #include <string.h> | |
| 9 | |
| 10 #include "base/logging.h" | |
| 11 #include "base/memory/scoped_ptr.h" | |
| 12 #include "sandbox/win/src/crosscall_server.h" | |
| 13 #include "sandbox/win/src/filesystem_dispatcher.h" | |
| 14 #include "sandbox/win/src/handle_dispatcher.h" | |
| 15 #include "sandbox/win/src/interception.h" | |
| 16 #include "sandbox/win/src/internal_types.h" | |
| 17 #include "sandbox/win/src/ipc_tags.h" | |
| 18 #include "sandbox/win/src/named_pipe_dispatcher.h" | |
| 19 #include "sandbox/win/src/process_mitigations_win32k_dispatcher.h" | |
| 20 #include "sandbox/win/src/process_thread_dispatcher.h" | |
| 21 #include "sandbox/win/src/registry_dispatcher.h" | |
| 22 #include "sandbox/win/src/sandbox_policy_base.h" | |
| 23 #include "sandbox/win/src/sync_dispatcher.h" | |
| 24 | |
| 25 namespace sandbox { | |
| 26 | |
| 27 TopLevelDispatcher::TopLevelDispatcher(PolicyBase* policy) : policy_(policy) { | |
| 28 // Initialize the IPC dispatcher array. | |
| 29 memset(ipc_targets_, 0, sizeof(ipc_targets_)); | |
| 30 Dispatcher* dispatcher; | |
| 31 | |
| 32 dispatcher = new FilesystemDispatcher(policy_); | |
| 33 ipc_targets_[IPC_NTCREATEFILE_TAG] = dispatcher; | |
| 34 ipc_targets_[IPC_NTOPENFILE_TAG] = dispatcher; | |
| 35 ipc_targets_[IPC_NTSETINFO_RENAME_TAG] = dispatcher; | |
| 36 ipc_targets_[IPC_NTQUERYATTRIBUTESFILE_TAG] = dispatcher; | |
| 37 ipc_targets_[IPC_NTQUERYFULLATTRIBUTESFILE_TAG] = dispatcher; | |
| 38 filesystem_dispatcher_.reset(dispatcher); | |
| 39 | |
| 40 dispatcher = new NamedPipeDispatcher(policy_); | |
| 41 ipc_targets_[IPC_CREATENAMEDPIPEW_TAG] = dispatcher; | |
| 42 named_pipe_dispatcher_.reset(dispatcher); | |
| 43 | |
| 44 dispatcher = new ThreadProcessDispatcher(policy_); | |
| 45 ipc_targets_[IPC_NTOPENTHREAD_TAG] = dispatcher; | |
| 46 ipc_targets_[IPC_NTOPENPROCESS_TAG] = dispatcher; | |
| 47 ipc_targets_[IPC_CREATEPROCESSW_TAG] = dispatcher; | |
| 48 ipc_targets_[IPC_NTOPENPROCESSTOKEN_TAG] = dispatcher; | |
| 49 ipc_targets_[IPC_NTOPENPROCESSTOKENEX_TAG] = dispatcher; | |
| 50 ipc_targets_[IPC_CREATETHREAD_TAG] = dispatcher; | |
| 51 thread_process_dispatcher_.reset(dispatcher); | |
| 52 | |
| 53 dispatcher = new SyncDispatcher(policy_); | |
| 54 ipc_targets_[IPC_CREATEEVENT_TAG] = dispatcher; | |
| 55 ipc_targets_[IPC_OPENEVENT_TAG] = dispatcher; | |
| 56 sync_dispatcher_.reset(dispatcher); | |
| 57 | |
| 58 dispatcher = new RegistryDispatcher(policy_); | |
| 59 ipc_targets_[IPC_NTCREATEKEY_TAG] = dispatcher; | |
| 60 ipc_targets_[IPC_NTOPENKEY_TAG] = dispatcher; | |
| 61 registry_dispatcher_.reset(dispatcher); | |
| 62 | |
| 63 dispatcher = new HandleDispatcher(policy_); | |
| 64 ipc_targets_[IPC_DUPLICATEHANDLEPROXY_TAG] = dispatcher; | |
| 65 handle_dispatcher_.reset(dispatcher); | |
| 66 | |
| 67 dispatcher = new ProcessMitigationsWin32KDispatcher(policy_); | |
| 68 ipc_targets_[IPC_GDI_GDIDLLINITIALIZE_TAG] = dispatcher; | |
| 69 ipc_targets_[IPC_GDI_GETSTOCKOBJECT_TAG] = dispatcher; | |
| 70 ipc_targets_[IPC_USER_REGISTERCLASSW_TAG] = dispatcher; | |
| 71 process_mitigations_win32k_dispatcher_.reset(dispatcher); | |
| 72 } | |
| 73 | |
| 74 TopLevelDispatcher::~TopLevelDispatcher() {} | |
| 75 | |
| 76 // When an IPC is ready in any of the targets we get called. We manage an array | |
| 77 // of IPC dispatchers which are keyed on the IPC tag so we normally delegate | |
| 78 // to the appropriate dispatcher unless we can handle the IPC call ourselves. | |
| 79 Dispatcher* TopLevelDispatcher::OnMessageReady(IPCParams* ipc, | |
| 80 CallbackGeneric* callback) { | |
| 81 DCHECK(callback); | |
| 82 static const IPCParams ping1 = {IPC_PING1_TAG, {UINT32_TYPE}}; | |
| 83 static const IPCParams ping2 = {IPC_PING2_TAG, {INOUTPTR_TYPE}}; | |
| 84 | |
| 85 if (ping1.Matches(ipc) || ping2.Matches(ipc)) { | |
| 86 *callback = reinterpret_cast<CallbackGeneric>( | |
| 87 static_cast<Callback1>(&TopLevelDispatcher::Ping)); | |
| 88 return this; | |
| 89 } | |
| 90 | |
| 91 Dispatcher* dispatcher = GetDispatcher(ipc->ipc_tag); | |
| 92 if (!dispatcher) { | |
| 93 NOTREACHED(); | |
| 94 return NULL; | |
| 95 } | |
| 96 return dispatcher->OnMessageReady(ipc, callback); | |
| 97 } | |
| 98 | |
| 99 // Delegate to the appropriate dispatcher. | |
| 100 bool TopLevelDispatcher::SetupService(InterceptionManager* manager, | |
| 101 int service) { | |
| 102 if (IPC_PING1_TAG == service || IPC_PING2_TAG == service) | |
| 103 return true; | |
| 104 | |
| 105 Dispatcher* dispatcher = GetDispatcher(service); | |
| 106 if (!dispatcher) { | |
| 107 NOTREACHED(); | |
| 108 return false; | |
| 109 } | |
| 110 return dispatcher->SetupService(manager, service); | |
| 111 } | |
| 112 | |
| 113 // We service IPC_PING_TAG message which is a way to test a round trip of the | |
| 114 // IPC subsystem. We receive a integer cookie and we are expected to return the | |
| 115 // cookie times two (or three) and the current tick count. | |
| 116 bool TopLevelDispatcher::Ping(IPCInfo* ipc, void* arg1) { | |
| 117 switch (ipc->ipc_tag) { | |
| 118 case IPC_PING1_TAG: { | |
| 119 IPCInt ipc_int(arg1); | |
| 120 uint32_t cookie = ipc_int.As32Bit(); | |
| 121 ipc->return_info.extended_count = 2; | |
| 122 ipc->return_info.extended[0].unsigned_int = ::GetTickCount(); | |
| 123 ipc->return_info.extended[1].unsigned_int = 2 * cookie; | |
| 124 return true; | |
| 125 } | |
| 126 case IPC_PING2_TAG: { | |
| 127 CountedBuffer* io_buffer = reinterpret_cast<CountedBuffer*>(arg1); | |
| 128 if (sizeof(uint32_t) != io_buffer->Size()) | |
| 129 return false; | |
| 130 | |
| 131 uint32_t* cookie = reinterpret_cast<uint32_t*>(io_buffer->Buffer()); | |
| 132 *cookie = (*cookie) * 3; | |
| 133 return true; | |
| 134 } | |
| 135 default: | |
| 136 return false; | |
| 137 } | |
| 138 } | |
| 139 | |
| 140 Dispatcher* TopLevelDispatcher::GetDispatcher(int ipc_tag) { | |
| 141 if (ipc_tag >= IPC_LAST_TAG || ipc_tag <= IPC_UNUSED_TAG) | |
| 142 return NULL; | |
| 143 | |
| 144 return ipc_targets_[ipc_tag]; | |
| 145 } | |
| 146 | |
| 147 } // namespace sandbox | |
| OLD | NEW |