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