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 #include "base/basictypes.h"
6 #include "sandbox/win/src/crosscall_client.h"
7 #include "sandbox/win/src/crosscall_server.h"
8 #include "sandbox/win/src/sharedmem_ipc_client.h"
9 #include "sandbox/win/src/sharedmem_ipc_server.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11
12 namespace sandbox {
13
14 // Helper function to make the fake shared memory with some
15 // basic elements initialized.
MakeChannels(size_t channel_size,size_t total_shared_size,size_t * base_start)16 IPCControl* MakeChannels(size_t channel_size, size_t total_shared_size,
17 size_t* base_start) {
18 // Allocate memory
19 char* mem = new char[total_shared_size];
20 memset(mem, 0, total_shared_size);
21 // Calculate how many channels we can fit in the shared memory.
22 total_shared_size -= offsetof(IPCControl, channels);
23 size_t channel_count =
24 total_shared_size / (sizeof(ChannelControl) + channel_size);
25 // Calculate the start of the first channel.
26 *base_start = (sizeof(ChannelControl)* channel_count) +
27 offsetof(IPCControl, channels);
28 // Setup client structure.
29 IPCControl* client_control = reinterpret_cast<IPCControl*>(mem);
30 client_control->channels_count = channel_count;
31 return client_control;
32 }
33
34 enum TestFixMode {
35 FIX_NO_EVENTS,
36 FIX_PONG_READY,
37 FIX_PONG_NOT_READY
38 };
39
FixChannels(IPCControl * client_control,size_t base_start,size_t channel_size,TestFixMode mode)40 void FixChannels(IPCControl* client_control, size_t base_start,
41 size_t channel_size, TestFixMode mode) {
42 for (size_t ix = 0; ix != client_control->channels_count; ++ix) {
43 ChannelControl& channel = client_control->channels[ix];
44 channel.channel_base = base_start;
45 channel.state = kFreeChannel;
46 if (mode != FIX_NO_EVENTS) {
47 BOOL signaled = (FIX_PONG_READY == mode)? TRUE : FALSE;
48 channel.ping_event = ::CreateEventW(NULL, FALSE, FALSE, NULL);
49 channel.pong_event = ::CreateEventW(NULL, FALSE, signaled, NULL);
50 }
51 base_start += channel_size;
52 }
53 }
54
CloseChannelEvents(IPCControl * client_control)55 void CloseChannelEvents(IPCControl* client_control) {
56 for (size_t ix = 0; ix != client_control->channels_count; ++ix) {
57 ChannelControl& channel = client_control->channels[ix];
58 ::CloseHandle(channel.ping_event);
59 ::CloseHandle(channel.pong_event);
60 }
61 }
62
TEST(IPCTest,ChannelMaker)63 TEST(IPCTest, ChannelMaker) {
64 // Test that our testing rig is computing offsets properly. We should have
65 // 5 channnels and the offset to the first channel is 108 bytes in 32 bits
66 // and 216 in 64 bits.
67 size_t channel_start = 0;
68 IPCControl* client_control = MakeChannels(12 * 64, 4096, &channel_start);
69 ASSERT_TRUE(NULL != client_control);
70 EXPECT_EQ(5, client_control->channels_count);
71 #if defined(_WIN64)
72 EXPECT_EQ(216, channel_start);
73 #else
74 EXPECT_EQ(108, channel_start);
75 #endif
76 delete[] reinterpret_cast<char*>(client_control);
77 }
78
TEST(IPCTest,ClientLockUnlock)79 TEST(IPCTest, ClientLockUnlock) {
80 // Make 7 channels of kIPCChannelSize (1kb) each. Test that we lock and
81 // unlock channels properly.
82 size_t base_start = 0;
83 IPCControl* client_control =
84 MakeChannels(kIPCChannelSize, 4096 * 2, &base_start);
85 FixChannels(client_control, base_start, kIPCChannelSize, FIX_NO_EVENTS);
86
87 char* mem = reinterpret_cast<char*>(client_control);
88 SharedMemIPCClient client(mem);
89
90 // Test that we lock the first 3 channels in sequence.
91 void* buff0 = client.GetBuffer();
92 EXPECT_TRUE(mem + client_control->channels[0].channel_base == buff0);
93 EXPECT_EQ(kBusyChannel, client_control->channels[0].state);
94 EXPECT_EQ(kFreeChannel, client_control->channels[1].state);
95 EXPECT_EQ(kFreeChannel, client_control->channels[2].state);
96 EXPECT_EQ(kFreeChannel, client_control->channels[3].state);
97 EXPECT_EQ(kFreeChannel, client_control->channels[4].state);
98 EXPECT_EQ(kFreeChannel, client_control->channels[5].state);
99
100 void* buff1 = client.GetBuffer();
101 EXPECT_TRUE(mem + client_control->channels[1].channel_base == buff1);
102 EXPECT_EQ(kBusyChannel, client_control->channels[0].state);
103 EXPECT_EQ(kBusyChannel, client_control->channels[1].state);
104 EXPECT_EQ(kFreeChannel, client_control->channels[2].state);
105 EXPECT_EQ(kFreeChannel, client_control->channels[3].state);
106 EXPECT_EQ(kFreeChannel, client_control->channels[4].state);
107 EXPECT_EQ(kFreeChannel, client_control->channels[5].state);
108
109 void* buff2 = client.GetBuffer();
110 EXPECT_TRUE(mem + client_control->channels[2].channel_base == buff2);
111 EXPECT_EQ(kBusyChannel, client_control->channels[0].state);
112 EXPECT_EQ(kBusyChannel, client_control->channels[1].state);
113 EXPECT_EQ(kBusyChannel, client_control->channels[2].state);
114 EXPECT_EQ(kFreeChannel, client_control->channels[3].state);
115 EXPECT_EQ(kFreeChannel, client_control->channels[4].state);
116 EXPECT_EQ(kFreeChannel, client_control->channels[5].state);
117
118 // Test that we unlock and re-lock the right channel.
119 client.FreeBuffer(buff1);
120 EXPECT_EQ(kBusyChannel, client_control->channels[0].state);
121 EXPECT_EQ(kFreeChannel, client_control->channels[1].state);
122 EXPECT_EQ(kBusyChannel, client_control->channels[2].state);
123 EXPECT_EQ(kFreeChannel, client_control->channels[3].state);
124 EXPECT_EQ(kFreeChannel, client_control->channels[4].state);
125 EXPECT_EQ(kFreeChannel, client_control->channels[5].state);
126
127 void* buff2b = client.GetBuffer();
128 EXPECT_TRUE(mem + client_control->channels[1].channel_base == buff2b);
129 EXPECT_EQ(kBusyChannel, client_control->channels[0].state);
130 EXPECT_EQ(kBusyChannel, client_control->channels[1].state);
131 EXPECT_EQ(kBusyChannel, client_control->channels[2].state);
132 EXPECT_EQ(kFreeChannel, client_control->channels[3].state);
133 EXPECT_EQ(kFreeChannel, client_control->channels[4].state);
134 EXPECT_EQ(kFreeChannel, client_control->channels[5].state);
135
136 client.FreeBuffer(buff0);
137 EXPECT_EQ(kFreeChannel, client_control->channels[0].state);
138 EXPECT_EQ(kBusyChannel, client_control->channels[1].state);
139 EXPECT_EQ(kBusyChannel, client_control->channels[2].state);
140 EXPECT_EQ(kFreeChannel, client_control->channels[3].state);
141 EXPECT_EQ(kFreeChannel, client_control->channels[4].state);
142 EXPECT_EQ(kFreeChannel, client_control->channels[5].state);
143
144 delete[] reinterpret_cast<char*>(client_control);
145 }
146
TEST(IPCTest,CrossCallStrPacking)147 TEST(IPCTest, CrossCallStrPacking) {
148 // This test tries the CrossCall object with null and non-null string
149 // combination of parameters, integer types and verifies that the unpacker
150 // can read them properly.
151 size_t base_start = 0;
152 IPCControl* client_control =
153 MakeChannels(kIPCChannelSize, 4096 * 4, &base_start);
154 client_control->server_alive = HANDLE(1);
155 FixChannels(client_control, base_start, kIPCChannelSize, FIX_PONG_READY);
156
157 char* mem = reinterpret_cast<char*>(client_control);
158 SharedMemIPCClient client(mem);
159
160 CrossCallReturn answer;
161 uint32 tag1 = 666;
162 const wchar_t *text = L"98765 - 43210";
163 base::string16 copied_text;
164 CrossCallParamsEx* actual_params;
165
166 CrossCall(client, tag1, text, &answer);
167 actual_params = reinterpret_cast<CrossCallParamsEx*>(client.GetBuffer());
168 EXPECT_EQ(1, actual_params->GetParamsCount());
169 EXPECT_EQ(tag1, actual_params->GetTag());
170 EXPECT_TRUE(actual_params->GetParameterStr(0, &copied_text));
171 EXPECT_STREQ(text, copied_text.c_str());
172
173 // Check with an empty string.
174 uint32 tag2 = 777;
175 const wchar_t* null_text = NULL;
176 CrossCall(client, tag2, null_text, &answer);
177 actual_params = reinterpret_cast<CrossCallParamsEx*>(client.GetBuffer());
178 EXPECT_EQ(1, actual_params->GetParamsCount());
179 EXPECT_EQ(tag2, actual_params->GetTag());
180 uint32 param_size = 1;
181 ArgType type = INVALID_TYPE;
182 void* param_addr = actual_params->GetRawParameter(0, ¶m_size, &type);
183 EXPECT_TRUE(NULL != param_addr);
184 EXPECT_EQ(0, param_size);
185 EXPECT_EQ(WCHAR_TYPE, type);
186 EXPECT_TRUE(actual_params->GetParameterStr(0, &copied_text));
187
188 uint32 tag3 = 888;
189 param_size = 1;
190 copied_text.clear();
191
192 // Check with an empty string and a non-empty string.
193 CrossCall(client, tag3, null_text, text, &answer);
194 actual_params = reinterpret_cast<CrossCallParamsEx*>(client.GetBuffer());
195 EXPECT_EQ(2, actual_params->GetParamsCount());
196 EXPECT_EQ(tag3, actual_params->GetTag());
197 type = INVALID_TYPE;
198 param_addr = actual_params->GetRawParameter(0, ¶m_size, &type);
199 EXPECT_TRUE(NULL != param_addr);
200 EXPECT_EQ(0, param_size);
201 EXPECT_EQ(WCHAR_TYPE, type);
202 EXPECT_TRUE(actual_params->GetParameterStr(0, &copied_text));
203 EXPECT_TRUE(actual_params->GetParameterStr(1, &copied_text));
204 EXPECT_STREQ(text, copied_text.c_str());
205
206 param_size = 1;
207 base::string16 copied_text_p0, copied_text_p2;
208
209 const wchar_t *text2 = L"AeFG";
210 CrossCall(client, tag1, text2, null_text, text, &answer);
211 actual_params = reinterpret_cast<CrossCallParamsEx*>(client.GetBuffer());
212 EXPECT_EQ(3, actual_params->GetParamsCount());
213 EXPECT_EQ(tag1, actual_params->GetTag());
214 EXPECT_TRUE(actual_params->GetParameterStr(0, &copied_text_p0));
215 EXPECT_STREQ(text2, copied_text_p0.c_str());
216 EXPECT_TRUE(actual_params->GetParameterStr(2, &copied_text_p2));
217 EXPECT_STREQ(text, copied_text_p2.c_str());
218 type = INVALID_TYPE;
219 param_addr = actual_params->GetRawParameter(1, ¶m_size, &type);
220 EXPECT_TRUE(NULL != param_addr);
221 EXPECT_EQ(0, param_size);
222 EXPECT_EQ(WCHAR_TYPE, type);
223
224 CloseChannelEvents(client_control);
225 delete[] reinterpret_cast<char*>(client_control);
226 }
227
TEST(IPCTest,CrossCallIntPacking)228 TEST(IPCTest, CrossCallIntPacking) {
229 // Check handling for regular 32 bit integers used in Windows.
230 size_t base_start = 0;
231 IPCControl* client_control =
232 MakeChannels(kIPCChannelSize, 4096 * 4, &base_start);
233 client_control->server_alive = HANDLE(1);
234 FixChannels(client_control, base_start, kIPCChannelSize, FIX_PONG_READY);
235
236 uint32 tag1 = 999;
237 uint32 tag2 = 111;
238 const wchar_t *text = L"godzilla";
239 CrossCallParamsEx* actual_params;
240
241 char* mem = reinterpret_cast<char*>(client_control);
242 SharedMemIPCClient client(mem);
243
244 CrossCallReturn answer;
245 DWORD dw = 0xE6578;
246 CrossCall(client, tag2, dw, &answer);
247 actual_params = reinterpret_cast<CrossCallParamsEx*>(client.GetBuffer());
248 EXPECT_EQ(1, actual_params->GetParamsCount());
249 EXPECT_EQ(tag2, actual_params->GetTag());
250 ArgType type = INVALID_TYPE;
251 uint32 param_size = 1;
252 void* param_addr = actual_params->GetRawParameter(0, ¶m_size, &type);
253 ASSERT_EQ(sizeof(dw), param_size);
254 EXPECT_EQ(ULONG_TYPE, type);
255 ASSERT_TRUE(NULL != param_addr);
256 EXPECT_EQ(0, memcmp(&dw, param_addr, param_size));
257
258 // Check handling for windows HANDLES.
259 HANDLE h = HANDLE(0x70000500);
260 CrossCall(client, tag1, text, h, &answer);
261 actual_params = reinterpret_cast<CrossCallParamsEx*>(client.GetBuffer());
262 EXPECT_EQ(2, actual_params->GetParamsCount());
263 EXPECT_EQ(tag1, actual_params->GetTag());
264 type = INVALID_TYPE;
265 param_addr = actual_params->GetRawParameter(1, ¶m_size, &type);
266 ASSERT_EQ(sizeof(h), param_size);
267 EXPECT_EQ(VOIDPTR_TYPE, type);
268 ASSERT_TRUE(NULL != param_addr);
269 EXPECT_EQ(0, memcmp(&h, param_addr, param_size));
270
271 // Check combination of 32 and 64 bits.
272 CrossCall(client, tag2, h, dw, h, &answer);
273 actual_params = reinterpret_cast<CrossCallParamsEx*>(client.GetBuffer());
274 EXPECT_EQ(3, actual_params->GetParamsCount());
275 EXPECT_EQ(tag2, actual_params->GetTag());
276 type = INVALID_TYPE;
277 param_addr = actual_params->GetRawParameter(0, ¶m_size, &type);
278 ASSERT_EQ(sizeof(h), param_size);
279 EXPECT_EQ(VOIDPTR_TYPE, type);
280 ASSERT_TRUE(NULL != param_addr);
281 EXPECT_EQ(0, memcmp(&h, param_addr, param_size));
282 type = INVALID_TYPE;
283 param_addr = actual_params->GetRawParameter(1, ¶m_size, &type);
284 ASSERT_EQ(sizeof(dw), param_size);
285 EXPECT_EQ(ULONG_TYPE, type);
286 ASSERT_TRUE(NULL != param_addr);
287 EXPECT_EQ(0, memcmp(&dw, param_addr, param_size));
288 type = INVALID_TYPE;
289 param_addr = actual_params->GetRawParameter(2, ¶m_size, &type);
290 ASSERT_EQ(sizeof(h), param_size);
291 EXPECT_EQ(VOIDPTR_TYPE, type);
292 ASSERT_TRUE(NULL != param_addr);
293 EXPECT_EQ(0, memcmp(&h, param_addr, param_size));
294
295 CloseChannelEvents(client_control);
296 delete[] reinterpret_cast<char*>(client_control);
297 }
298
TEST(IPCTest,CrossCallValidation)299 TEST(IPCTest, CrossCallValidation) {
300 // First a sanity test with a well formed parameter object.
301 unsigned long value = 124816;
302 const uint32 kTag = 33;
303 const uint32 kBufferSize = 256;
304 ActualCallParams<1, kBufferSize> params_1(kTag);
305 params_1.CopyParamIn(0, &value, sizeof(value), false, ULONG_TYPE);
306 void* buffer = const_cast<void*>(params_1.GetBuffer());
307
308 uint32 out_size = 0;
309 CrossCallParamsEx* ccp = 0;
310 ccp = CrossCallParamsEx::CreateFromBuffer(buffer, params_1.GetSize(),
311 &out_size);
312 ASSERT_TRUE(NULL != ccp);
313 EXPECT_TRUE(ccp->GetBuffer() != buffer);
314 EXPECT_EQ(kTag, ccp->GetTag());
315 EXPECT_EQ(1, ccp->GetParamsCount());
316 delete[] (reinterpret_cast<char*>(ccp));
317
318 // Test that we handle integer overflow on the number of params
319 // correctly. We use a test-only ctor for ActualCallParams that
320 // allows to create malformed cross-call buffers.
321 const int32 kPtrDiffSz = sizeof(ptrdiff_t);
322 for (int32 ix = -1; ix != 3; ++ix) {
323 uint32 fake_num_params = (kuint32max / kPtrDiffSz) + ix;
324 ActualCallParams<1, kBufferSize> params_2(kTag, fake_num_params);
325 params_2.CopyParamIn(0, &value, sizeof(value), false, ULONG_TYPE);
326 buffer = const_cast<void*>(params_2.GetBuffer());
327
328 EXPECT_TRUE(NULL != buffer);
329 ccp = CrossCallParamsEx::CreateFromBuffer(buffer, params_1.GetSize(),
330 &out_size);
331 // If the buffer is malformed the return is NULL.
332 EXPECT_TRUE(NULL == ccp);
333 }
334
335 ActualCallParams<1, kBufferSize> params_3(kTag, 1);
336 params_3.CopyParamIn(0, &value, sizeof(value), false, ULONG_TYPE);
337 buffer = const_cast<void*>(params_3.GetBuffer());
338 EXPECT_TRUE(NULL != buffer);
339
340 uint32 correct_size = params_3.OverrideSize(1);
341 ccp = CrossCallParamsEx::CreateFromBuffer(buffer, kBufferSize, &out_size);
342 EXPECT_TRUE(NULL == ccp);
343
344 // The correct_size is 8 bytes aligned.
345 params_3.OverrideSize(correct_size - 7);
346 ccp = CrossCallParamsEx::CreateFromBuffer(buffer, kBufferSize, &out_size);
347 EXPECT_TRUE(NULL == ccp);
348
349 params_3.OverrideSize(correct_size);
350 ccp = CrossCallParamsEx::CreateFromBuffer(buffer, kBufferSize, &out_size);
351 EXPECT_TRUE(NULL != ccp);
352
353 // Make sure that two parameters work as expected.
354 ActualCallParams<2, kBufferSize> params_4(kTag, 2);
355 params_4.CopyParamIn(0, &value, sizeof(value), false, ULONG_TYPE);
356 params_4.CopyParamIn(1, buffer, sizeof(buffer), false, VOIDPTR_TYPE);
357 buffer = const_cast<void*>(params_4.GetBuffer());
358 EXPECT_TRUE(NULL != buffer);
359
360 ccp = CrossCallParamsEx::CreateFromBuffer(buffer, kBufferSize, &out_size);
361 EXPECT_TRUE(NULL != ccp);
362
363 #if defined(_WIN64)
364 correct_size = params_4.OverrideSize(1);
365 params_4.OverrideSize(correct_size - 1);
366 ccp = CrossCallParamsEx::CreateFromBuffer(buffer, kBufferSize, &out_size);
367 EXPECT_TRUE(NULL == ccp);
368 #endif
369 }
370
371 // This structure is passed to the mock server threads to simulate
372 // the server side IPC so it has the required kernel objects.
373 struct ServerEvents {
374 HANDLE ping;
375 HANDLE pong;
376 volatile LONG* state;
377 HANDLE mutex;
378 };
379
380 // This is the server thread that quicky answers an IPC and exits.
QuickResponseServer(PVOID param)381 DWORD WINAPI QuickResponseServer(PVOID param) {
382 ServerEvents* events = reinterpret_cast<ServerEvents*>(param);
383 DWORD wait_result = 0;
384 wait_result = ::WaitForSingleObject(events->ping, INFINITE);
385 ::InterlockedExchange(events->state, kAckChannel);
386 ::SetEvent(events->pong);
387 return wait_result;
388 }
389
390 class CrossCallParamsMock : public CrossCallParams {
391 public:
CrossCallParamsMock(uint32 tag,uint32 params_count)392 CrossCallParamsMock(uint32 tag, uint32 params_count)
393 : CrossCallParams(tag, params_count) {
394 }
395 private:
396 void* params[4];
397 };
398
FakeOkAnswerInChannel(void * channel)399 void FakeOkAnswerInChannel(void* channel) {
400 CrossCallReturn* answer = reinterpret_cast<CrossCallReturn*>(channel);
401 answer->call_outcome = SBOX_ALL_OK;
402 }
403
404 // Create two threads that will quickly answer IPCs; the first one
405 // using channel 1 (channel 0 is busy) and one using channel 0. No time-out
406 // should occur.
TEST(IPCTest,ClientFastServer)407 TEST(IPCTest, ClientFastServer) {
408 const size_t channel_size = kIPCChannelSize;
409 size_t base_start = 0;
410 IPCControl* client_control =
411 MakeChannels(channel_size, 4096 * 2, &base_start);
412 FixChannels(client_control, base_start, kIPCChannelSize, FIX_PONG_NOT_READY);
413 client_control->server_alive = ::CreateMutex(NULL, FALSE, NULL);
414
415 char* mem = reinterpret_cast<char*>(client_control);
416 SharedMemIPCClient client(mem);
417
418 ServerEvents events = {0};
419 events.ping = client_control->channels[1].ping_event;
420 events.pong = client_control->channels[1].pong_event;
421 events.state = &client_control->channels[1].state;
422
423 HANDLE t1 = ::CreateThread(NULL, 0, QuickResponseServer, &events, 0, NULL);
424 ASSERT_TRUE(NULL != t1);
425 ::CloseHandle(t1);
426
427 void* buff0 = client.GetBuffer();
428 EXPECT_TRUE(mem + client_control->channels[0].channel_base == buff0);
429 EXPECT_EQ(kBusyChannel, client_control->channels[0].state);
430 EXPECT_EQ(kFreeChannel, client_control->channels[1].state);
431 EXPECT_EQ(kFreeChannel, client_control->channels[2].state);
432
433 void* buff1 = client.GetBuffer();
434 EXPECT_TRUE(mem + client_control->channels[1].channel_base == buff1);
435 EXPECT_EQ(kBusyChannel, client_control->channels[0].state);
436 EXPECT_EQ(kBusyChannel, client_control->channels[1].state);
437 EXPECT_EQ(kFreeChannel, client_control->channels[2].state);
438
439 EXPECT_EQ(0, client_control->channels[1].ipc_tag);
440
441 uint32 tag = 7654;
442 CrossCallReturn answer;
443 CrossCallParamsMock* params1 = new(buff1) CrossCallParamsMock(tag, 1);
444 FakeOkAnswerInChannel(buff1);
445
446 ResultCode result = client.DoCall(params1, &answer);
447 if (SBOX_ERROR_CHANNEL_ERROR != result)
448 client.FreeBuffer(buff1);
449
450 EXPECT_TRUE(SBOX_ALL_OK == result);
451 EXPECT_EQ(tag, client_control->channels[1].ipc_tag);
452 EXPECT_EQ(kBusyChannel, client_control->channels[0].state);
453 EXPECT_EQ(kFreeChannel, client_control->channels[1].state);
454 EXPECT_EQ(kFreeChannel, client_control->channels[2].state);
455
456 HANDLE t2 = ::CreateThread(NULL, 0, QuickResponseServer, &events, 0, NULL);
457 ASSERT_TRUE(NULL != t2);
458 ::CloseHandle(t2);
459
460 client.FreeBuffer(buff0);
461 events.ping = client_control->channels[0].ping_event;
462 events.pong = client_control->channels[0].pong_event;
463 events.state = &client_control->channels[0].state;
464
465 tag = 4567;
466 CrossCallParamsMock* params2 = new(buff0) CrossCallParamsMock(tag, 1);
467 FakeOkAnswerInChannel(buff0);
468
469 result = client.DoCall(params2, &answer);
470 if (SBOX_ERROR_CHANNEL_ERROR != result)
471 client.FreeBuffer(buff0);
472
473 EXPECT_TRUE(SBOX_ALL_OK == result);
474 EXPECT_EQ(tag, client_control->channels[0].ipc_tag);
475 EXPECT_EQ(kFreeChannel, client_control->channels[0].state);
476 EXPECT_EQ(kFreeChannel, client_control->channels[1].state);
477 EXPECT_EQ(kFreeChannel, client_control->channels[2].state);
478
479 CloseChannelEvents(client_control);
480 ::CloseHandle(client_control->server_alive);
481
482 delete[] reinterpret_cast<char*>(client_control);
483 }
484
485 // This is the server thread that very slowly answers an IPC and exits. Note
486 // that the pong event needs to be signaled twice.
SlowResponseServer(PVOID param)487 DWORD WINAPI SlowResponseServer(PVOID param) {
488 ServerEvents* events = reinterpret_cast<ServerEvents*>(param);
489 DWORD wait_result = 0;
490 wait_result = ::WaitForSingleObject(events->ping, INFINITE);
491 ::Sleep(kIPCWaitTimeOut1 + kIPCWaitTimeOut2 + 200);
492 ::InterlockedExchange(events->state, kAckChannel);
493 ::SetEvent(events->pong);
494 return wait_result;
495 }
496
497 // This thread's job is to keep the mutex locked.
MainServerThread(PVOID param)498 DWORD WINAPI MainServerThread(PVOID param) {
499 ServerEvents* events = reinterpret_cast<ServerEvents*>(param);
500 DWORD wait_result = 0;
501 wait_result = ::WaitForSingleObject(events->mutex, INFINITE);
502 Sleep(kIPCWaitTimeOut1 * 20);
503 return wait_result;
504 }
505
506 // Creates a server thread that answers the IPC so slow that is guaranteed to
507 // trigger the time-out code path in the client. A second thread is created
508 // to hold locked the server_alive mutex: this signals the client that the
509 // server is not dead and it retries the wait.
TEST(IPCTest,ClientSlowServer)510 TEST(IPCTest, ClientSlowServer) {
511 size_t base_start = 0;
512 IPCControl* client_control =
513 MakeChannels(kIPCChannelSize, 4096*2, &base_start);
514 FixChannels(client_control, base_start, kIPCChannelSize, FIX_PONG_NOT_READY);
515 client_control->server_alive = ::CreateMutex(NULL, FALSE, NULL);
516
517 char* mem = reinterpret_cast<char*>(client_control);
518 SharedMemIPCClient client(mem);
519
520 ServerEvents events = {0};
521 events.ping = client_control->channels[0].ping_event;
522 events.pong = client_control->channels[0].pong_event;
523 events.state = &client_control->channels[0].state;
524
525 HANDLE t1 = ::CreateThread(NULL, 0, SlowResponseServer, &events, 0, NULL);
526 ASSERT_TRUE(NULL != t1);
527 ::CloseHandle(t1);
528
529 ServerEvents events2 = {0};
530 events2.pong = events.pong;
531 events2.mutex = client_control->server_alive;
532
533 HANDLE t2 = ::CreateThread(NULL, 0, MainServerThread, &events2, 0, NULL);
534 ASSERT_TRUE(NULL != t2);
535 ::CloseHandle(t2);
536
537 ::Sleep(1);
538
539 void* buff0 = client.GetBuffer();
540 uint32 tag = 4321;
541 CrossCallReturn answer;
542 CrossCallParamsMock* params1 = new(buff0) CrossCallParamsMock(tag, 1);
543 FakeOkAnswerInChannel(buff0);
544
545 ResultCode result = client.DoCall(params1, &answer);
546 if (SBOX_ERROR_CHANNEL_ERROR != result)
547 client.FreeBuffer(buff0);
548
549 EXPECT_TRUE(SBOX_ALL_OK == result);
550 EXPECT_EQ(tag, client_control->channels[0].ipc_tag);
551 EXPECT_EQ(kFreeChannel, client_control->channels[0].state);
552
553 CloseChannelEvents(client_control);
554 ::CloseHandle(client_control->server_alive);
555 delete[] reinterpret_cast<char*>(client_control);
556 }
557
558 // This test-only IPC dispatcher has two handlers with the same signature
559 // but only CallOneHandler should be used.
560 class UnitTestIPCDispatcher : public Dispatcher {
561 public:
562 enum {
563 CALL_ONE_TAG = 78,
564 CALL_TWO_TAG = 87
565 };
566
567 UnitTestIPCDispatcher();
~UnitTestIPCDispatcher()568 ~UnitTestIPCDispatcher() {};
569
SetupService(InterceptionManager * manager,int service)570 virtual bool SetupService(InterceptionManager* manager, int service) {
571 return true;
572 }
573
574 private:
CallOneHandler(IPCInfo * ipc,HANDLE p1,DWORD p2)575 bool CallOneHandler(IPCInfo* ipc, HANDLE p1, DWORD p2) {
576 ipc->return_info.extended[0].handle = p1;
577 ipc->return_info.extended[1].unsigned_int = p2;
578 return true;
579 }
580
CallTwoHandler(IPCInfo * ipc,HANDLE p1,DWORD p2)581 bool CallTwoHandler(IPCInfo* ipc, HANDLE p1, DWORD p2) {
582 return true;
583 }
584 };
585
UnitTestIPCDispatcher()586 UnitTestIPCDispatcher::UnitTestIPCDispatcher() {
587 static const IPCCall call_one = {
588 {CALL_ONE_TAG, VOIDPTR_TYPE, ULONG_TYPE},
589 reinterpret_cast<CallbackGeneric>(
590 &UnitTestIPCDispatcher::CallOneHandler)
591 };
592 static const IPCCall call_two = {
593 {CALL_TWO_TAG, VOIDPTR_TYPE, ULONG_TYPE},
594 reinterpret_cast<CallbackGeneric>(
595 &UnitTestIPCDispatcher::CallTwoHandler)
596 };
597 ipc_calls_.push_back(call_one);
598 ipc_calls_.push_back(call_two);
599 }
600
601 // This test does most of the shared memory IPC client-server roundtrip
602 // and tests the packing, unpacking and call dispatching.
TEST(IPCTest,SharedMemServerTests)603 TEST(IPCTest, SharedMemServerTests) {
604 size_t base_start = 0;
605 IPCControl* client_control =
606 MakeChannels(kIPCChannelSize, 4096, &base_start);
607 client_control->server_alive = HANDLE(1);
608 FixChannels(client_control, base_start, kIPCChannelSize, FIX_PONG_READY);
609
610 char* mem = reinterpret_cast<char*>(client_control);
611 SharedMemIPCClient client(mem);
612
613 CrossCallReturn answer;
614 HANDLE bar = HANDLE(191919);
615 DWORD foo = 6767676;
616 CrossCall(client, UnitTestIPCDispatcher::CALL_ONE_TAG, bar, foo, &answer);
617 void* buff = client.GetBuffer();
618 ASSERT_TRUE(NULL != buff);
619
620 UnitTestIPCDispatcher dispatcher;
621 // Since we are directly calling InvokeCallback, most of this structure
622 // can be set to NULL.
623 sandbox::SharedMemIPCServer::ServerControl srv_control = {
624 NULL, NULL, kIPCChannelSize, NULL,
625 reinterpret_cast<char*>(client_control),
626 NULL, &dispatcher, {0} };
627
628 sandbox::CrossCallReturn call_return = {0};
629 EXPECT_TRUE(SharedMemIPCServer::InvokeCallback(&srv_control, buff,
630 &call_return));
631 EXPECT_EQ(SBOX_ALL_OK, call_return.call_outcome);
632 EXPECT_TRUE(bar == call_return.extended[0].handle);
633 EXPECT_EQ(foo, call_return.extended[1].unsigned_int);
634
635 CloseChannelEvents(client_control);
636 delete[] reinterpret_cast<char*>(client_control);
637 }
638
639 } // namespace sandbox
640