OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "base/memory/shared_memory.h" | 5 #include "base/memory/shared_memory.h" |
6 | 6 |
7 #include <aclapi.h> | 7 #include <aclapi.h> |
8 #include <stddef.h> | 8 #include <stddef.h> |
9 #include <stdint.h> | 9 #include <stdint.h> |
10 | 10 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
55 // The handle must have SECTION_QUERY access for this to succeed. | 55 // The handle must have SECTION_QUERY access for this to succeed. |
56 SECTION_BASIC_INFORMATION basic_information = {}; | 56 SECTION_BASIC_INFORMATION basic_information = {}; |
57 ULONG status = | 57 ULONG status = |
58 nt_query_section_func(handle, SectionBasicInformation, &basic_information, | 58 nt_query_section_func(handle, SectionBasicInformation, &basic_information, |
59 sizeof(basic_information), nullptr); | 59 sizeof(basic_information), nullptr); |
60 if (status) | 60 if (status) |
61 return false; | 61 return false; |
62 return (basic_information.Attributes & SEC_IMAGE) != SEC_IMAGE; | 62 return (basic_information.Attributes & SEC_IMAGE) != SEC_IMAGE; |
63 } | 63 } |
64 | 64 |
65 // Returns a HANDLE on success and |nullptr| on failure. | |
66 // This function is similar to CreateFileMapping, but removes the permissions | |
67 // WRITE_DAC, WRITE_OWNER, READ_CONTROL, and DELETE. | |
68 // | |
69 // A newly created file mapping has two sets of permissions. It has access | |
70 // control permissions (WRITE_DAC, WRITE_OWNER, READ_CONTROL, and DELETE) and | |
71 // file permissions (FILE_MAP_READ, FILE_MAP_WRITE, etc.). ::DuplicateHandle() | |
72 // with the parameter DUPLICATE_SAME_ACCESS copies both sets of permissions. | |
73 // | |
74 // The Chrome sandbox prevents HANDLEs with the WRITE_DAC permission from being | |
75 // duplicated into unprivileged processes. But the only way to copy file | |
76 // permissions is with the parameter DUPLICATE_SAME_ACCESS. This means that | |
77 // there is no way for a privileged process to duplicate a file mapping into an | |
78 // unprivileged process while maintaining the previous file permissions. | |
79 // | |
80 // By removing all access control permissions of a file mapping immediately | |
81 // after creation, ::DuplicateHandle() effectively only copies the file | |
82 // permissions. | |
83 HANDLE CreateFileMappingWithReducedPermissions(SECURITY_ATTRIBUTES* sa, | |
84 size_t rounded_size, | |
85 LPCWSTR name) { | |
86 HANDLE h = CreateFileMapping(INVALID_HANDLE_VALUE, sa, PAGE_READWRITE, 0, | |
87 static_cast<DWORD>(rounded_size), name); | |
88 if (!h) | |
89 return nullptr; | |
90 | |
91 HANDLE h2; | |
92 BOOL success = ::DuplicateHandle( | |
93 GetCurrentProcess(), h, GetCurrentProcess(), &h2, | |
94 FILE_MAP_READ | FILE_MAP_WRITE | SECTION_QUERY, FALSE, 0); | |
95 ::CloseHandle(h); | |
Mark Mentovai
2016/02/17 19:03:14
BOOL rv = ::CloseHandle(h);
DCHECK(rv);
?
erikchen
2016/02/17 19:22:26
Done.
| |
96 return success ? h2 : nullptr; | |
97 } | |
98 | |
65 } // namespace. | 99 } // namespace. |
66 | 100 |
67 namespace base { | 101 namespace base { |
68 | 102 |
69 SharedMemoryCreateOptions::SharedMemoryCreateOptions() | 103 SharedMemoryCreateOptions::SharedMemoryCreateOptions() |
70 : name_deprecated(nullptr), | 104 : name_deprecated(nullptr), |
71 open_existing_deprecated(false), | 105 open_existing_deprecated(false), |
72 size(0), | 106 size(0), |
73 executable(false), | 107 executable(false), |
74 share_read_only(false) {} | 108 share_read_only(false) {} |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
129 | 163 |
130 // static | 164 // static |
131 SharedMemoryHandle SharedMemory::DuplicateHandle( | 165 SharedMemoryHandle SharedMemory::DuplicateHandle( |
132 const SharedMemoryHandle& handle) { | 166 const SharedMemoryHandle& handle) { |
133 DCHECK(handle.BelongsToCurrentProcess()); | 167 DCHECK(handle.BelongsToCurrentProcess()); |
134 HANDLE duped_handle; | 168 HANDLE duped_handle; |
135 ProcessHandle process = GetCurrentProcess(); | 169 ProcessHandle process = GetCurrentProcess(); |
136 BOOL success = | 170 BOOL success = |
137 ::DuplicateHandle(process, handle.GetHandle(), process, &duped_handle, 0, | 171 ::DuplicateHandle(process, handle.GetHandle(), process, &duped_handle, 0, |
138 FALSE, DUPLICATE_SAME_ACCESS); | 172 FALSE, DUPLICATE_SAME_ACCESS); |
139 if (success) | 173 if (success) { |
140 return SharedMemoryHandle(duped_handle, GetCurrentProcId()); | 174 base::SharedMemoryHandle handle(duped_handle, GetCurrentProcId()); |
175 handle.SetOwnershipPassesToIPC(true); | |
176 return handle; | |
177 } | |
141 return SharedMemoryHandle(); | 178 return SharedMemoryHandle(); |
142 } | 179 } |
143 | 180 |
144 bool SharedMemory::CreateAndMapAnonymous(size_t size) { | 181 bool SharedMemory::CreateAndMapAnonymous(size_t size) { |
145 return CreateAnonymous(size) && Map(size); | 182 return CreateAnonymous(size) && Map(size); |
146 } | 183 } |
147 | 184 |
148 bool SharedMemory::Create(const SharedMemoryCreateOptions& options) { | 185 bool SharedMemory::Create(const SharedMemoryCreateOptions& options) { |
149 // TODO(bsy,sehr): crbug.com/210609 NaCl forces us to round up 64k here, | 186 // TODO(bsy,sehr): crbug.com/210609 NaCl forces us to round up 64k here, |
150 // wasting 32k per mapping on average. | 187 // wasting 32k per mapping on average. |
151 static const size_t kSectionMask = 65536 - 1; | 188 static const size_t kSectionMask = 65536 - 1; |
152 DCHECK(!options.executable); | 189 DCHECK(!options.executable); |
153 DCHECK(!mapped_file_); | 190 DCHECK(!mapped_file_); |
154 if (options.size == 0) | 191 if (options.size == 0) |
155 return false; | 192 return false; |
156 | 193 |
157 // Check maximum accounting for overflow. | 194 // Check maximum accounting for overflow. |
158 if (options.size > | 195 if (options.size > |
159 static_cast<size_t>(std::numeric_limits<int>::max()) - kSectionMask) | 196 static_cast<size_t>(std::numeric_limits<int>::max()) - kSectionMask) |
160 return false; | 197 return false; |
161 | 198 |
162 size_t rounded_size = (options.size + kSectionMask) & ~kSectionMask; | 199 size_t rounded_size = (options.size + kSectionMask) & ~kSectionMask; |
163 name_ = options.name_deprecated ? | 200 name_ = options.name_deprecated ? |
164 ASCIIToUTF16(*options.name_deprecated) : L""; | 201 ASCIIToUTF16(*options.name_deprecated) : L""; |
165 SECURITY_ATTRIBUTES sa = { sizeof(sa), NULL, FALSE }; | 202 SECURITY_ATTRIBUTES sa = { sizeof(sa), NULL, FALSE }; |
166 SECURITY_DESCRIPTOR sd; | 203 SECURITY_DESCRIPTOR sd; |
167 ACL dacl; | 204 ACL dacl; |
168 | 205 |
169 if (options.share_read_only && name_.empty()) { | 206 if (name_.empty()) { |
penny
2016/02/17 00:32:24
So, we're no longer looking at whether |share_read
erikchen
2016/02/17 00:43:22
(1) is a correct assessment. I would prefer to rem
| |
170 // Add an empty DACL to enforce anonymous read-only sections. | 207 // Add an empty DACL to enforce anonymous read-only sections. |
171 sa.lpSecurityDescriptor = &sd; | 208 sa.lpSecurityDescriptor = &sd; |
172 if (!InitializeAcl(&dacl, sizeof(dacl), ACL_REVISION)) | 209 if (!InitializeAcl(&dacl, sizeof(dacl), ACL_REVISION)) |
173 return false; | 210 return false; |
174 if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) | 211 if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) |
175 return false; | 212 return false; |
176 if (!SetSecurityDescriptorDacl(&sd, TRUE, &dacl, FALSE)) | 213 if (!SetSecurityDescriptorDacl(&sd, TRUE, &dacl, FALSE)) |
177 return false; | 214 return false; |
178 | 215 |
179 // Windows ignores DACLs on certain unnamed objects (like shared sections). | 216 // Windows ignores DACLs on certain unnamed objects (like shared sections). |
180 // So, we generate a random name when we need to enforce read-only. | 217 // So, we generate a random name when we need to enforce read-only. |
181 uint64_t rand_values[4]; | 218 uint64_t rand_values[4]; |
182 RandBytes(&rand_values, sizeof(rand_values)); | 219 RandBytes(&rand_values, sizeof(rand_values)); |
183 name_ = StringPrintf(L"CrSharedMem_%016llx%016llx%016llx%016llx", | 220 name_ = StringPrintf(L"CrSharedMem_%016llx%016llx%016llx%016llx", |
184 rand_values[0], rand_values[1], | 221 rand_values[0], rand_values[1], |
185 rand_values[2], rand_values[3]); | 222 rand_values[2], rand_values[3]); |
186 } | 223 } |
187 mapped_file_ = CreateFileMapping(INVALID_HANDLE_VALUE, &sa, | 224 mapped_file_ = CreateFileMappingWithReducedPermissions( |
188 PAGE_READWRITE, 0, static_cast<DWORD>(rounded_size), | 225 &sa, rounded_size, name_.empty() ? nullptr : name_.c_str()); |
189 name_.empty() ? nullptr : name_.c_str()); | |
190 if (!mapped_file_) | 226 if (!mapped_file_) |
191 return false; | 227 return false; |
192 | 228 |
193 requested_size_ = options.size; | 229 requested_size_ = options.size; |
194 | 230 |
195 // Check if the shared memory pre-exists. | 231 // Check if the shared memory pre-exists. |
196 if (GetLastError() == ERROR_ALREADY_EXISTS) { | 232 if (GetLastError() == ERROR_ALREADY_EXISTS) { |
197 // If the file already existed, set requested_size_ to 0 to show that | 233 // If the file already existed, set requested_size_ to 0 to show that |
198 // we don't know the size. | 234 // we don't know the size. |
199 requested_size_ = 0; | 235 requested_size_ = 0; |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
302 ::CloseHandle(mapped_file_); | 338 ::CloseHandle(mapped_file_); |
303 mapped_file_ = NULL; | 339 mapped_file_ = NULL; |
304 } | 340 } |
305 } | 341 } |
306 | 342 |
307 SharedMemoryHandle SharedMemory::handle() const { | 343 SharedMemoryHandle SharedMemory::handle() const { |
308 return SharedMemoryHandle(mapped_file_, base::GetCurrentProcId()); | 344 return SharedMemoryHandle(mapped_file_, base::GetCurrentProcId()); |
309 } | 345 } |
310 | 346 |
311 } // namespace base | 347 } // namespace base |
OLD | NEW |