| 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 "ipc/attachment_broker_privileged_mac.h" | 5 #include "ipc/attachment_broker_privileged_mac.h" |
| 6 | 6 |
| 7 #include <mach/mach.h> | 7 #include <mach/mach.h> |
| 8 #include <mach/mach_vm.h> | 8 #include <mach/mach_vm.h> |
| 9 | 9 |
| 10 #include <map> | 10 #include <map> |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 82 cmd_line.GetSwitchValueASCII(g_service_switch_name); | 82 cmd_line.GetSwitchValueASCII(g_service_switch_name); |
| 83 base::mac::ScopedMachSendRight server_port( | 83 base::mac::ScopedMachSendRight server_port( |
| 84 LookupServer(service_name.c_str())); | 84 LookupServer(service_name.c_str())); |
| 85 base::mac::ScopedMachReceiveRight client_port(MakeReceivingPort()); | 85 base::mac::ScopedMachReceiveRight client_port(MakeReceivingPort()); |
| 86 | 86 |
| 87 // |server_port| is a newly allocated right which will be deallocated once | 87 // |server_port| is a newly allocated right which will be deallocated once |
| 88 // this method returns. | 88 // this method returns. |
| 89 *original_name_count = GetActiveNameCount() - 1; | 89 *original_name_count = GetActiveNameCount() - 1; |
| 90 | 90 |
| 91 // Send the port that this process is listening on to the server. | 91 // Send the port that this process is listening on to the server. |
| 92 SendMachPort(server_port, client_port, MACH_MSG_TYPE_MAKE_SEND); | 92 SendMachPort(server_port.get(), client_port.get(), MACH_MSG_TYPE_MAKE_SEND); |
| 93 | 93 |
| 94 // Send the task port for this process. | 94 // Send the task port for this process. |
| 95 SendMachPort(server_port, mach_task_self(), MACH_MSG_TYPE_COPY_SEND); | 95 SendMachPort(server_port.get(), mach_task_self(), MACH_MSG_TYPE_COPY_SEND); |
| 96 return client_port; | 96 return client_port; |
| 97 } | 97 } |
| 98 | 98 |
| 99 // Creates a new shared memory region populated with 'a'. | 99 // Creates a new shared memory region populated with 'a'. |
| 100 scoped_ptr<base::SharedMemory> CreateAndPopulateSharedMemoryHandle( | 100 scoped_ptr<base::SharedMemory> CreateAndPopulateSharedMemoryHandle( |
| 101 size_t size) { | 101 size_t size) { |
| 102 base::SharedMemoryHandle shm(size); | 102 base::SharedMemoryHandle shm(size); |
| 103 scoped_ptr<base::SharedMemory> shared_memory( | 103 scoped_ptr<base::SharedMemory> shared_memory( |
| 104 new base::SharedMemory(shm, false)); | 104 new base::SharedMemory(shm, false)); |
| 105 shared_memory->Map(size); | 105 shared_memory->Map(size); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 131 command_line.AppendSwitchASCII(g_service_switch_name, service_name_); | 131 command_line.AppendSwitchASCII(g_service_switch_name, service_name_); |
| 132 return command_line; | 132 return command_line; |
| 133 } | 133 } |
| 134 | 134 |
| 135 void SetUpChild(const std::string& name) { | 135 void SetUpChild(const std::string& name) { |
| 136 // Make a random service name so that this test doesn't conflict with other | 136 // Make a random service name so that this test doesn't conflict with other |
| 137 // similar tests. | 137 // similar tests. |
| 138 service_name_ = CreateRandomServiceName(); | 138 service_name_ = CreateRandomServiceName(); |
| 139 server_port_.reset(BecomeMachServer(service_name_.c_str()).release()); | 139 server_port_.reset(BecomeMachServer(service_name_.c_str()).release()); |
| 140 child_process_ = SpawnChild(name); | 140 child_process_ = SpawnChild(name); |
| 141 client_port_.reset(ReceiveMachPort(server_port_).release()); | 141 client_port_.reset(ReceiveMachPort(server_port_.get()).release()); |
| 142 client_task_port_.reset(ReceiveMachPort(server_port_).release()); | 142 client_task_port_.reset(ReceiveMachPort(server_port_.get()).release()); |
| 143 } | 143 } |
| 144 | 144 |
| 145 static const int s_memory_size = 99999; | 145 static const int s_memory_size = 99999; |
| 146 | 146 |
| 147 protected: | 147 protected: |
| 148 std::string service_name_; | 148 std::string service_name_; |
| 149 | 149 |
| 150 // A port on which the main process listens for mach messages from the child | 150 // A port on which the main process listens for mach messages from the child |
| 151 // process. | 151 // process. |
| 152 base::mac::ScopedMachReceiveRight server_port_; | 152 base::mac::ScopedMachReceiveRight server_port_; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 172 // Create some shared memory. | 172 // Create some shared memory. |
| 173 scoped_ptr<base::SharedMemory> shared_memory = | 173 scoped_ptr<base::SharedMemory> shared_memory = |
| 174 CreateAndPopulateSharedMemoryHandle(s_memory_size); | 174 CreateAndPopulateSharedMemoryHandle(s_memory_size); |
| 175 ASSERT_TRUE(shared_memory->handle().IsValid()); | 175 ASSERT_TRUE(shared_memory->handle().IsValid()); |
| 176 | 176 |
| 177 // Insert the memory object into the destination task, via an intermediate | 177 // Insert the memory object into the destination task, via an intermediate |
| 178 // port. | 178 // port. |
| 179 IncrementMachRefCount(shared_memory->handle().GetMemoryObject(), | 179 IncrementMachRefCount(shared_memory->handle().GetMemoryObject(), |
| 180 MACH_PORT_RIGHT_SEND); | 180 MACH_PORT_RIGHT_SEND); |
| 181 mach_port_name_t inserted_memory_object = broker.CreateIntermediateMachPort( | 181 mach_port_name_t inserted_memory_object = broker.CreateIntermediateMachPort( |
| 182 client_task_port_, base::mac::ScopedMachSendRight( | 182 client_task_port_.get(), base::mac::ScopedMachSendRight( |
| 183 shared_memory->handle().GetMemoryObject())); | 183 shared_memory->handle().GetMemoryObject())); |
| 184 EXPECT_NE(inserted_memory_object, | 184 EXPECT_NE(inserted_memory_object, |
| 185 static_cast<mach_port_name_t>(MACH_PORT_NULL)); | 185 static_cast<mach_port_name_t>(MACH_PORT_NULL)); |
| 186 SendUInt32(client_port_, inserted_memory_object); | 186 SendUInt32(client_port_.get(), inserted_memory_object); |
| 187 | 187 |
| 188 // Check that no names have been leaked. | 188 // Check that no names have been leaked. |
| 189 shared_memory.reset(); | 189 shared_memory.reset(); |
| 190 EXPECT_EQ(original_name_count, GetActiveNameCount()); | 190 EXPECT_EQ(original_name_count, GetActiveNameCount()); |
| 191 | 191 |
| 192 int rv = -1; | 192 int rv = -1; |
| 193 ASSERT_TRUE(child_process_.WaitForExitWithTimeout( | 193 ASSERT_TRUE(child_process_.WaitForExitWithTimeout( |
| 194 TestTimeouts::action_timeout(), &rv)); | 194 TestTimeouts::action_timeout(), &rv)); |
| 195 EXPECT_EQ(0, rv); | 195 EXPECT_EQ(0, rv); |
| 196 } | 196 } |
| 197 | 197 |
| 198 MULTIPROCESS_TEST_MAIN(InsertRightClient) { | 198 MULTIPROCESS_TEST_MAIN(InsertRightClient) { |
| 199 mach_msg_type_number_t original_name_count = 0; | 199 mach_msg_type_number_t original_name_count = 0; |
| 200 base::mac::ScopedMachReceiveRight client_port( | 200 base::mac::ScopedMachReceiveRight client_port( |
| 201 CommonChildProcessSetUp(&original_name_count).release()); | 201 CommonChildProcessSetUp(&original_name_count).release()); |
| 202 base::mac::ScopedMachReceiveRight inserted_port(ReceiveUInt32(client_port)); | 202 base::mac::ScopedMachReceiveRight inserted_port( |
| 203 base::mac::ScopedMachSendRight memory_object(ReceiveMachPort(inserted_port)); | 203 ReceiveUInt32(client_port.get())); |
| 204 base::mac::ScopedMachSendRight memory_object( |
| 205 ReceiveMachPort(inserted_port.get())); |
| 204 inserted_port.reset(); | 206 inserted_port.reset(); |
| 205 | 207 |
| 206 // The server should have inserted a right into this process. | 208 // The server should have inserted a right into this process. |
| 207 EXPECT_EQ(original_name_count + 1, GetActiveNameCount()); | 209 EXPECT_EQ(original_name_count + 1, GetActiveNameCount()); |
| 208 | 210 |
| 209 // Map the memory object and check its contents. | 211 // Map the memory object and check its contents. |
| 210 scoped_ptr<base::SharedMemory> shared_memory(MapMemoryObject( | 212 scoped_ptr<base::SharedMemory> shared_memory(MapMemoryObject( |
| 211 memory_object.release(), | 213 memory_object.release(), |
| 212 AttachmentBrokerPrivilegedMacMultiProcessTest::s_memory_size)); | 214 AttachmentBrokerPrivilegedMacMultiProcessTest::s_memory_size)); |
| 213 const char* start = static_cast<const char*>(shared_memory->memory()); | 215 const char* start = static_cast<const char*>(shared_memory->memory()); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 234 scoped_ptr<base::SharedMemory> shared_memory = | 236 scoped_ptr<base::SharedMemory> shared_memory = |
| 235 CreateAndPopulateSharedMemoryHandle(s_memory_size); | 237 CreateAndPopulateSharedMemoryHandle(s_memory_size); |
| 236 ASSERT_TRUE(shared_memory->handle().IsValid()); | 238 ASSERT_TRUE(shared_memory->handle().IsValid()); |
| 237 | 239 |
| 238 // Insert the memory object into the destination task, via an intermediate | 240 // Insert the memory object into the destination task, via an intermediate |
| 239 // port, twice. | 241 // port, twice. |
| 240 for (int i = 0; i < 2; ++i) { | 242 for (int i = 0; i < 2; ++i) { |
| 241 IncrementMachRefCount(shared_memory->handle().GetMemoryObject(), | 243 IncrementMachRefCount(shared_memory->handle().GetMemoryObject(), |
| 242 MACH_PORT_RIGHT_SEND); | 244 MACH_PORT_RIGHT_SEND); |
| 243 mach_port_name_t inserted_memory_object = broker.CreateIntermediateMachPort( | 245 mach_port_name_t inserted_memory_object = broker.CreateIntermediateMachPort( |
| 244 client_task_port_, base::mac::ScopedMachSendRight( | 246 client_task_port_.get(), |
| 245 shared_memory->handle().GetMemoryObject())); | 247 base::mac::ScopedMachSendRight( |
| 248 shared_memory->handle().GetMemoryObject())); |
| 246 EXPECT_NE(inserted_memory_object, | 249 EXPECT_NE(inserted_memory_object, |
| 247 static_cast<mach_port_name_t>(MACH_PORT_NULL)); | 250 static_cast<mach_port_name_t>(MACH_PORT_NULL)); |
| 248 SendUInt32(client_port_, inserted_memory_object); | 251 SendUInt32(client_port_.get(), inserted_memory_object); |
| 249 } | 252 } |
| 250 | 253 |
| 251 // Check that no names have been leaked. | 254 // Check that no names have been leaked. |
| 252 shared_memory.reset(); | 255 shared_memory.reset(); |
| 253 EXPECT_EQ(original_name_count, GetActiveNameCount()); | 256 EXPECT_EQ(original_name_count, GetActiveNameCount()); |
| 254 | 257 |
| 255 int rv = -1; | 258 int rv = -1; |
| 256 ASSERT_TRUE(child_process_.WaitForExitWithTimeout( | 259 ASSERT_TRUE(child_process_.WaitForExitWithTimeout( |
| 257 TestTimeouts::action_timeout(), &rv)); | 260 TestTimeouts::action_timeout(), &rv)); |
| 258 EXPECT_EQ(0, rv); | 261 EXPECT_EQ(0, rv); |
| 259 } | 262 } |
| 260 | 263 |
| 261 MULTIPROCESS_TEST_MAIN(InsertSameRightTwiceClient) { | 264 MULTIPROCESS_TEST_MAIN(InsertSameRightTwiceClient) { |
| 262 mach_msg_type_number_t original_name_count = 0; | 265 mach_msg_type_number_t original_name_count = 0; |
| 263 base::mac::ScopedMachReceiveRight client_port( | 266 base::mac::ScopedMachReceiveRight client_port( |
| 264 CommonChildProcessSetUp(&original_name_count).release()); | 267 CommonChildProcessSetUp(&original_name_count).release()); |
| 265 | 268 |
| 266 // Receive two memory objects. | 269 // Receive two memory objects. |
| 267 base::mac::ScopedMachReceiveRight inserted_port(ReceiveUInt32(client_port)); | 270 base::mac::ScopedMachReceiveRight inserted_port( |
| 268 base::mac::ScopedMachReceiveRight inserted_port2(ReceiveUInt32(client_port)); | 271 ReceiveUInt32(client_port.get())); |
| 269 base::mac::ScopedMachSendRight memory_object(ReceiveMachPort(inserted_port)); | 272 base::mac::ScopedMachReceiveRight inserted_port2( |
| 273 ReceiveUInt32(client_port.get())); |
| 274 base::mac::ScopedMachSendRight memory_object( |
| 275 ReceiveMachPort(inserted_port.get())); |
| 270 base::mac::ScopedMachSendRight memory_object2( | 276 base::mac::ScopedMachSendRight memory_object2( |
| 271 ReceiveMachPort(inserted_port2)); | 277 ReceiveMachPort(inserted_port2.get())); |
| 272 inserted_port.reset(); | 278 inserted_port.reset(); |
| 273 inserted_port2.reset(); | 279 inserted_port2.reset(); |
| 274 | 280 |
| 275 // Both rights are for the same Mach port, so only one new name should appear. | 281 // Both rights are for the same Mach port, so only one new name should appear. |
| 276 EXPECT_EQ(original_name_count + 1, GetActiveNameCount()); | 282 EXPECT_EQ(original_name_count + 1, GetActiveNameCount()); |
| 277 | 283 |
| 278 // Map both memory objects and check their contents. | 284 // Map both memory objects and check their contents. |
| 279 scoped_ptr<base::SharedMemory> shared_memory(MapMemoryObject( | 285 scoped_ptr<base::SharedMemory> shared_memory(MapMemoryObject( |
| 280 memory_object.release(), | 286 memory_object.release(), |
| 281 AttachmentBrokerPrivilegedMacMultiProcessTest::s_memory_size)); | 287 AttachmentBrokerPrivilegedMacMultiProcessTest::s_memory_size)); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 322 // Create some shared memory. | 328 // Create some shared memory. |
| 323 scoped_ptr<base::SharedMemory> shared_memory = | 329 scoped_ptr<base::SharedMemory> shared_memory = |
| 324 CreateAndPopulateSharedMemoryHandle(s_memory_size); | 330 CreateAndPopulateSharedMemoryHandle(s_memory_size); |
| 325 ASSERT_TRUE(shared_memory->handle().IsValid()); | 331 ASSERT_TRUE(shared_memory->handle().IsValid()); |
| 326 | 332 |
| 327 // Insert the memory object into the destination task, via an intermediate | 333 // Insert the memory object into the destination task, via an intermediate |
| 328 // port. | 334 // port. |
| 329 IncrementMachRefCount(shared_memory->handle().GetMemoryObject(), | 335 IncrementMachRefCount(shared_memory->handle().GetMemoryObject(), |
| 330 MACH_PORT_RIGHT_SEND); | 336 MACH_PORT_RIGHT_SEND); |
| 331 mach_port_name_t inserted_memory_object = broker.CreateIntermediateMachPort( | 337 mach_port_name_t inserted_memory_object = broker.CreateIntermediateMachPort( |
| 332 client_task_port_, base::mac::ScopedMachSendRight( | 338 client_task_port_.get(), |
| 333 shared_memory->handle().GetMemoryObject())); | 339 base::mac::ScopedMachSendRight( |
| 340 shared_memory->handle().GetMemoryObject())); |
| 334 EXPECT_NE(inserted_memory_object, | 341 EXPECT_NE(inserted_memory_object, |
| 335 static_cast<mach_port_name_t>(MACH_PORT_NULL)); | 342 static_cast<mach_port_name_t>(MACH_PORT_NULL)); |
| 336 SendUInt32(client_port_, inserted_memory_object); | 343 SendUInt32(client_port_.get(), inserted_memory_object); |
| 337 } | 344 } |
| 338 | 345 |
| 339 // Check that no names have been leaked. | 346 // Check that no names have been leaked. |
| 340 EXPECT_EQ(original_name_count, GetActiveNameCount()); | 347 EXPECT_EQ(original_name_count, GetActiveNameCount()); |
| 341 | 348 |
| 342 int rv = -1; | 349 int rv = -1; |
| 343 ASSERT_TRUE(child_process_.WaitForExitWithTimeout( | 350 ASSERT_TRUE(child_process_.WaitForExitWithTimeout( |
| 344 TestTimeouts::action_timeout(), &rv)); | 351 TestTimeouts::action_timeout(), &rv)); |
| 345 EXPECT_EQ(0, rv); | 352 EXPECT_EQ(0, rv); |
| 346 } | 353 } |
| 347 | 354 |
| 348 MULTIPROCESS_TEST_MAIN(InsertTwoRightsClient) { | 355 MULTIPROCESS_TEST_MAIN(InsertTwoRightsClient) { |
| 349 mach_msg_type_number_t original_name_count = 0; | 356 mach_msg_type_number_t original_name_count = 0; |
| 350 base::mac::ScopedMachReceiveRight client_port( | 357 base::mac::ScopedMachReceiveRight client_port( |
| 351 CommonChildProcessSetUp(&original_name_count).release()); | 358 CommonChildProcessSetUp(&original_name_count).release()); |
| 352 | 359 |
| 353 // Receive two memory objects. | 360 // Receive two memory objects. |
| 354 base::mac::ScopedMachReceiveRight inserted_port(ReceiveUInt32(client_port)); | 361 base::mac::ScopedMachReceiveRight inserted_port( |
| 355 base::mac::ScopedMachReceiveRight inserted_port2(ReceiveUInt32(client_port)); | 362 ReceiveUInt32(client_port.get())); |
| 356 base::mac::ScopedMachSendRight memory_object(ReceiveMachPort(inserted_port)); | 363 base::mac::ScopedMachReceiveRight inserted_port2( |
| 364 ReceiveUInt32(client_port.get())); |
| 365 base::mac::ScopedMachSendRight memory_object( |
| 366 ReceiveMachPort(inserted_port.get())); |
| 357 base::mac::ScopedMachSendRight memory_object2( | 367 base::mac::ScopedMachSendRight memory_object2( |
| 358 ReceiveMachPort(inserted_port2)); | 368 ReceiveMachPort(inserted_port2.get())); |
| 359 inserted_port.reset(); | 369 inserted_port.reset(); |
| 360 inserted_port2.reset(); | 370 inserted_port2.reset(); |
| 361 | 371 |
| 362 // There should be two new names to reflect the two new shared memory regions. | 372 // There should be two new names to reflect the two new shared memory regions. |
| 363 EXPECT_EQ(original_name_count + 2, GetActiveNameCount()); | 373 EXPECT_EQ(original_name_count + 2, GetActiveNameCount()); |
| 364 | 374 |
| 365 // Map both memory objects and check their contents. | 375 // Map both memory objects and check their contents. |
| 366 scoped_ptr<base::SharedMemory> shared_memory(MapMemoryObject( | 376 scoped_ptr<base::SharedMemory> shared_memory(MapMemoryObject( |
| 367 memory_object.release(), | 377 memory_object.release(), |
| 368 AttachmentBrokerPrivilegedMacMultiProcessTest::s_memory_size)); | 378 AttachmentBrokerPrivilegedMacMultiProcessTest::s_memory_size)); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 388 // After releasing one shared memory region, the name count should decrement. | 398 // After releasing one shared memory region, the name count should decrement. |
| 389 shared_memory.reset(); | 399 shared_memory.reset(); |
| 390 EXPECT_EQ(original_name_count + 1, GetActiveNameCount()); | 400 EXPECT_EQ(original_name_count + 1, GetActiveNameCount()); |
| 391 shared_memory2.reset(); | 401 shared_memory2.reset(); |
| 392 EXPECT_EQ(original_name_count, GetActiveNameCount()); | 402 EXPECT_EQ(original_name_count, GetActiveNameCount()); |
| 393 | 403 |
| 394 return 0; | 404 return 0; |
| 395 } | 405 } |
| 396 | 406 |
| 397 } // namespace IPC | 407 } // namespace IPC |
| OLD | NEW |