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.
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"
14 // Helper function to make the fake shared memory with some
15 // basic elements initialized.
16 IPCControl
* MakeChannels(size_t channel_size
, size_t total_shared_size
,
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
;
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
);
51 base_start
+= channel_size
;
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
);
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
);
72 EXPECT_EQ(216, channel_start
);
74 EXPECT_EQ(108, channel_start
);
76 delete[] reinterpret_cast<char*>(client_control
);
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
);
87 char* mem
= reinterpret_cast<char*>(client_control
);
88 SharedMemIPCClient
client(mem
);
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
);
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
);
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
);
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
);
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
);
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
);
144 delete[] reinterpret_cast<char*>(client_control
);
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
);
157 char* mem
= reinterpret_cast<char*>(client_control
);
158 SharedMemIPCClient
client(mem
);
160 CrossCallReturn answer
;
162 const wchar_t text
[] = L
"98765 - 43210";
163 std::wstring copied_text
;
164 CrossCallParamsEx
* actual_params
;
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());
173 // Check with an empty string.
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
));
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());
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());
207 std::wstring copied_text_p0
, copied_text_p2
;
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());
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
);
224 CloseChannelEvents(client_control
);
225 delete[] reinterpret_cast<char*>(client_control
);
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
);
238 const wchar_t text
[] = L
"godzilla";
239 CrossCallParamsEx
* actual_params
;
241 char* mem
= reinterpret_cast<char*>(client_control
);
242 SharedMemIPCClient
client(mem
);
244 CrossCallReturn answer
;
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
));
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());
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
));
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());
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
));
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
));
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
));
295 CloseChannelEvents(client_control
);
296 delete[] reinterpret_cast<char*>(client_control
);
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());
309 CrossCallParamsEx
* ccp
= 0;
310 ccp
= CrossCallParamsEx::CreateFromBuffer(buffer
, params_1
.GetSize(),
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
));
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());
329 EXPECT_TRUE(NULL
!= buffer
);
330 ccp
= CrossCallParamsEx::CreateFromBuffer(buffer
, params_1
.GetSize(),
332 // If the buffer is malformed the return is NULL.
333 EXPECT_TRUE(NULL
== ccp
);
335 #endif // defined(NDEBUG)
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
);
342 uint32 correct_size
= params_3
.OverrideSize(1);
343 ccp
= CrossCallParamsEx::CreateFromBuffer(buffer
, kBufferSize
, &out_size
);
344 EXPECT_TRUE(NULL
== ccp
);
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
);
351 params_3
.OverrideSize(correct_size
);
352 ccp
= CrossCallParamsEx::CreateFromBuffer(buffer
, kBufferSize
, &out_size
);
353 EXPECT_TRUE(NULL
!= ccp
);
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
);
362 ccp
= CrossCallParamsEx::CreateFromBuffer(buffer
, kBufferSize
, &out_size
);
363 EXPECT_TRUE(NULL
!= ccp
);
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
);
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
{
378 volatile LONG
* state
;
382 // This is the server thread that quicky answers an IPC and exits.
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
);
392 class CrossCallParamsMock
: public CrossCallParams
{
394 CrossCallParamsMock(uint32 tag
, uint32 params_count
)
395 : CrossCallParams(tag
, params_count
) {
401 void FakeOkAnswerInChannel(void* channel
) {
402 CrossCallReturn
* answer
= reinterpret_cast<CrossCallReturn
*>(channel
);
403 answer
->call_outcome
= SBOX_ALL_OK
;
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
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
);
417 char* mem
= reinterpret_cast<char*>(client_control
);
418 SharedMemIPCClient
client(mem
);
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
;
425 HANDLE t1
= ::CreateThread(NULL
, 0, QuickResponseServer
, &events
, 0, NULL
);
426 ASSERT_TRUE(NULL
!= t1
);
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
);
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
);
441 EXPECT_EQ(0, client_control
->channels
[1].ipc_tag
);
444 CrossCallReturn answer
;
445 CrossCallParamsMock
* params1
= new(buff1
) CrossCallParamsMock(tag
, 1);
446 FakeOkAnswerInChannel(buff1
);
448 ResultCode result
= client
.DoCall(params1
, &answer
);
449 if (SBOX_ERROR_CHANNEL_ERROR
!= result
)
450 client
.FreeBuffer(buff1
);
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
);
458 HANDLE t2
= ::CreateThread(NULL
, 0, QuickResponseServer
, &events
, 0, NULL
);
459 ASSERT_TRUE(NULL
!= t2
);
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
;
468 CrossCallParamsMock
* params2
= new(buff0
) CrossCallParamsMock(tag
, 1);
469 FakeOkAnswerInChannel(buff0
);
471 result
= client
.DoCall(params2
, &answer
);
472 if (SBOX_ERROR_CHANNEL_ERROR
!= result
)
473 client
.FreeBuffer(buff0
);
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
);
481 CloseChannelEvents(client_control
);
482 ::CloseHandle(client_control
->server_alive
);
484 delete[] reinterpret_cast<char*>(client_control
);
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.
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
);
499 // This thread's job is to keep the mutex locked.
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);
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.
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
);
519 char* mem
= reinterpret_cast<char*>(client_control
);
520 SharedMemIPCClient
client(mem
);
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
;
527 HANDLE t1
= ::CreateThread(NULL
, 0, SlowResponseServer
, &events
, 0, NULL
);
528 ASSERT_TRUE(NULL
!= t1
);
531 ServerEvents events2
= {0};
532 events2
.pong
= events
.pong
;
533 events2
.mutex
= client_control
->server_alive
;
535 HANDLE t2
= ::CreateThread(NULL
, 0, MainServerThread
, &events2
, 0, NULL
);
536 ASSERT_TRUE(NULL
!= t2
);
541 void* buff0
= client
.GetBuffer();
543 CrossCallReturn answer
;
544 CrossCallParamsMock
* params1
= new(buff0
) CrossCallParamsMock(tag
, 1);
545 FakeOkAnswerInChannel(buff0
);
547 ResultCode result
= client
.DoCall(params1
, &answer
);
548 if (SBOX_ERROR_CHANNEL_ERROR
!= result
)
549 client
.FreeBuffer(buff0
);
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
);
555 CloseChannelEvents(client_control
);
556 ::CloseHandle(client_control
->server_alive
);
557 delete[] reinterpret_cast<char*>(client_control
);
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
{
569 UnitTestIPCDispatcher();
570 ~UnitTestIPCDispatcher() {};
572 virtual bool SetupService(InterceptionManager
* manager
, int service
) {
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
;
583 bool CallTwoHandler(IPCInfo
* ipc
, HANDLE p1
, DWORD p2
) {
588 UnitTestIPCDispatcher::UnitTestIPCDispatcher() {
589 static const IPCCall call_one
= {
590 {CALL_ONE_TAG
, VOIDPTR_TYPE
, ULONG_TYPE
},
591 reinterpret_cast<CallbackGeneric
>(
592 &UnitTestIPCDispatcher::CallOneHandler
)
594 static const IPCCall call_two
= {
595 {CALL_TWO_TAG
, VOIDPTR_TYPE
, ULONG_TYPE
},
596 reinterpret_cast<CallbackGeneric
>(
597 &UnitTestIPCDispatcher::CallTwoHandler
)
599 ipc_calls_
.push_back(call_one
);
600 ipc_calls_
.push_back(call_two
);
603 // This test does most of the shared memory IPC client-server roundtrip
604 // and tests the packing, unpacking and call dispatching.
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
);
612 char* mem
= reinterpret_cast<char*>(client_control
);
613 SharedMemIPCClient
client(mem
);
615 CrossCallReturn answer
;
616 HANDLE bar
= HANDLE(191919);
618 CrossCall(client
, UnitTestIPCDispatcher::CALL_ONE_TAG
, bar
, foo
, &answer
);
619 void* buff
= client
.GetBuffer();
620 ASSERT_TRUE(NULL
!= buff
);
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} };
630 sandbox::CrossCallReturn call_return
= {0};
631 EXPECT_TRUE(SharedMemIPCServer::InvokeCallback(&srv_control
, buff
,
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
);
637 CloseChannelEvents(client_control
);
638 delete[] reinterpret_cast<char*>(client_control
);
641 } // namespace sandbox