Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(269)

Side by Side Diff: sandbox/win/src/ipc_unittest.cc

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

Powered by Google App Engine
This is Rietveld 408576698