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