OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <mach/mach.h> | 5 #include <mach/mach.h> |
6 #include <mach/mach_vm.h> | 6 #include <mach/mach_vm.h> |
7 #include <servers/bootstrap.h> | 7 #include <servers/bootstrap.h> |
8 #include <stddef.h> | 8 #include <stddef.h> |
9 #include <stdint.h> | 9 #include <stdint.h> |
10 | 10 |
11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
12 #include "base/mac/mac_util.h" | 12 #include "base/mac/mac_util.h" |
13 #include "base/mac/mach_logging.h" | 13 #include "base/mac/mach_logging.h" |
14 #include "base/mac/scoped_mach_port.h" | 14 #include "base/mac/scoped_mach_port.h" |
15 #include "base/macros.h" | 15 #include "base/macros.h" |
16 #include "base/memory/shared_memory.h" | 16 #include "base/memory/shared_memory.h" |
17 #include "base/process/process_handle.h" | 17 #include "base/process/process_handle.h" |
18 #include "base/rand_util.h" | 18 #include "base/rand_util.h" |
19 #include "base/strings/stringprintf.h" | 19 #include "base/strings/stringprintf.h" |
20 #include "base/sys_info.h" | 20 #include "base/sys_info.h" |
21 #include "base/test/multiprocess_test.h" | 21 #include "base/test/multiprocess_test.h" |
22 #include "base/test/test_timeouts.h" | 22 #include "base/test/test_timeouts.h" |
| 23 #include "base/unguessable_token.h" |
23 #include "testing/multiprocess_func_list.h" | 24 #include "testing/multiprocess_func_list.h" |
24 | 25 |
25 namespace base { | 26 namespace base { |
26 | 27 |
27 namespace { | 28 namespace { |
28 | 29 |
29 // Gets the current and maximum protection levels of the memory region. | 30 // Gets the current and maximum protection levels of the memory region. |
30 // Returns whether the operation was successful. | 31 // Returns whether the operation was successful. |
31 // |current| and |max| are output variables only populated on success. | 32 // |current| and |max| are output variables only populated on success. |
32 bool GetProtections(void* address, size_t size, int* current, int* max) { | 33 bool GetProtections(void* address, size_t size, int* current, int* max) { |
(...skipping 15 matching lines...) Expand all Loading... |
48 return false; | 49 return false; |
49 } | 50 } |
50 | 51 |
51 *current = basic_info.protection; | 52 *current = basic_info.protection; |
52 *max = basic_info.max_protection; | 53 *max = basic_info.max_protection; |
53 return true; | 54 return true; |
54 } | 55 } |
55 | 56 |
56 // Creates a new SharedMemory with the given |size|, filled with 'a'. | 57 // Creates a new SharedMemory with the given |size|, filled with 'a'. |
57 std::unique_ptr<SharedMemory> CreateSharedMemory(int size) { | 58 std::unique_ptr<SharedMemory> CreateSharedMemory(int size) { |
58 SharedMemoryHandle shm(size); | 59 SharedMemoryHandle shm(size, UnguessableToken::Create()); |
59 if (!shm.IsValid()) { | 60 if (!shm.IsValid()) { |
60 LOG(ERROR) << "Failed to make SharedMemoryHandle"; | 61 LOG(ERROR) << "Failed to make SharedMemoryHandle"; |
61 return nullptr; | 62 return nullptr; |
62 } | 63 } |
63 std::unique_ptr<SharedMemory> shared_memory(new SharedMemory(shm, false)); | 64 std::unique_ptr<SharedMemory> shared_memory(new SharedMemory(shm, false)); |
64 shared_memory->Map(size); | 65 shared_memory->Map(size); |
65 memset(shared_memory->memory(), 'a', size); | 66 memset(shared_memory->memory(), 'a', size); |
66 return shared_memory; | 67 return shared_memory; |
67 } | 68 } |
68 | 69 |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
240 ASSERT_TRUE(spawn_child_.process.WaitForExitWithTimeout( | 241 ASSERT_TRUE(spawn_child_.process.WaitForExitWithTimeout( |
241 TestTimeouts::action_timeout(), &rv)); | 242 TestTimeouts::action_timeout(), &rv)); |
242 EXPECT_EQ(0, rv); | 243 EXPECT_EQ(0, rv); |
243 } | 244 } |
244 | 245 |
245 MULTIPROCESS_TEST_MAIN(MachBasedSharedMemoryClient) { | 246 MULTIPROCESS_TEST_MAIN(MachBasedSharedMemoryClient) { |
246 mac::ScopedMachReceiveRight client_port(CommonChildProcessSetUp()); | 247 mac::ScopedMachReceiveRight client_port(CommonChildProcessSetUp()); |
247 // The next mach port should be for a memory object. | 248 // The next mach port should be for a memory object. |
248 mach_port_t memory_object = ReceiveMachPort(client_port.get()); | 249 mach_port_t memory_object = ReceiveMachPort(client_port.get()); |
249 SharedMemoryHandle shm(memory_object, | 250 SharedMemoryHandle shm(memory_object, |
250 SharedMemoryMacMultiProcessTest::s_memory_size); | 251 SharedMemoryMacMultiProcessTest::s_memory_size, |
| 252 UnguessableToken::Create()); |
251 SharedMemory shared_memory(shm, false); | 253 SharedMemory shared_memory(shm, false); |
252 shared_memory.Map(SharedMemoryMacMultiProcessTest::s_memory_size); | 254 shared_memory.Map(SharedMemoryMacMultiProcessTest::s_memory_size); |
253 const char* start = static_cast<const char*>(shared_memory.memory()); | 255 const char* start = static_cast<const char*>(shared_memory.memory()); |
254 for (int i = 0; i < SharedMemoryMacMultiProcessTest::s_memory_size; ++i) { | 256 for (int i = 0; i < SharedMemoryMacMultiProcessTest::s_memory_size; ++i) { |
255 DCHECK_EQ(start[i], 'a'); | 257 DCHECK_EQ(start[i], 'a'); |
256 } | 258 } |
257 return 0; | 259 return 0; |
258 } | 260 } |
259 | 261 |
260 // Tests that mapping shared memory with an offset works correctly. | 262 // Tests that mapping shared memory with an offset works correctly. |
261 TEST_F(SharedMemoryMacMultiProcessTest, MachBasedSharedMemoryWithOffset) { | 263 TEST_F(SharedMemoryMacMultiProcessTest, MachBasedSharedMemoryWithOffset) { |
262 SetUpChild("MachBasedSharedMemoryWithOffsetClient"); | 264 SetUpChild("MachBasedSharedMemoryWithOffsetClient"); |
263 | 265 |
264 SharedMemoryHandle shm(s_memory_size); | 266 SharedMemoryHandle shm(s_memory_size, UnguessableToken::Create()); |
265 ASSERT_TRUE(shm.IsValid()); | 267 ASSERT_TRUE(shm.IsValid()); |
266 SharedMemory shared_memory(shm, false); | 268 SharedMemory shared_memory(shm, false); |
267 shared_memory.Map(s_memory_size); | 269 shared_memory.Map(s_memory_size); |
268 | 270 |
269 size_t page_size = SysInfo::VMAllocationGranularity(); | 271 size_t page_size = SysInfo::VMAllocationGranularity(); |
270 char* start = static_cast<char*>(shared_memory.memory()); | 272 char* start = static_cast<char*>(shared_memory.memory()); |
271 memset(start, 'a', page_size); | 273 memset(start, 'a', page_size); |
272 memset(start + page_size, 'b', page_size); | 274 memset(start + page_size, 'b', page_size); |
273 memset(start + 2 * page_size, 'c', page_size); | 275 memset(start + 2 * page_size, 'c', page_size); |
274 | 276 |
275 // Send the underlying memory object to the client process. | 277 // Send the underlying memory object to the client process. |
276 SendMachPort( | 278 SendMachPort( |
277 client_port_.get(), shm.GetMemoryObject(), MACH_MSG_TYPE_COPY_SEND); | 279 client_port_.get(), shm.GetMemoryObject(), MACH_MSG_TYPE_COPY_SEND); |
278 int rv = -1; | 280 int rv = -1; |
279 ASSERT_TRUE(spawn_child_.process.WaitForExitWithTimeout( | 281 ASSERT_TRUE(spawn_child_.process.WaitForExitWithTimeout( |
280 TestTimeouts::action_timeout(), &rv)); | 282 TestTimeouts::action_timeout(), &rv)); |
281 EXPECT_EQ(0, rv); | 283 EXPECT_EQ(0, rv); |
282 } | 284 } |
283 | 285 |
284 MULTIPROCESS_TEST_MAIN(MachBasedSharedMemoryWithOffsetClient) { | 286 MULTIPROCESS_TEST_MAIN(MachBasedSharedMemoryWithOffsetClient) { |
285 mac::ScopedMachReceiveRight client_port(CommonChildProcessSetUp()); | 287 mac::ScopedMachReceiveRight client_port(CommonChildProcessSetUp()); |
286 // The next mach port should be for a memory object. | 288 // The next mach port should be for a memory object. |
287 mach_port_t memory_object = ReceiveMachPort(client_port.get()); | 289 mach_port_t memory_object = ReceiveMachPort(client_port.get()); |
288 SharedMemoryHandle shm(memory_object, | 290 SharedMemoryHandle shm(memory_object, |
289 SharedMemoryMacMultiProcessTest::s_memory_size); | 291 SharedMemoryMacMultiProcessTest::s_memory_size, |
| 292 UnguessableToken::Create()); |
290 SharedMemory shared_memory(shm, false); | 293 SharedMemory shared_memory(shm, false); |
291 size_t page_size = SysInfo::VMAllocationGranularity(); | 294 size_t page_size = SysInfo::VMAllocationGranularity(); |
292 shared_memory.MapAt(page_size, 2 * page_size); | 295 shared_memory.MapAt(page_size, 2 * page_size); |
293 const char* start = static_cast<const char*>(shared_memory.memory()); | 296 const char* start = static_cast<const char*>(shared_memory.memory()); |
294 for (size_t i = 0; i < page_size; ++i) { | 297 for (size_t i = 0; i < page_size; ++i) { |
295 DCHECK_EQ(start[i], 'b'); | 298 DCHECK_EQ(start[i], 'b'); |
296 } | 299 } |
297 for (size_t i = page_size; i < 2 * page_size; ++i) { | 300 for (size_t i = page_size; i < 2 * page_size; ++i) { |
298 DCHECK_EQ(start[i], 'c'); | 301 DCHECK_EQ(start[i], 'c'); |
299 } | 302 } |
300 return 0; | 303 return 0; |
301 } | 304 } |
302 | 305 |
303 // Tests that duplication and closing has the right effect on Mach reference | 306 // Tests that duplication and closing has the right effect on Mach reference |
304 // counts. | 307 // counts. |
305 TEST_F(SharedMemoryMacMultiProcessTest, MachDuplicateAndClose) { | 308 TEST_F(SharedMemoryMacMultiProcessTest, MachDuplicateAndClose) { |
306 mach_msg_type_number_t active_name_count = GetActiveNameCount(); | 309 mach_msg_type_number_t active_name_count = GetActiveNameCount(); |
307 | 310 |
308 // Making a new SharedMemoryHandle increments the name count. | 311 // Making a new SharedMemoryHandle increments the name count. |
309 SharedMemoryHandle shm(s_memory_size); | 312 SharedMemoryHandle shm(s_memory_size, UnguessableToken::Create()); |
310 ASSERT_TRUE(shm.IsValid()); | 313 ASSERT_TRUE(shm.IsValid()); |
311 EXPECT_EQ(active_name_count + 1, GetActiveNameCount()); | 314 EXPECT_EQ(active_name_count + 1, GetActiveNameCount()); |
312 | 315 |
313 // Duplicating the SharedMemoryHandle increments the ref count, but doesn't | 316 // Duplicating the SharedMemoryHandle increments the ref count, but doesn't |
314 // make a new name. | 317 // make a new name. |
315 shm.Duplicate(); | 318 shm.Duplicate(); |
316 EXPECT_EQ(active_name_count + 1, GetActiveNameCount()); | 319 EXPECT_EQ(active_name_count + 1, GetActiveNameCount()); |
317 | 320 |
318 // Closing the SharedMemoryHandle decrements the ref count. The first time has | 321 // Closing the SharedMemoryHandle decrements the ref count. The first time has |
319 // no effect. | 322 // no effect. |
(...skipping 18 matching lines...) Expand all Loading... |
338 EXPECT_EQ(active_name_count, GetActiveNameCount()); | 341 EXPECT_EQ(active_name_count, GetActiveNameCount()); |
339 } | 342 } |
340 | 343 |
341 // Tests that passing a SharedMemoryHandle to a SharedMemory object also passes | 344 // Tests that passing a SharedMemoryHandle to a SharedMemory object also passes |
342 // ownership, and that destroying the SharedMemory closes the SharedMemoryHandle | 345 // ownership, and that destroying the SharedMemory closes the SharedMemoryHandle |
343 // as well. | 346 // as well. |
344 TEST_F(SharedMemoryMacMultiProcessTest, MachSharedMemoryTakesOwnership) { | 347 TEST_F(SharedMemoryMacMultiProcessTest, MachSharedMemoryTakesOwnership) { |
345 mach_msg_type_number_t active_name_count = GetActiveNameCount(); | 348 mach_msg_type_number_t active_name_count = GetActiveNameCount(); |
346 | 349 |
347 // Making a new SharedMemoryHandle increments the name count. | 350 // Making a new SharedMemoryHandle increments the name count. |
348 SharedMemoryHandle shm(s_memory_size); | 351 SharedMemoryHandle shm(s_memory_size, UnguessableToken::Create()); |
349 ASSERT_TRUE(shm.IsValid()); | 352 ASSERT_TRUE(shm.IsValid()); |
350 EXPECT_EQ(active_name_count + 1, GetActiveNameCount()); | 353 EXPECT_EQ(active_name_count + 1, GetActiveNameCount()); |
351 | 354 |
352 // Name count doesn't change when mapping the memory. | 355 // Name count doesn't change when mapping the memory. |
353 std::unique_ptr<SharedMemory> shared_memory(new SharedMemory(shm, false)); | 356 std::unique_ptr<SharedMemory> shared_memory(new SharedMemory(shm, false)); |
354 shared_memory->Map(s_memory_size); | 357 shared_memory->Map(s_memory_size); |
355 EXPECT_EQ(active_name_count + 1, GetActiveNameCount()); | 358 EXPECT_EQ(active_name_count + 1, GetActiveNameCount()); |
356 | 359 |
357 // Destroying the SharedMemory object frees the resource. | 360 // Destroying the SharedMemory object frees the resource. |
358 shared_memory.reset(); | 361 shared_memory.reset(); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
401 int current_prot, max_prot; | 404 int current_prot, max_prot; |
402 ASSERT_TRUE(GetProtections(shared_memory->memory(), | 405 ASSERT_TRUE(GetProtections(shared_memory->memory(), |
403 shared_memory->mapped_size(), ¤t_prot, | 406 shared_memory->mapped_size(), ¤t_prot, |
404 &max_prot)); | 407 &max_prot)); |
405 ASSERT_EQ(VM_PROT_READ | VM_PROT_WRITE, current_prot); | 408 ASSERT_EQ(VM_PROT_READ | VM_PROT_WRITE, current_prot); |
406 ASSERT_EQ(VM_PROT_READ | VM_PROT_WRITE, max_prot); | 409 ASSERT_EQ(VM_PROT_READ | VM_PROT_WRITE, max_prot); |
407 | 410 |
408 // Make a new memory object. | 411 // Make a new memory object. |
409 SharedMemoryHandle shm2 = shared_memory->GetReadOnlyHandle(); | 412 SharedMemoryHandle shm2 = shared_memory->GetReadOnlyHandle(); |
410 ASSERT_TRUE(shm2.IsValid()); | 413 ASSERT_TRUE(shm2.IsValid()); |
| 414 EXPECT_EQ(shared_memory->handle().GetGUID(), shm2.GetGUID()); |
411 | 415 |
412 // Mapping with |readonly| set to |false| should fail. | 416 // Mapping with |readonly| set to |false| should fail. |
413 SharedMemory shared_memory2(shm2, false); | 417 SharedMemory shared_memory2(shm2, false); |
414 shared_memory2.Map(s_memory_size); | 418 shared_memory2.Map(s_memory_size); |
415 ASSERT_EQ(nullptr, shared_memory2.memory()); | 419 ASSERT_EQ(nullptr, shared_memory2.memory()); |
416 | 420 |
417 // Now trying mapping with |readonly| set to |true|. | 421 // Now trying mapping with |readonly| set to |true|. |
418 SharedMemory shared_memory3(shm2.Duplicate(), true); | 422 SharedMemory shared_memory3(shm2.Duplicate(), true); |
419 shared_memory3.Map(s_memory_size); | 423 shared_memory3.Map(s_memory_size); |
420 ASSERT_NE(nullptr, shared_memory3.memory()); | 424 ASSERT_NE(nullptr, shared_memory3.memory()); |
(...skipping 23 matching lines...) Expand all Loading... |
444 | 448 |
445 // Intentionally map with |readonly| set to |false|. | 449 // Intentionally map with |readonly| set to |false|. |
446 SharedMemory shared_memory2(shm2, false); | 450 SharedMemory shared_memory2(shm2, false); |
447 shared_memory2.Map(s_memory_size); | 451 shared_memory2.Map(s_memory_size); |
448 } | 452 } |
449 | 453 |
450 EXPECT_EQ(active_name_count, GetActiveNameCount()); | 454 EXPECT_EQ(active_name_count, GetActiveNameCount()); |
451 } | 455 } |
452 | 456 |
453 } // namespace base | 457 } // namespace base |
OLD | NEW |