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 "build/build_config.h" | 5 #include "build/build_config.h" |
6 | 6 |
7 #include <fcntl.h> | 7 #include <fcntl.h> |
8 #include <sys/mman.h> | 8 #include <sys/mman.h> |
9 | 9 |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
104 return false; | 104 return false; |
105 } | 105 } |
106 | 106 |
107 *handle1 = base::get<0>(p); | 107 *handle1 = base::get<0>(p); |
108 *handle2 = base::get<1>(p); | 108 *handle2 = base::get<1>(p); |
109 return true; | 109 return true; |
110 } | 110 } |
111 | 111 |
112 // Returns |nullptr| on error. | 112 // Returns |nullptr| on error. |
113 scoped_ptr<base::SharedMemory> MapSharedMemoryHandle( | 113 scoped_ptr<base::SharedMemory> MapSharedMemoryHandle( |
114 const base::SharedMemoryHandle& shm) { | 114 const base::SharedMemoryHandle& shm, |
| 115 bool read_only) { |
115 if (!shm.IsValid()) { | 116 if (!shm.IsValid()) { |
116 LOG(ERROR) << "Invalid SharedMemoryHandle"; | 117 LOG(ERROR) << "Invalid SharedMemoryHandle"; |
117 return nullptr; | 118 return nullptr; |
118 } | 119 } |
119 | 120 |
120 size_t size; | 121 size_t size; |
121 if (!shm.GetSize(&size)) { | 122 if (!shm.GetSize(&size)) { |
122 LOG(ERROR) << "Couldn't get size of SharedMemoryHandle"; | 123 LOG(ERROR) << "Couldn't get size of SharedMemoryHandle"; |
123 return nullptr; | 124 return nullptr; |
124 } | 125 } |
125 | 126 |
126 scoped_ptr<base::SharedMemory> shared_memory( | 127 scoped_ptr<base::SharedMemory> shared_memory( |
127 new base::SharedMemory(shm, false)); | 128 new base::SharedMemory(shm, read_only)); |
128 shared_memory->Map(size); | 129 shared_memory->Map(size); |
129 return shared_memory; | 130 return shared_memory; |
130 } | 131 } |
131 | 132 |
132 // This method maps the SharedMemoryHandle, checks the contents, and then | 133 // This method maps the SharedMemoryHandle, checks the contents, and then |
133 // consumes a reference to the underlying Mach port. | 134 // consumes a reference to the underlying Mach port. |
134 bool CheckContentsOfSharedMemoryHandle(const base::SharedMemoryHandle& shm, | 135 bool CheckContentsOfSharedMemoryHandle(const base::SharedMemoryHandle& shm, |
135 const std::string& contents) { | 136 const std::string& contents) { |
136 scoped_ptr<base::SharedMemory> shared_memory(MapSharedMemoryHandle(shm)); | 137 scoped_ptr<base::SharedMemory> shared_memory( |
| 138 MapSharedMemoryHandle(shm, false)); |
137 | 139 |
138 if (memcmp(shared_memory->memory(), contents.c_str(), contents.size()) != 0) { | 140 if (memcmp(shared_memory->memory(), contents.c_str(), contents.size()) != 0) { |
139 LOG(ERROR) << "Shared Memory contents not equivalent"; | 141 LOG(ERROR) << "Shared Memory contents not equivalent"; |
140 return false; | 142 return false; |
141 } | 143 } |
142 return true; | 144 return true; |
143 } | 145 } |
144 | 146 |
145 // This method mmaps the FileDescriptor, checks the contents, and then munmaps | 147 // This method mmaps the FileDescriptor, checks the contents, and then munmaps |
146 // the FileDescriptor and closes the underlying fd. | 148 // the FileDescriptor and closes the underlying fd. |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
181 return base::FileDescriptor(fd_closer.release(), true); | 183 return base::FileDescriptor(fd_closer.release(), true); |
182 } | 184 } |
183 | 185 |
184 // Maps both handles, then checks that their contents matches |contents|. Then | 186 // Maps both handles, then checks that their contents matches |contents|. Then |
185 // checks that changes to one are reflected in the other. Then consumes | 187 // checks that changes to one are reflected in the other. Then consumes |
186 // references to both underlying Mach ports. | 188 // references to both underlying Mach ports. |
187 bool CheckContentsOfTwoEquivalentSharedMemoryHandles( | 189 bool CheckContentsOfTwoEquivalentSharedMemoryHandles( |
188 const base::SharedMemoryHandle& handle1, | 190 const base::SharedMemoryHandle& handle1, |
189 const base::SharedMemoryHandle& handle2, | 191 const base::SharedMemoryHandle& handle2, |
190 const std::string& contents) { | 192 const std::string& contents) { |
191 scoped_ptr<base::SharedMemory> shared_memory1(MapSharedMemoryHandle(handle1)); | 193 scoped_ptr<base::SharedMemory> shared_memory1( |
192 scoped_ptr<base::SharedMemory> shared_memory2(MapSharedMemoryHandle(handle2)); | 194 MapSharedMemoryHandle(handle1, false)); |
| 195 scoped_ptr<base::SharedMemory> shared_memory2( |
| 196 MapSharedMemoryHandle(handle2, false)); |
193 | 197 |
194 if (memcmp(shared_memory1->memory(), contents.c_str(), contents.size()) != | 198 if (memcmp(shared_memory1->memory(), contents.c_str(), contents.size()) != |
195 0) { | 199 0) { |
196 LOG(ERROR) << "Incorrect contents in shared_memory1"; | 200 LOG(ERROR) << "Incorrect contents in shared_memory1"; |
197 return false; | 201 return false; |
198 } | 202 } |
199 | 203 |
200 if (memcmp(shared_memory1->memory(), shared_memory2->memory(), | 204 if (memcmp(shared_memory1->memory(), shared_memory2->memory(), |
201 contents.size()) != 0) { | 205 contents.size()) != 0) { |
202 LOG(ERROR) << "Incorrect contents in shared_memory2"; | 206 LOG(ERROR) << "Incorrect contents in shared_memory2"; |
(...skipping 690 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
893 bool success = CheckContentsOfMessage1(message, kDataBuffer1); | 897 bool success = CheckContentsOfMessage1(message, kDataBuffer1); |
894 SendControlMessage(sender, success); | 898 SendControlMessage(sender, success); |
895 } | 899 } |
896 | 900 |
897 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendSharedMemoryHandleChannelProxy) { | 901 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendSharedMemoryHandleChannelProxy) { |
898 return CommonPrivilegedProcessMain( | 902 return CommonPrivilegedProcessMain( |
899 &SendSharedMemoryHandleChannelProxyCallback, | 903 &SendSharedMemoryHandleChannelProxyCallback, |
900 "SendSharedMemoryHandleChannelProxy"); | 904 "SendSharedMemoryHandleChannelProxy"); |
901 } | 905 } |
902 | 906 |
| 907 // Similar to SendSharedMemoryHandle, but first makes a copy of the handle using |
| 908 // ShareToProcess(). |
| 909 TEST_F(IPCAttachmentBrokerMacTest, ShareToProcess) { |
| 910 CommonSetUp("ShareToProcess"); |
| 911 |
| 912 { |
| 913 scoped_ptr<base::SharedMemory> shared_memory( |
| 914 MakeSharedMemory(kDataBuffer1)); |
| 915 base::SharedMemoryHandle new_handle; |
| 916 ASSERT_TRUE(shared_memory->ShareToProcess(0, &new_handle)); |
| 917 IPC::Message* message = |
| 918 new TestSharedMemoryHandleMsg1(100, new_handle, 200); |
| 919 sender()->Send(message); |
| 920 } |
| 921 |
| 922 base::MessageLoop::current()->Run(); |
| 923 CommonTearDown(); |
| 924 } |
| 925 |
| 926 void ShareToProcessCallback(IPC::Sender* sender, const IPC::Message& message) { |
| 927 bool success = CheckContentsOfMessage1(message, kDataBuffer1); |
| 928 SendControlMessage(sender, success); |
| 929 } |
| 930 |
| 931 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(ShareToProcess) { |
| 932 return CommonPrivilegedProcessMain(&ShareToProcessCallback, "ShareToProcess"); |
| 933 } |
| 934 |
| 935 // Similar to ShareToProcess, but instead shares the memory object only with |
| 936 // read permissions. |
| 937 TEST_F(IPCAttachmentBrokerMacTest, ShareReadOnlyToProcess) { |
| 938 CommonSetUp("ShareReadOnlyToProcess"); |
| 939 |
| 940 { |
| 941 scoped_ptr<base::SharedMemory> shared_memory( |
| 942 MakeSharedMemory(kDataBuffer1)); |
| 943 base::SharedMemoryHandle new_handle; |
| 944 ASSERT_TRUE(shared_memory->ShareReadOnlyToProcess(0, &new_handle)); |
| 945 IPC::Message* message = |
| 946 new TestSharedMemoryHandleMsg1(100, new_handle, 200); |
| 947 sender()->Send(message); |
| 948 } |
| 949 |
| 950 base::MessageLoop::current()->Run(); |
| 951 CommonTearDown(); |
| 952 } |
| 953 |
| 954 void ShareReadOnlyToProcessCallback(IPC::Sender* sender, |
| 955 const IPC::Message& message) { |
| 956 base::SharedMemoryHandle shm(GetSharedMemoryHandleFromMsg1(message)); |
| 957 |
| 958 // Try to map the memory as writable. |
| 959 scoped_ptr<base::SharedMemory> shared_memory( |
| 960 MapSharedMemoryHandle(shm, false)); |
| 961 ASSERT_EQ(nullptr, shared_memory->memory()); |
| 962 |
| 963 // Now try as read-only. |
| 964 scoped_ptr<base::SharedMemory> shared_memory2( |
| 965 MapSharedMemoryHandle(shm.Duplicate(), true)); |
| 966 int current_prot, max_prot; |
| 967 ASSERT_TRUE(IPC::GetMachProtections(shared_memory2->memory(), |
| 968 shared_memory2->mapped_size(), |
| 969 ¤t_prot, &max_prot)); |
| 970 ASSERT_EQ(VM_PROT_READ, current_prot); |
| 971 ASSERT_EQ(VM_PROT_READ, max_prot); |
| 972 |
| 973 bool success = |
| 974 memcmp(shared_memory2->memory(), kDataBuffer1, strlen(kDataBuffer1)) == 0; |
| 975 SendControlMessage(sender, success); |
| 976 } |
| 977 |
| 978 MULTIPROCESS_IPC_TEST_CLIENT_MAIN(ShareReadOnlyToProcess) { |
| 979 return CommonPrivilegedProcessMain(&ShareReadOnlyToProcessCallback, |
| 980 "ShareReadOnlyToProcess"); |
| 981 } |
| 982 |
903 } // namespace | 983 } // namespace |
OLD | NEW |