OLD | NEW |
| (Empty) |
1 // Copyright 2015 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 "build/build_config.h" | |
6 | |
7 #include <windows.h> | |
8 | |
9 #include <memory> | |
10 #include <tuple> | |
11 | |
12 #include "base/files/file_path.h" | |
13 #include "base/files/file_util.h" | |
14 #include "base/files/scoped_temp_dir.h" | |
15 #include "base/memory/shared_memory.h" | |
16 #include "base/memory/shared_memory_handle.h" | |
17 #include "base/run_loop.h" | |
18 #include "base/win/scoped_handle.h" | |
19 #include "ipc/attachment_broker_privileged_win.h" | |
20 #include "ipc/attachment_broker_unprivileged_win.h" | |
21 #include "ipc/handle_attachment_win.h" | |
22 #include "ipc/handle_win.h" | |
23 #include "ipc/ipc_listener.h" | |
24 #include "ipc/ipc_message.h" | |
25 #include "ipc/ipc_test_base.h" | |
26 #include "ipc/ipc_test_messages.h" | |
27 | |
28 namespace { | |
29 | |
30 using base::win::ScopedHandle; | |
31 | |
32 const char kDataBuffer[] = "This is some test data to write to the file."; | |
33 const size_t kSharedMemorySize = 20000; | |
34 | |
35 // Returns the contents of the file represented by |h| as a std::string. | |
36 std::string ReadFromFile(HANDLE h) { | |
37 SetFilePointer(h, 0, nullptr, FILE_BEGIN); | |
38 char buffer[100]; | |
39 DWORD bytes_read; | |
40 BOOL success = ::ReadFile(h, buffer, static_cast<DWORD>(strlen(kDataBuffer)), | |
41 &bytes_read, nullptr); | |
42 return success ? std::string(buffer, bytes_read) : std::string(); | |
43 } | |
44 | |
45 ScopedHandle GetHandleFromBrokeredAttachment( | |
46 const scoped_refptr<IPC::BrokerableAttachment>& attachment) { | |
47 if (attachment->GetType() != | |
48 IPC::BrokerableAttachment::TYPE_BROKERABLE_ATTACHMENT) { | |
49 LOG(INFO) << "Attachment type not TYPE_BROKERABLE_ATTACHMENT."; | |
50 return ScopedHandle(nullptr); | |
51 } | |
52 | |
53 if (attachment->GetBrokerableType() != | |
54 IPC::BrokerableAttachment::WIN_HANDLE) { | |
55 LOG(INFO) << "Brokerable type not WIN_HANDLE."; | |
56 return ScopedHandle(nullptr); | |
57 } | |
58 | |
59 IPC::internal::HandleAttachmentWin* received_handle_attachment = | |
60 static_cast<IPC::internal::HandleAttachmentWin*>(attachment.get()); | |
61 ScopedHandle h(received_handle_attachment->get_handle()); | |
62 received_handle_attachment->reset_handle_ownership(); | |
63 return h; | |
64 } | |
65 | |
66 // |message| must be deserializable as a TestHandleWinMsg. Returns the HANDLE, | |
67 // or nullptr if deserialization failed. | |
68 ScopedHandle GetHandleFromTestHandleWinMsg(const IPC::Message& message) { | |
69 // Expect a message with a brokered attachment. | |
70 if (!message.HasBrokerableAttachments()) { | |
71 LOG(INFO) << "Message missing brokerable attachment."; | |
72 return ScopedHandle(nullptr); | |
73 } | |
74 | |
75 TestHandleWinMsg::Schema::Param p; | |
76 bool success = TestHandleWinMsg::Read(&message, &p); | |
77 if (!success) { | |
78 LOG(INFO) << "Failed to deserialize message."; | |
79 return ScopedHandle(nullptr); | |
80 } | |
81 | |
82 IPC::HandleWin handle_win = std::get<1>(p); | |
83 return ScopedHandle(handle_win.get_handle()); | |
84 } | |
85 | |
86 // Returns a mapped, shared memory region based on the handle in |message|. | |
87 std::unique_ptr<base::SharedMemory> GetSharedMemoryFromSharedMemoryHandleMsg1( | |
88 const IPC::Message& message, | |
89 size_t size) { | |
90 // Expect a message with a brokered attachment. | |
91 if (!message.HasBrokerableAttachments()) { | |
92 LOG(INFO) << "Message missing brokerable attachment."; | |
93 return nullptr; | |
94 } | |
95 | |
96 TestSharedMemoryHandleMsg1::Schema::Param p; | |
97 bool success = TestSharedMemoryHandleMsg1::Read(&message, &p); | |
98 if (!success) { | |
99 LOG(INFO) << "Failed to deserialize message."; | |
100 return nullptr; | |
101 } | |
102 | |
103 base::SharedMemoryHandle handle = std::get<0>(p); | |
104 std::unique_ptr<base::SharedMemory> shared_memory( | |
105 new base::SharedMemory(handle, false)); | |
106 | |
107 shared_memory->Map(size); | |
108 return shared_memory; | |
109 } | |
110 | |
111 // |message| must be deserializable as a TestTwoHandleWinMsg. Returns the | |
112 // HANDLE, or nullptr if deserialization failed. | |
113 bool GetHandleFromTestTwoHandleWinMsg(const IPC::Message& message, | |
114 HANDLE* h1, | |
115 HANDLE* h2) { | |
116 // Expect a message with a brokered attachment. | |
117 if (!message.HasBrokerableAttachments()) { | |
118 LOG(INFO) << "Message missing brokerable attachment."; | |
119 return false; | |
120 } | |
121 | |
122 TestTwoHandleWinMsg::Schema::Param p; | |
123 bool success = TestTwoHandleWinMsg::Read(&message, &p); | |
124 if (!success) { | |
125 LOG(INFO) << "Failed to deserialize message."; | |
126 return false; | |
127 } | |
128 | |
129 IPC::HandleWin handle_win = std::get<0>(p); | |
130 *h1 = handle_win.get_handle(); | |
131 handle_win = std::get<1>(p); | |
132 *h2 = handle_win.get_handle(); | |
133 return true; | |
134 } | |
135 | |
136 // |message| must be deserializable as a TestHandleWinMsg. Returns true if the | |
137 // attached file HANDLE has contents |kDataBuffer|. | |
138 bool CheckContentsOfTestMessage(const IPC::Message& message) { | |
139 ScopedHandle h(GetHandleFromTestHandleWinMsg(message)); | |
140 if (h.Get() == nullptr) { | |
141 LOG(INFO) << "Failed to get handle from TestHandleWinMsg."; | |
142 return false; | |
143 } | |
144 | |
145 std::string contents = ReadFromFile(h.Get()); | |
146 bool success = (contents == std::string(kDataBuffer)); | |
147 if (!success) { | |
148 LOG(INFO) << "Expected contents: " << std::string(kDataBuffer); | |
149 LOG(INFO) << "Read contents: " << contents; | |
150 } | |
151 return success; | |
152 } | |
153 | |
154 // Returns 0 on error. | |
155 DWORD GetCurrentProcessHandleCount() { | |
156 DWORD handle_count = 0; | |
157 BOOL success = ::GetProcessHandleCount(::GetCurrentProcess(), &handle_count); | |
158 return success ? handle_count : 0; | |
159 } | |
160 | |
161 enum TestResult { | |
162 RESULT_UNKNOWN, | |
163 RESULT_SUCCESS, | |
164 RESULT_FAILURE, | |
165 }; | |
166 | |
167 // Once the test is finished, send a control message to the parent process with | |
168 // the result. The message may require the runloop to be run before its | |
169 // dispatched. | |
170 void SendControlMessage(IPC::Sender* sender, bool success) { | |
171 IPC::Message* message = new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL); | |
172 TestResult result = success ? RESULT_SUCCESS : RESULT_FAILURE; | |
173 message->WriteInt(result); | |
174 sender->Send(message); | |
175 } | |
176 | |
177 class MockObserver : public IPC::AttachmentBroker::Observer { | |
178 public: | |
179 void ReceivedBrokerableAttachmentWithId( | |
180 const IPC::BrokerableAttachment::AttachmentId& id) override { | |
181 id_ = id; | |
182 } | |
183 IPC::BrokerableAttachment::AttachmentId* get_id() { return &id_; } | |
184 | |
185 private: | |
186 IPC::BrokerableAttachment::AttachmentId id_; | |
187 }; | |
188 | |
189 // Forwards all messages to |listener_|. Quits the message loop after a | |
190 // message is received, or the channel has an error. | |
191 class ProxyListener : public IPC::Listener { | |
192 public: | |
193 ProxyListener() : listener_(nullptr), reason_(MESSAGE_RECEIVED) {} | |
194 ~ProxyListener() override {} | |
195 | |
196 // The reason for exiting the message loop. | |
197 enum Reason { MESSAGE_RECEIVED, CHANNEL_ERROR }; | |
198 | |
199 bool OnMessageReceived(const IPC::Message& message) override { | |
200 bool result = false; | |
201 if (listener_) | |
202 result = listener_->OnMessageReceived(message); | |
203 reason_ = MESSAGE_RECEIVED; | |
204 messages_.push_back(message); | |
205 base::MessageLoop::current()->QuitNow(); | |
206 return result; | |
207 } | |
208 | |
209 void OnChannelError() override { | |
210 reason_ = CHANNEL_ERROR; | |
211 base::MessageLoop::current()->QuitNow(); | |
212 } | |
213 | |
214 void set_listener(IPC::Listener* listener) { listener_ = listener; } | |
215 Reason get_reason() { return reason_; } | |
216 IPC::Message get_first_message() { return messages_[0]; } | |
217 void pop_first_message() { messages_.erase(messages_.begin()); } | |
218 bool has_message() { return !messages_.empty(); } | |
219 | |
220 private: | |
221 IPC::Listener* listener_; | |
222 Reason reason_; | |
223 std::vector<IPC::Message> messages_; | |
224 }; | |
225 | |
226 // Waits for a result to be sent over the channel. Quits the message loop | |
227 // after a message is received, or the channel has an error. | |
228 class ResultListener : public IPC::Listener { | |
229 public: | |
230 ResultListener() : result_(RESULT_UNKNOWN) {} | |
231 ~ResultListener() override {} | |
232 | |
233 bool OnMessageReceived(const IPC::Message& message) override { | |
234 base::PickleIterator iter(message); | |
235 | |
236 int result; | |
237 EXPECT_TRUE(iter.ReadInt(&result)); | |
238 result_ = static_cast<TestResult>(result); | |
239 return true; | |
240 } | |
241 | |
242 TestResult get_result() { return result_; } | |
243 | |
244 private: | |
245 TestResult result_; | |
246 }; | |
247 | |
248 // The parent process acts as an unprivileged process. The forked process acts | |
249 // as the privileged process. | |
250 class IPCAttachmentBrokerPrivilegedWinTest : public IPCTestBase { | |
251 public: | |
252 IPCAttachmentBrokerPrivilegedWinTest() {} | |
253 ~IPCAttachmentBrokerPrivilegedWinTest() override {} | |
254 | |
255 void SetUp() override { | |
256 IPCTestBase::SetUp(); | |
257 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); | |
258 ASSERT_TRUE( | |
259 base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &temp_path_)); | |
260 } | |
261 | |
262 void TearDown() override { IPCTestBase::TearDown(); } | |
263 | |
264 // Takes ownership of |broker|. Has no effect if called after CommonSetUp(). | |
265 void set_broker(IPC::AttachmentBrokerUnprivilegedWin* broker) { | |
266 broker_.reset(broker); | |
267 } | |
268 | |
269 void CommonSetUp() { | |
270 PreConnectSetUp(); | |
271 PostConnectSetUp(); | |
272 } | |
273 | |
274 // All of setup before the channel is connected. | |
275 void PreConnectSetUp() { | |
276 if (!broker_.get()) | |
277 set_broker(new IPC::AttachmentBrokerUnprivilegedWin); | |
278 broker_->AddObserver(&observer_, task_runner()); | |
279 CreateChannel(&proxy_listener_); | |
280 broker_->RegisterBrokerCommunicationChannel(channel()); | |
281 } | |
282 | |
283 // All of setup including the connection and everything after. | |
284 void PostConnectSetUp() { | |
285 ASSERT_TRUE(ConnectChannel()); | |
286 ASSERT_TRUE(StartClient()); | |
287 | |
288 handle_count_ = GetCurrentProcessHandleCount(); | |
289 EXPECT_NE(handle_count_, 0u); | |
290 } | |
291 | |
292 void CommonTearDown() { | |
293 EXPECT_EQ(handle_count_, handle_count_); | |
294 | |
295 // Close the channel so the client's OnChannelError() gets fired. | |
296 channel()->Close(); | |
297 | |
298 EXPECT_TRUE(WaitForClientShutdown()); | |
299 DestroyChannel(); | |
300 broker_.reset(); | |
301 } | |
302 | |
303 HANDLE CreateTempFile() { | |
304 EXPECT_NE(-1, WriteFile(temp_path_, kDataBuffer, | |
305 static_cast<int>(strlen(kDataBuffer)))); | |
306 | |
307 HANDLE h = | |
308 CreateFile(temp_path_.value().c_str(), GENERIC_READ | GENERIC_WRITE, 0, | |
309 nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); | |
310 EXPECT_NE(h, INVALID_HANDLE_VALUE); | |
311 return h; | |
312 } | |
313 | |
314 void SendMessageWithAttachment(HANDLE h) { | |
315 IPC::HandleWin handle_win(h, IPC::HandleWin::FILE_READ_WRITE); | |
316 IPC::Message* message = new TestHandleWinMsg(100, handle_win, 200); | |
317 sender()->Send(message); | |
318 } | |
319 | |
320 ProxyListener* get_proxy_listener() { return &proxy_listener_; } | |
321 IPC::AttachmentBrokerUnprivilegedWin* get_broker() { return broker_.get(); } | |
322 MockObserver* get_observer() { return &observer_; } | |
323 | |
324 private: | |
325 base::ScopedTempDir temp_dir_; | |
326 base::FilePath temp_path_; | |
327 ProxyListener proxy_listener_; | |
328 std::unique_ptr<IPC::AttachmentBrokerUnprivilegedWin> broker_; | |
329 MockObserver observer_; | |
330 DWORD handle_count_; | |
331 }; | |
332 | |
333 // A broker which always sets the current process as the destination process | |
334 // for attachments. | |
335 class MockBroker : public IPC::AttachmentBrokerUnprivilegedWin { | |
336 public: | |
337 MockBroker() {} | |
338 ~MockBroker() override {} | |
339 bool SendAttachmentToProcess( | |
340 const scoped_refptr<IPC::BrokerableAttachment>& attachment, | |
341 base::ProcessId destination_process) override { | |
342 return IPC::AttachmentBrokerUnprivilegedWin::SendAttachmentToProcess( | |
343 attachment, base::Process::Current().Pid()); | |
344 } | |
345 }; | |
346 | |
347 // An unprivileged process makes a file HANDLE, and writes a string to it. The | |
348 // file HANDLE is sent to the privileged process using the attachment broker. | |
349 // The privileged process dups the HANDLE into its own HANDLE table. This test | |
350 // checks that the file has the same contents in the privileged process. | |
351 TEST_F(IPCAttachmentBrokerPrivilegedWinTest, SendHandle) { | |
352 Init("SendHandle"); | |
353 | |
354 CommonSetUp(); | |
355 ResultListener result_listener; | |
356 get_proxy_listener()->set_listener(&result_listener); | |
357 | |
358 HANDLE h = CreateTempFile(); | |
359 SendMessageWithAttachment(h); | |
360 base::RunLoop().Run(); | |
361 | |
362 // Check the result. | |
363 ASSERT_EQ(ProxyListener::MESSAGE_RECEIVED, | |
364 get_proxy_listener()->get_reason()); | |
365 ASSERT_EQ(result_listener.get_result(), RESULT_SUCCESS); | |
366 | |
367 CommonTearDown(); | |
368 } | |
369 | |
370 // Similar to SendHandle, except the file HANDLE attached to the message has | |
371 // neither read nor write permissions. | |
372 TEST_F(IPCAttachmentBrokerPrivilegedWinTest, | |
373 SendHandleWithoutPermissions) { | |
374 Init("SendHandleWithoutPermissions"); | |
375 | |
376 CommonSetUp(); | |
377 ResultListener result_listener; | |
378 get_proxy_listener()->set_listener(&result_listener); | |
379 | |
380 HANDLE h = CreateTempFile(); | |
381 HANDLE h2; | |
382 BOOL result = ::DuplicateHandle(GetCurrentProcess(), h, GetCurrentProcess(), | |
383 &h2, 0, FALSE, DUPLICATE_CLOSE_SOURCE); | |
384 ASSERT_TRUE(result); | |
385 IPC::HandleWin handle_win(h2, IPC::HandleWin::DUPLICATE); | |
386 IPC::Message* message = new TestHandleWinMsg(100, handle_win, 200); | |
387 sender()->Send(message); | |
388 base::RunLoop().Run(); | |
389 | |
390 // Check the result. | |
391 ASSERT_EQ(ProxyListener::MESSAGE_RECEIVED, | |
392 get_proxy_listener()->get_reason()); | |
393 ASSERT_EQ(result_listener.get_result(), RESULT_SUCCESS); | |
394 | |
395 CommonTearDown(); | |
396 } | |
397 | |
398 // Similar to SendHandle, except the attachment's destination process is this | |
399 // process. This is an unrealistic scenario, but simulates an unprivileged | |
400 // process sending an attachment to another unprivileged process. | |
401 TEST_F(IPCAttachmentBrokerPrivilegedWinTest, SendHandleToSelf) { | |
402 Init("SendHandleToSelf"); | |
403 | |
404 set_broker(new MockBroker); | |
405 | |
406 PreConnectSetUp(); | |
407 // Technically, the channel is an endpoint, but we need the proxy listener to | |
408 // receive the messages so that it can quit the message loop. | |
409 channel()->SetAttachmentBrokerEndpoint(false); | |
410 PostConnectSetUp(); | |
411 get_proxy_listener()->set_listener(get_broker()); | |
412 | |
413 HANDLE h = CreateTempFile(); | |
414 SendMessageWithAttachment(h); | |
415 base::RunLoop().Run(); | |
416 | |
417 // Get the received attachment. | |
418 IPC::BrokerableAttachment::AttachmentId* id = get_observer()->get_id(); | |
419 scoped_refptr<IPC::BrokerableAttachment> received_attachment; | |
420 get_broker()->GetAttachmentWithId(*id, &received_attachment); | |
421 ASSERT_NE(received_attachment.get(), nullptr); | |
422 | |
423 // Check that it's a different entry in the HANDLE table. | |
424 ScopedHandle h2(GetHandleFromBrokeredAttachment(received_attachment)); | |
425 EXPECT_NE(h2.Get(), h); | |
426 | |
427 // But still points to the same file. | |
428 std::string contents = ReadFromFile(h2.Get()); | |
429 EXPECT_EQ(contents, std::string(kDataBuffer)); | |
430 | |
431 CommonTearDown(); | |
432 } | |
433 | |
434 // Similar to SendHandle, but sends a message with two instances of the same | |
435 // handle. | |
436 TEST_F(IPCAttachmentBrokerPrivilegedWinTest, SendTwoHandles) { | |
437 Init("SendTwoHandles"); | |
438 | |
439 CommonSetUp(); | |
440 ResultListener result_listener; | |
441 get_proxy_listener()->set_listener(&result_listener); | |
442 | |
443 HANDLE h = CreateTempFile(); | |
444 HANDLE h2; | |
445 BOOL result = ::DuplicateHandle(GetCurrentProcess(), h, GetCurrentProcess(), | |
446 &h2, 0, FALSE, DUPLICATE_SAME_ACCESS); | |
447 ASSERT_TRUE(result); | |
448 IPC::HandleWin handle_win1(h, IPC::HandleWin::FILE_READ_WRITE); | |
449 IPC::HandleWin handle_win2(h2, IPC::HandleWin::FILE_READ_WRITE); | |
450 IPC::Message* message = new TestTwoHandleWinMsg(handle_win1, handle_win2); | |
451 sender()->Send(message); | |
452 base::RunLoop().Run(); | |
453 | |
454 // Check the result. | |
455 ASSERT_EQ(ProxyListener::MESSAGE_RECEIVED, | |
456 get_proxy_listener()->get_reason()); | |
457 ASSERT_EQ(result_listener.get_result(), RESULT_SUCCESS); | |
458 | |
459 CommonTearDown(); | |
460 } | |
461 | |
462 // Similar to SendHandle, but sends the same message twice. | |
463 TEST_F(IPCAttachmentBrokerPrivilegedWinTest, SendHandleTwice) { | |
464 Init("SendHandleTwice"); | |
465 | |
466 CommonSetUp(); | |
467 ResultListener result_listener; | |
468 get_proxy_listener()->set_listener(&result_listener); | |
469 | |
470 HANDLE h = CreateTempFile(); | |
471 HANDLE h2; | |
472 BOOL result = ::DuplicateHandle(GetCurrentProcess(), h, GetCurrentProcess(), | |
473 &h2, 0, FALSE, DUPLICATE_SAME_ACCESS); | |
474 ASSERT_TRUE(result); | |
475 SendMessageWithAttachment(h); | |
476 SendMessageWithAttachment(h2); | |
477 base::RunLoop().Run(); | |
478 | |
479 // Check the result. | |
480 ASSERT_EQ(ProxyListener::MESSAGE_RECEIVED, | |
481 get_proxy_listener()->get_reason()); | |
482 ASSERT_EQ(result_listener.get_result(), RESULT_SUCCESS); | |
483 | |
484 CommonTearDown(); | |
485 } | |
486 | |
487 // An unprivileged process makes a shared memory region and sends it to the | |
488 // privileged process. | |
489 TEST_F(IPCAttachmentBrokerPrivilegedWinTest, SendSharedMemoryHandle) { | |
490 Init("SendSharedMemoryHandle"); | |
491 | |
492 CommonSetUp(); | |
493 ResultListener result_listener; | |
494 get_proxy_listener()->set_listener(&result_listener); | |
495 | |
496 std::unique_ptr<base::SharedMemory> shared_memory(new base::SharedMemory); | |
497 shared_memory->CreateAndMapAnonymous(kSharedMemorySize); | |
498 memcpy(shared_memory->memory(), kDataBuffer, strlen(kDataBuffer)); | |
499 sender()->Send(new TestSharedMemoryHandleMsg1(shared_memory->handle())); | |
500 base::RunLoop().Run(); | |
501 | |
502 // Check the result. | |
503 ASSERT_EQ(ProxyListener::MESSAGE_RECEIVED, | |
504 get_proxy_listener()->get_reason()); | |
505 ASSERT_EQ(result_listener.get_result(), RESULT_SUCCESS); | |
506 | |
507 CommonTearDown(); | |
508 } | |
509 | |
510 using OnMessageReceivedCallback = void (*)(IPC::Sender* sender, | |
511 const IPC::Message& message); | |
512 | |
513 int CommonPrivilegedProcessMain(OnMessageReceivedCallback callback, | |
514 const char* channel_name) { | |
515 LOG(INFO) << "Privileged process start."; | |
516 base::MessageLoopForIO main_message_loop; | |
517 ProxyListener listener; | |
518 | |
519 // Set up IPC channel. | |
520 IPC::AttachmentBrokerPrivilegedWin broker; | |
521 std::unique_ptr<IPC::Channel> channel(IPC::Channel::CreateClient( | |
522 IPCTestBase::GetChannelName(channel_name), &listener)); | |
523 broker.RegisterCommunicationChannel(channel.get(), nullptr); | |
524 CHECK(channel->Connect()); | |
525 | |
526 while (true) { | |
527 LOG(INFO) << "Privileged process spinning run loop."; | |
528 base::RunLoop().Run(); | |
529 ProxyListener::Reason reason = listener.get_reason(); | |
530 if (reason == ProxyListener::CHANNEL_ERROR) | |
531 break; | |
532 | |
533 while (listener.has_message()) { | |
534 LOG(INFO) << "Privileged process running callback."; | |
535 callback(channel.get(), listener.get_first_message()); | |
536 LOG(INFO) << "Privileged process finishing callback."; | |
537 listener.pop_first_message(); | |
538 } | |
539 } | |
540 | |
541 LOG(INFO) << "Privileged process end."; | |
542 return 0; | |
543 } | |
544 | |
545 void SendHandleCallback(IPC::Sender* sender, const IPC::Message& message) { | |
546 bool success = CheckContentsOfTestMessage(message); | |
547 SendControlMessage(sender, success); | |
548 } | |
549 | |
550 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendHandle) { | |
551 return CommonPrivilegedProcessMain(&SendHandleCallback, "SendHandle"); | |
552 } | |
553 | |
554 void SendHandleWithoutPermissionsCallback(IPC::Sender* sender, | |
555 const IPC::Message& message) { | |
556 ScopedHandle h(GetHandleFromTestHandleWinMsg(message)); | |
557 if (h.Get() != nullptr) { | |
558 SetFilePointer(h.Get(), 0, nullptr, FILE_BEGIN); | |
559 | |
560 char buffer[100]; | |
561 DWORD bytes_read; | |
562 BOOL success = | |
563 ::ReadFile(h.Get(), buffer, static_cast<DWORD>(strlen(kDataBuffer)), | |
564 &bytes_read, nullptr); | |
565 if (!success && GetLastError() == ERROR_ACCESS_DENIED) { | |
566 SendControlMessage(sender, true); | |
567 return; | |
568 } | |
569 } | |
570 | |
571 SendControlMessage(sender, false); | |
572 } | |
573 | |
574 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendHandleWithoutPermissions) { | |
575 return CommonPrivilegedProcessMain(&SendHandleWithoutPermissionsCallback, | |
576 "SendHandleWithoutPermissions"); | |
577 } | |
578 | |
579 void SendHandleToSelfCallback(IPC::Sender* sender, const IPC::Message&) { | |
580 // Do nothing special. The default behavior already runs the | |
581 // AttachmentBrokerPrivilegedWin. | |
582 } | |
583 | |
584 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendHandleToSelf) { | |
585 return CommonPrivilegedProcessMain(&SendHandleToSelfCallback, | |
586 "SendHandleToSelf"); | |
587 } | |
588 | |
589 void SendTwoHandlesCallback(IPC::Sender* sender, const IPC::Message& message) { | |
590 // Check for two handles. | |
591 HANDLE h1, h2; | |
592 EXPECT_TRUE(GetHandleFromTestTwoHandleWinMsg(message, &h1, &h2)); | |
593 if (h1 == nullptr || h2 == nullptr) { | |
594 SendControlMessage(sender, false); | |
595 return; | |
596 } | |
597 | |
598 // Check that their contents are correct. | |
599 std::string contents1 = ReadFromFile(h1); | |
600 std::string contents2 = ReadFromFile(h2); | |
601 if (contents1 != std::string(kDataBuffer) || | |
602 contents2 != std::string(kDataBuffer)) { | |
603 SendControlMessage(sender, false); | |
604 return; | |
605 } | |
606 | |
607 // Check that the handles point to the same file. | |
608 const char text[] = "katy perry"; | |
609 DWORD bytes_written = 0; | |
610 SetFilePointer(h1, 0, nullptr, FILE_BEGIN); | |
611 BOOL success = ::WriteFile(h1, text, static_cast<DWORD>(strlen(text)), | |
612 &bytes_written, nullptr); | |
613 if (!success) { | |
614 SendControlMessage(sender, false); | |
615 return; | |
616 } | |
617 | |
618 SetFilePointer(h2, 0, nullptr, FILE_BEGIN); | |
619 char buffer[100]; | |
620 DWORD bytes_read; | |
621 success = ::ReadFile(h2, buffer, static_cast<DWORD>(strlen(text)), | |
622 &bytes_read, nullptr); | |
623 if (!success) { | |
624 SendControlMessage(sender, false); | |
625 return; | |
626 } | |
627 success = std::string(buffer, bytes_read) == std::string(text); | |
628 SendControlMessage(sender, success); | |
629 } | |
630 | |
631 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendTwoHandles) { | |
632 return CommonPrivilegedProcessMain(&SendTwoHandlesCallback, "SendTwoHandles"); | |
633 } | |
634 | |
635 void SendHandleTwiceCallback(IPC::Sender* sender, const IPC::Message& message) { | |
636 // We expect the same message twice. | |
637 static int i = 0; | |
638 static bool success = true; | |
639 success &= CheckContentsOfTestMessage(message); | |
640 if (i == 0) { | |
641 LOG(INFO) << "Received first message."; | |
642 ++i; | |
643 } else { | |
644 LOG(INFO) << "Received second message."; | |
645 SendControlMessage(sender, success); | |
646 } | |
647 } | |
648 | |
649 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendHandleTwice) { | |
650 return CommonPrivilegedProcessMain(&SendHandleTwiceCallback, | |
651 "SendHandleTwice"); | |
652 } | |
653 | |
654 void SendSharedMemoryHandleCallback(IPC::Sender* sender, | |
655 const IPC::Message& message) { | |
656 std::unique_ptr<base::SharedMemory> shared_memory = | |
657 GetSharedMemoryFromSharedMemoryHandleMsg1(message, kSharedMemorySize); | |
658 bool success = | |
659 memcmp(shared_memory->memory(), kDataBuffer, strlen(kDataBuffer)) == 0; | |
660 SendControlMessage(sender, success); | |
661 } | |
662 | |
663 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendSharedMemoryHandle) { | |
664 return CommonPrivilegedProcessMain(&SendSharedMemoryHandleCallback, | |
665 "SendSharedMemoryHandle"); | |
666 } | |
667 | |
668 } // namespace | |
OLD | NEW |