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