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