• 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   // 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