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