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 |