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