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 BOOL rv = ::CloseHandle(h); |
| 96 DCHECK(rv); |
| 97 return success ? h2 : nullptr; |
| 98 } |
| 99 |
65 } // namespace. | 100 } // namespace. |
66 | 101 |
67 namespace base { | 102 namespace base { |
68 | 103 |
69 SharedMemoryCreateOptions::SharedMemoryCreateOptions() | 104 SharedMemoryCreateOptions::SharedMemoryCreateOptions() |
70 : name_deprecated(nullptr), | 105 : name_deprecated(nullptr), |
71 open_existing_deprecated(false), | 106 open_existing_deprecated(false), |
72 size(0), | 107 size(0), |
73 executable(false), | 108 executable(false), |
74 share_read_only(false) {} | 109 share_read_only(false) {} |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
162 static_cast<size_t>(std::numeric_limits<int>::max()) - kSectionMask) | 197 static_cast<size_t>(std::numeric_limits<int>::max()) - kSectionMask) |
163 return false; | 198 return false; |
164 | 199 |
165 size_t rounded_size = (options.size + kSectionMask) & ~kSectionMask; | 200 size_t rounded_size = (options.size + kSectionMask) & ~kSectionMask; |
166 name_ = options.name_deprecated ? | 201 name_ = options.name_deprecated ? |
167 ASCIIToUTF16(*options.name_deprecated) : L""; | 202 ASCIIToUTF16(*options.name_deprecated) : L""; |
168 SECURITY_ATTRIBUTES sa = { sizeof(sa), NULL, FALSE }; | 203 SECURITY_ATTRIBUTES sa = { sizeof(sa), NULL, FALSE }; |
169 SECURITY_DESCRIPTOR sd; | 204 SECURITY_DESCRIPTOR sd; |
170 ACL dacl; | 205 ACL dacl; |
171 | 206 |
172 if (options.share_read_only && name_.empty()) { | 207 if (name_.empty()) { |
173 // Add an empty DACL to enforce anonymous read-only sections. | 208 // Add an empty DACL to enforce anonymous read-only sections. |
174 sa.lpSecurityDescriptor = &sd; | 209 sa.lpSecurityDescriptor = &sd; |
175 if (!InitializeAcl(&dacl, sizeof(dacl), ACL_REVISION)) | 210 if (!InitializeAcl(&dacl, sizeof(dacl), ACL_REVISION)) |
176 return false; | 211 return false; |
177 if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) | 212 if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) |
178 return false; | 213 return false; |
179 if (!SetSecurityDescriptorDacl(&sd, TRUE, &dacl, FALSE)) | 214 if (!SetSecurityDescriptorDacl(&sd, TRUE, &dacl, FALSE)) |
180 return false; | 215 return false; |
181 | 216 |
182 // Windows ignores DACLs on certain unnamed objects (like shared sections). | 217 // Windows ignores DACLs on certain unnamed objects (like shared sections). |
183 // So, we generate a random name when we need to enforce read-only. | 218 // So, we generate a random name when we need to enforce read-only. |
184 uint64_t rand_values[4]; | 219 uint64_t rand_values[4]; |
185 RandBytes(&rand_values, sizeof(rand_values)); | 220 RandBytes(&rand_values, sizeof(rand_values)); |
186 name_ = StringPrintf(L"CrSharedMem_%016llx%016llx%016llx%016llx", | 221 name_ = StringPrintf(L"CrSharedMem_%016llx%016llx%016llx%016llx", |
187 rand_values[0], rand_values[1], | 222 rand_values[0], rand_values[1], |
188 rand_values[2], rand_values[3]); | 223 rand_values[2], rand_values[3]); |
189 } | 224 } |
190 mapped_file_ = CreateFileMapping(INVALID_HANDLE_VALUE, &sa, | 225 mapped_file_ = CreateFileMappingWithReducedPermissions( |
191 PAGE_READWRITE, 0, static_cast<DWORD>(rounded_size), | 226 &sa, rounded_size, name_.empty() ? nullptr : name_.c_str()); |
192 name_.empty() ? nullptr : name_.c_str()); | |
193 if (!mapped_file_) | 227 if (!mapped_file_) |
194 return false; | 228 return false; |
195 | 229 |
196 requested_size_ = options.size; | 230 requested_size_ = options.size; |
197 | 231 |
198 // Check if the shared memory pre-exists. | 232 // Check if the shared memory pre-exists. |
199 if (GetLastError() == ERROR_ALREADY_EXISTS) { | 233 if (GetLastError() == ERROR_ALREADY_EXISTS) { |
200 // If the file already existed, set requested_size_ to 0 to show that | 234 // If the file already existed, set requested_size_ to 0 to show that |
201 // we don't know the size. | 235 // we don't know the size. |
202 requested_size_ = 0; | 236 requested_size_ = 0; |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
305 ::CloseHandle(mapped_file_); | 339 ::CloseHandle(mapped_file_); |
306 mapped_file_ = NULL; | 340 mapped_file_ = NULL; |
307 } | 341 } |
308 } | 342 } |
309 | 343 |
310 SharedMemoryHandle SharedMemory::handle() const { | 344 SharedMemoryHandle SharedMemory::handle() const { |
311 return SharedMemoryHandle(mapped_file_, base::GetCurrentProcId()); | 345 return SharedMemoryHandle(mapped_file_, base::GetCurrentProcId()); |
312 } | 346 } |
313 | 347 |
314 } // namespace base | 348 } // namespace base |
OLD | NEW |