• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &param_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, &param_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, &param_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, &param_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, &param_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, &param_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, &param_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, &param_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 #if defined(NDEBUG)
319   // Test hat we handle integer overflow on the number of params
320   // correctly. We use a test-only ctor for ActualCallParams that
321   // allows to create malformed cross-call buffers.
322   const int32 kPtrDiffSz = sizeof(ptrdiff_t);
323   for (int32 ix = -1; ix != 3; ++ix) {
324     uint32 fake_num_params = (kuint32max / kPtrDiffSz) + ix;
325     ActualCallParams<1, kBufferSize> params_2(kTag, fake_num_params);
326     params_2.CopyParamIn(0, &value, sizeof(value), false, ULONG_TYPE);
327     buffer = const_cast<void*>(params_2.GetBuffer());
328 
329     EXPECT_TRUE(NULL != buffer);
330     ccp = CrossCallParamsEx::CreateFromBuffer(buffer, params_1.GetSize(),
331                                               &out_size);
332     // If the buffer is malformed the return is NULL.
333     EXPECT_TRUE(NULL == ccp);
334   }
335 #endif  // defined(NDEBUG)
336 
337   ActualCallParams<1, kBufferSize> params_3(kTag, 1);
338   params_3.CopyParamIn(0, &value, sizeof(value), false, ULONG_TYPE);
339   buffer = const_cast<void*>(params_3.GetBuffer());
340   EXPECT_TRUE(NULL != buffer);
341 
342   uint32 correct_size = params_3.OverrideSize(1);
343   ccp = CrossCallParamsEx::CreateFromBuffer(buffer, kBufferSize, &out_size);
344   EXPECT_TRUE(NULL == ccp);
345 
346   // The correct_size is 8 bytes aligned.
347   params_3.OverrideSize(correct_size - 7);
348   ccp = CrossCallParamsEx::CreateFromBuffer(buffer, kBufferSize, &out_size);
349   EXPECT_TRUE(NULL == ccp);
350 
351   params_3.OverrideSize(correct_size);
352   ccp = CrossCallParamsEx::CreateFromBuffer(buffer, kBufferSize, &out_size);
353   EXPECT_TRUE(NULL != ccp);
354 
355   // Make sure that two parameters work as expected.
356   ActualCallParams<2, kBufferSize> params_4(kTag, 2);
357   params_4.CopyParamIn(0, &value, sizeof(value), false, ULONG_TYPE);
358   params_4.CopyParamIn(1, buffer, sizeof(buffer), false, VOIDPTR_TYPE);
359   buffer = const_cast<void*>(params_4.GetBuffer());
360   EXPECT_TRUE(NULL != buffer);
361 
362   ccp = CrossCallParamsEx::CreateFromBuffer(buffer, kBufferSize, &out_size);
363   EXPECT_TRUE(NULL != ccp);
364 
365 #if defined(_WIN64)
366   correct_size = params_4.OverrideSize(1);
367   params_4.OverrideSize(correct_size - 1);
368   ccp = CrossCallParamsEx::CreateFromBuffer(buffer, kBufferSize, &out_size);
369   EXPECT_TRUE(NULL == ccp);
370 #endif
371 }
372 
373 // This structure is passed to the mock server threads to simulate
374 // the server side IPC so it has the required kernel objects.
375 struct ServerEvents {
376   HANDLE ping;
377   HANDLE pong;
378   volatile LONG* state;
379   HANDLE mutex;
380 };
381 
382 // This is the server thread that quicky answers an IPC and exits.
QuickResponseServer(PVOID param)383 DWORD WINAPI QuickResponseServer(PVOID param) {
384   ServerEvents* events = reinterpret_cast<ServerEvents*>(param);
385   DWORD wait_result = 0;
386   wait_result = ::WaitForSingleObject(events->ping, INFINITE);
387   ::InterlockedExchange(events->state, kAckChannel);
388   ::SetEvent(events->pong);
389   return wait_result;
390 }
391 
392 class CrossCallParamsMock : public CrossCallParams {
393  public:
CrossCallParamsMock(uint32 tag,uint32 params_count)394   CrossCallParamsMock(uint32 tag, uint32 params_count)
395       :  CrossCallParams(tag, params_count) {
396   }
397  private:
398   void* params[4];
399 };
400 
FakeOkAnswerInChannel(void * channel)401 void FakeOkAnswerInChannel(void* channel) {
402   CrossCallReturn* answer = reinterpret_cast<CrossCallReturn*>(channel);
403   answer->call_outcome = SBOX_ALL_OK;
404 }
405 
406 // Create two threads that will quickly answer IPCs; the first one
407 // using channel 1 (channel 0 is busy) and one using channel 0. No time-out
408 // should occur.
TEST(IPCTest,ClientFastServer)409 TEST(IPCTest, ClientFastServer) {
410   const size_t channel_size = kIPCChannelSize;
411   size_t base_start = 0;
412   IPCControl* client_control =
413       MakeChannels(channel_size, 4096 * 2, &base_start);
414   FixChannels(client_control, base_start, kIPCChannelSize, FIX_PONG_NOT_READY);
415   client_control->server_alive = ::CreateMutex(NULL, FALSE, NULL);
416 
417   char* mem = reinterpret_cast<char*>(client_control);
418   SharedMemIPCClient client(mem);
419 
420   ServerEvents events = {0};
421   events.ping = client_control->channels[1].ping_event;
422   events.pong = client_control->channels[1].pong_event;
423   events.state = &client_control->channels[1].state;
424 
425   HANDLE t1 = ::CreateThread(NULL, 0, QuickResponseServer, &events, 0, NULL);
426   ASSERT_TRUE(NULL != t1);
427   ::CloseHandle(t1);
428 
429   void* buff0 = client.GetBuffer();
430   EXPECT_TRUE(mem + client_control->channels[0].channel_base == buff0);
431   EXPECT_EQ(kBusyChannel, client_control->channels[0].state);
432   EXPECT_EQ(kFreeChannel, client_control->channels[1].state);
433   EXPECT_EQ(kFreeChannel, client_control->channels[2].state);
434 
435   void* buff1 = client.GetBuffer();
436   EXPECT_TRUE(mem + client_control->channels[1].channel_base == buff1);
437   EXPECT_EQ(kBusyChannel, client_control->channels[0].state);
438   EXPECT_EQ(kBusyChannel, client_control->channels[1].state);
439   EXPECT_EQ(kFreeChannel, client_control->channels[2].state);
440 
441   EXPECT_EQ(0, client_control->channels[1].ipc_tag);
442 
443   uint32 tag = 7654;
444   CrossCallReturn answer;
445   CrossCallParamsMock* params1 = new(buff1) CrossCallParamsMock(tag, 1);
446   FakeOkAnswerInChannel(buff1);
447 
448   ResultCode result = client.DoCall(params1, &answer);
449   if (SBOX_ERROR_CHANNEL_ERROR != result)
450     client.FreeBuffer(buff1);
451 
452   EXPECT_TRUE(SBOX_ALL_OK == result);
453   EXPECT_EQ(tag, client_control->channels[1].ipc_tag);
454   EXPECT_EQ(kBusyChannel, client_control->channels[0].state);
455   EXPECT_EQ(kFreeChannel, client_control->channels[1].state);
456   EXPECT_EQ(kFreeChannel, client_control->channels[2].state);
457 
458   HANDLE t2 = ::CreateThread(NULL, 0, QuickResponseServer, &events, 0, NULL);
459   ASSERT_TRUE(NULL != t2);
460   ::CloseHandle(t2);
461 
462   client.FreeBuffer(buff0);
463   events.ping = client_control->channels[0].ping_event;
464   events.pong = client_control->channels[0].pong_event;
465   events.state = &client_control->channels[0].state;
466 
467   tag = 4567;
468   CrossCallParamsMock* params2 = new(buff0) CrossCallParamsMock(tag, 1);
469   FakeOkAnswerInChannel(buff0);
470 
471   result = client.DoCall(params2, &answer);
472   if (SBOX_ERROR_CHANNEL_ERROR != result)
473     client.FreeBuffer(buff0);
474 
475   EXPECT_TRUE(SBOX_ALL_OK == result);
476   EXPECT_EQ(tag, client_control->channels[0].ipc_tag);
477   EXPECT_EQ(kFreeChannel, client_control->channels[0].state);
478   EXPECT_EQ(kFreeChannel, client_control->channels[1].state);
479   EXPECT_EQ(kFreeChannel, client_control->channels[2].state);
480 
481   CloseChannelEvents(client_control);
482   ::CloseHandle(client_control->server_alive);
483 
484   delete[] reinterpret_cast<char*>(client_control);
485 }
486 
487 // This is the server thread that very slowly answers an IPC and exits. Note
488 // that the pong event needs to be signaled twice.
SlowResponseServer(PVOID param)489 DWORD WINAPI SlowResponseServer(PVOID param) {
490   ServerEvents* events = reinterpret_cast<ServerEvents*>(param);
491   DWORD wait_result = 0;
492   wait_result = ::WaitForSingleObject(events->ping, INFINITE);
493   ::Sleep(kIPCWaitTimeOut1 + kIPCWaitTimeOut2 + 200);
494   ::InterlockedExchange(events->state, kAckChannel);
495   ::SetEvent(events->pong);
496   return wait_result;
497 }
498 
499 // This thread's job is to keep the mutex locked.
MainServerThread(PVOID param)500 DWORD WINAPI MainServerThread(PVOID param) {
501   ServerEvents* events = reinterpret_cast<ServerEvents*>(param);
502   DWORD wait_result = 0;
503   wait_result = ::WaitForSingleObject(events->mutex, INFINITE);
504   Sleep(kIPCWaitTimeOut1 * 20);
505   return wait_result;
506 }
507 
508 // Creates a server thread that answers the IPC so slow that is guaranteed to
509 // trigger the time-out code path in the client. A second thread is created
510 // to hold locked the server_alive mutex: this signals the client that the
511 // server is not dead and it retries the wait.
TEST(IPCTest,ClientSlowServer)512 TEST(IPCTest, ClientSlowServer) {
513   size_t base_start = 0;
514   IPCControl* client_control =
515       MakeChannels(kIPCChannelSize, 4096*2, &base_start);
516   FixChannels(client_control, base_start, kIPCChannelSize, FIX_PONG_NOT_READY);
517   client_control->server_alive = ::CreateMutex(NULL, FALSE, NULL);
518 
519   char* mem = reinterpret_cast<char*>(client_control);
520   SharedMemIPCClient client(mem);
521 
522   ServerEvents events = {0};
523   events.ping = client_control->channels[0].ping_event;
524   events.pong = client_control->channels[0].pong_event;
525   events.state = &client_control->channels[0].state;
526 
527   HANDLE t1 = ::CreateThread(NULL, 0, SlowResponseServer, &events, 0, NULL);
528   ASSERT_TRUE(NULL != t1);
529   ::CloseHandle(t1);
530 
531   ServerEvents events2 = {0};
532   events2.pong = events.pong;
533   events2.mutex = client_control->server_alive;
534 
535   HANDLE t2 = ::CreateThread(NULL, 0, MainServerThread, &events2, 0, NULL);
536   ASSERT_TRUE(NULL != t2);
537   ::CloseHandle(t2);
538 
539   ::Sleep(1);
540 
541   void* buff0 = client.GetBuffer();
542   uint32 tag = 4321;
543   CrossCallReturn answer;
544   CrossCallParamsMock* params1 = new(buff0) CrossCallParamsMock(tag, 1);
545   FakeOkAnswerInChannel(buff0);
546 
547   ResultCode result = client.DoCall(params1, &answer);
548   if (SBOX_ERROR_CHANNEL_ERROR != result)
549     client.FreeBuffer(buff0);
550 
551   EXPECT_TRUE(SBOX_ALL_OK == result);
552   EXPECT_EQ(tag, client_control->channels[0].ipc_tag);
553   EXPECT_EQ(kFreeChannel, client_control->channels[0].state);
554 
555   CloseChannelEvents(client_control);
556   ::CloseHandle(client_control->server_alive);
557   delete[] reinterpret_cast<char*>(client_control);
558 }
559 
560 // This test-only IPC dispatcher has two handlers with the same signature
561 // but only CallOneHandler should be used.
562 class UnitTestIPCDispatcher : public Dispatcher {
563  public:
564   enum {
565     CALL_ONE_TAG = 78,
566     CALL_TWO_TAG = 87
567   };
568 
569   UnitTestIPCDispatcher();
~UnitTestIPCDispatcher()570   ~UnitTestIPCDispatcher() {};
571 
SetupService(InterceptionManager * manager,int service)572   virtual bool SetupService(InterceptionManager* manager, int service) {
573     return true;
574   }
575 
576  private:
CallOneHandler(IPCInfo * ipc,HANDLE p1,DWORD p2)577   bool CallOneHandler(IPCInfo* ipc, HANDLE p1, DWORD p2) {
578     ipc->return_info.extended[0].handle = p1;
579     ipc->return_info.extended[1].unsigned_int = p2;
580     return true;
581   }
582 
CallTwoHandler(IPCInfo * ipc,HANDLE p1,DWORD p2)583   bool CallTwoHandler(IPCInfo* ipc, HANDLE p1, DWORD p2) {
584     return true;
585   }
586 };
587 
UnitTestIPCDispatcher()588 UnitTestIPCDispatcher::UnitTestIPCDispatcher() {
589   static const IPCCall call_one = {
590     {CALL_ONE_TAG, VOIDPTR_TYPE, ULONG_TYPE},
591     reinterpret_cast<CallbackGeneric>(
592         &UnitTestIPCDispatcher::CallOneHandler)
593   };
594   static const IPCCall call_two = {
595     {CALL_TWO_TAG, VOIDPTR_TYPE, ULONG_TYPE},
596     reinterpret_cast<CallbackGeneric>(
597         &UnitTestIPCDispatcher::CallTwoHandler)
598   };
599   ipc_calls_.push_back(call_one);
600   ipc_calls_.push_back(call_two);
601 }
602 
603 // This test does most of the shared memory IPC client-server roundtrip
604 // and tests the packing, unpacking and call dispatching.
TEST(IPCTest,SharedMemServerTests)605 TEST(IPCTest, SharedMemServerTests) {
606   size_t base_start = 0;
607   IPCControl* client_control =
608       MakeChannels(kIPCChannelSize, 4096, &base_start);
609   client_control->server_alive = HANDLE(1);
610   FixChannels(client_control, base_start, kIPCChannelSize, FIX_PONG_READY);
611 
612   char* mem = reinterpret_cast<char*>(client_control);
613   SharedMemIPCClient client(mem);
614 
615   CrossCallReturn answer;
616   HANDLE bar = HANDLE(191919);
617   DWORD foo = 6767676;
618   CrossCall(client, UnitTestIPCDispatcher::CALL_ONE_TAG, bar, foo, &answer);
619   void* buff = client.GetBuffer();
620   ASSERT_TRUE(NULL != buff);
621 
622   UnitTestIPCDispatcher dispatcher;
623   // Since we are directly calling InvokeCallback, most of this structure
624   // can be set to NULL.
625   sandbox::SharedMemIPCServer::ServerControl srv_control = {
626       NULL, NULL, kIPCChannelSize, NULL,
627       reinterpret_cast<char*>(client_control),
628       NULL, &dispatcher, {0} };
629 
630   sandbox::CrossCallReturn call_return = {0};
631   EXPECT_TRUE(SharedMemIPCServer::InvokeCallback(&srv_control, buff,
632                                                  &call_return));
633   EXPECT_EQ(SBOX_ALL_OK, call_return.call_outcome);
634   EXPECT_TRUE(bar == call_return.extended[0].handle);
635   EXPECT_EQ(foo, call_return.extended[1].unsigned_int);
636 
637   CloseChannelEvents(client_control);
638   delete[] reinterpret_cast<char*>(client_control);
639 }
640 
641 }  // namespace sandbox
642