1 // Copyright (c) 2012 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 #ifndef SANDBOX_SRC_CROSSCALL_SERVER_H_ 6 #define SANDBOX_SRC_CROSSCALL_SERVER_H_ 7 8 #include <string> 9 #include <vector> 10 #include "base/basictypes.h" 11 #include "base/callback.h" 12 #include "sandbox/win/src/crosscall_params.h" 13 14 // This is the IPC server interface for CrossCall: The IPC for the Sandbox 15 // On the server, CrossCall needs two things: 16 // 1) threads: Or better said, someone to provide them, that is what the 17 // ThreadProvider interface is defined for. These thread(s) are 18 // the ones that will actually execute the IPC data retrieval. 19 // 20 // 2) a dispatcher: This interface represents the way to route and process 21 // an IPC call given the IPC tag. 22 // 23 // The other class included here CrossCallParamsEx is the server side version 24 // of the CrossCallParams class of /sandbox/crosscall_params.h The difference 25 // is that the sever version is paranoid about the correctness of the IPC 26 // message and will do all sorts of verifications. 27 // 28 // A general diagram of the interaction is as follows: 29 // 30 // ------------ 31 // | | 32 // ThreadProvider <--(1)Register--| IPC | 33 // | | Implemen | 34 // | | -tation | 35 // (2) | | OnMessage 36 // IPC fired --callback ------>| |--(3)---> Dispatcher 37 // | | 38 // ------------ 39 // 40 // The IPC implementation sits as a middleman between the handling of the 41 // specifics of scheduling a thread to service the IPC and the multiple 42 // entities that can potentially serve each particular IPC. 43 namespace sandbox { 44 45 class InterceptionManager; 46 47 // This function signature is required as the callback when an IPC call fires. 48 // context: a user-defined pointer that was set using ThreadProvider 49 // reason: 0 if the callback was fired because of a timeout. 50 // 1 if the callback was fired because of an event. 51 typedef void (__stdcall * CrossCallIPCCallback)(void* context, 52 unsigned char reason); 53 54 // ThreadProvider models a thread factory. The idea is to decouple thread 55 // creation and lifetime from the inner guts of the IPC. The contract is 56 // simple: 57 // - the IPC implementation calls RegisterWait with a waitable object that 58 // becomes signaled when an IPC arrives and needs to be serviced. 59 // - when the waitable object becomes signaled, the thread provider conjures 60 // a thread that calls the callback (CrossCallIPCCallback) function 61 // - the callback function tries its best not to block and return quickly 62 // and should not assume that the next callback will use the same thread 63 // - when the callback returns the ThreadProvider owns again the thread 64 // and can destroy it or keep it around. 65 class ThreadProvider { 66 public: 67 // Registers a waitable object with the thread provider. 68 // client: A number to associate with all the RegisterWait calls, typically 69 // this is the address of the caller object. This parameter cannot 70 // be zero. 71 // waitable_object : a kernel object that can be waited on 72 // callback: a function pointer which is the function that will be called 73 // when the waitable object fires 74 // context: a user-provider pointer that is passed back to the callback 75 // when its called 76 virtual bool RegisterWait(const void* client, HANDLE waitable_object, 77 CrossCallIPCCallback callback, 78 void* context) = 0; 79 80 // Removes all the registrations done with the same cookie parameter. 81 // This frees internal thread pool resources. 82 virtual bool UnRegisterWaits(void* cookie) = 0; 83 virtual ~ThreadProvider() {} 84 }; 85 86 // Models the server-side of the original input parameters. 87 // Provides IPC buffer validation and it is capable of reading the parameters 88 // out of the IPC buffer. 89 class CrossCallParamsEx : public CrossCallParams { 90 public: 91 // Factory constructor. Pass an IPCbuffer (and buffer size) that contains a 92 // pending IPCcall. This constructor will: 93 // 1) validate the IPC buffer. returns NULL is the IPCbuffer is malformed. 94 // 2) make a copy of the IPCbuffer (parameter capture) 95 static CrossCallParamsEx* CreateFromBuffer(void* buffer_base, 96 uint32 buffer_size, 97 uint32* output_size); 98 99 // Provides IPCinput parameter raw access: 100 // index : the parameter to read; 0 is the first parameter 101 // returns NULL if the parameter is non-existent. If it exists it also 102 // returns the size in *size 103 void* GetRawParameter(uint32 index, uint32* size, ArgType* type); 104 105 // Gets a parameter that is four bytes in size. 106 // Returns false if the parameter does not exist or is not 32 bits wide. 107 bool GetParameter32(uint32 index, uint32* param); 108 109 // Gets a parameter that is void pointer in size. 110 // Returns false if the parameter does not exist or is not void pointer sized. 111 bool GetParameterVoidPtr(uint32 index, void** param); 112 113 // Gets a parameter that is a string. Returns false if the parameter does not 114 // exist. 115 bool GetParameterStr(uint32 index, std::wstring* string); 116 117 // Gets a parameter that is an in/out buffer. Returns false is the parameter 118 // does not exist or if the size of the actual parameter is not equal to the 119 // expected size. 120 bool GetParameterPtr(uint32 index, uint32 expected_size, void** pointer); 121 122 // Frees the memory associated with the IPC parameters. 123 static void operator delete(void* raw_memory) throw(); 124 125 private: 126 // Only the factory method CreateFromBuffer can construct these objects. 127 CrossCallParamsEx(); 128 129 ParamInfo param_info_[1]; 130 DISALLOW_COPY_AND_ASSIGN(CrossCallParamsEx); 131 }; 132 133 // Simple helper function that sets the members of CrossCallReturn 134 // to the proper state to signal a basic error. 135 void SetCallError(ResultCode error, CrossCallReturn* call_return); 136 137 // Sets the internal status of call_return to signify the that IPC call 138 // completed successfully. 139 void SetCallSuccess(CrossCallReturn* call_return); 140 141 // Represents the client process that initiated the IPC which boils down to the 142 // process handle and the job object handle that contains the client process. 143 struct ClientInfo { 144 HANDLE process; 145 HANDLE job_object; 146 DWORD process_id; 147 }; 148 149 // All IPC-related information to be passed to the IPC handler. 150 struct IPCInfo { 151 int ipc_tag; 152 const ClientInfo* client_info; 153 CrossCallReturn return_info; 154 }; 155 156 // This structure identifies IPC signatures. 157 struct IPCParams { 158 int ipc_tag; 159 ArgType args[kMaxIpcParams]; 160 161 bool Matches(IPCParams* other) const { 162 return !memcmp(this, other, sizeof(*other)); 163 } 164 }; 165 166 // Models an entity that can process an IPC message or it can route to another 167 // one that could handle it. When an IPC arrives the IPC implementation will: 168 // 1) call OnMessageReady() with the tag of the pending IPC. If the dispatcher 169 // returns NULL it means that it cannot handle this IPC but if it returns 170 // non-null, it must be the pointer to a dispatcher that can handle it. 171 // 2) When the IPC finally obtains a valid Dispatcher the IPC 172 // implementation creates a CrossCallParamsEx from the raw IPC buffer. 173 // 3) It calls the returned callback, with the IPC info and arguments. 174 class Dispatcher { 175 public: 176 // Called from the IPC implementation to handle a specific IPC message. 177 typedef bool (Dispatcher::*CallbackGeneric)(); 178 typedef bool (Dispatcher::*Callback0)(IPCInfo* ipc); 179 typedef bool (Dispatcher::*Callback1)(IPCInfo* ipc, void* p1); 180 typedef bool (Dispatcher::*Callback2)(IPCInfo* ipc, void* p1, void* p2); 181 typedef bool (Dispatcher::*Callback3)(IPCInfo* ipc, void* p1, void* p2, 182 void* p3); 183 typedef bool (Dispatcher::*Callback4)(IPCInfo* ipc, void* p1, void* p2, 184 void* p3, void* p4); 185 typedef bool (Dispatcher::*Callback5)(IPCInfo* ipc, void* p1, void* p2, 186 void* p3, void* p4, void* p5); 187 typedef bool (Dispatcher::*Callback6)(IPCInfo* ipc, void* p1, void* p2, 188 void* p3, void* p4, void* p5, void* p6); 189 typedef bool (Dispatcher::*Callback7)(IPCInfo* ipc, void* p1, void* p2, 190 void* p3, void* p4, void* p5, void* p6, 191 void* p7); 192 typedef bool (Dispatcher::*Callback8)(IPCInfo* ipc, void* p1, void* p2, 193 void* p3, void* p4, void* p5, void* p6, 194 void* p7, void* p8); 195 typedef bool (Dispatcher::*Callback9)(IPCInfo* ipc, void* p1, void* p2, 196 void* p3, void* p4, void* p5, void* p6, 197 void* p7, void* p8, void* p9); 198 199 // Called from the IPC implementation when an IPC message is ready override 200 // on a derived class to handle a set of IPC messages. Return NULL if your 201 // subclass does not handle the message or return the pointer to the subclass 202 // that can handle it. 203 virtual Dispatcher* OnMessageReady(IPCParams* ipc, CallbackGeneric* callback); 204 205 // Called when a target proces is created, to setup the interceptions related 206 // with the given service (IPC). 207 virtual bool SetupService(InterceptionManager* manager, int service) = 0; 208 209 virtual ~Dispatcher() {} 210 211 protected: 212 // Structure that defines an IPC Call with all the parameters and the handler. 213 struct IPCCall { 214 IPCParams params; 215 CallbackGeneric callback; 216 }; 217 218 // List of IPC Calls supported by the class. 219 std::vector<IPCCall> ipc_calls_; 220 }; 221 222 } // namespace sandbox 223 224 #endif // SANDBOX_SRC_CROSSCALL_SERVER_H_ 225