Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(919)

Side by Side Diff: base/memory/shared_memory_win.cc

Issue 1501003002: Added protection against mapping image sections between processes. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixes from review Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/memory/shared_memory_unittest.cc ('k') | content/common/sandbox_init_win.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/memory/scoped_ptr.h" 10 #include "base/memory/scoped_ptr.h"
11 #include "base/rand_util.h" 11 #include "base/rand_util.h"
12 #include "base/strings/stringprintf.h" 12 #include "base/strings/stringprintf.h"
13 #include "base/strings/utf_string_conversions.h" 13 #include "base/strings/utf_string_conversions.h"
14 14
15 namespace { 15 namespace {
16 16
17 typedef enum _SECTION_INFORMATION_CLASS {
18 SectionBasicInformation,
19 } SECTION_INFORMATION_CLASS;
20
21 typedef struct _SECTION_BASIC_INFORMATION {
22 PVOID BaseAddress;
23 ULONG Attributes;
24 LARGE_INTEGER Size;
25 } SECTION_BASIC_INFORMATION, *PSECTION_BASIC_INFORMATION;
26
27 typedef ULONG(__stdcall* NtQuerySectionType)(
28 HANDLE SectionHandle,
29 SECTION_INFORMATION_CLASS SectionInformationClass,
30 PVOID SectionInformation,
31 ULONG SectionInformationLength,
32 PULONG ResultLength);
33
17 // Returns the length of the memory section starting at the supplied address. 34 // Returns the length of the memory section starting at the supplied address.
18 size_t GetMemorySectionSize(void* address) { 35 size_t GetMemorySectionSize(void* address) {
19 MEMORY_BASIC_INFORMATION memory_info; 36 MEMORY_BASIC_INFORMATION memory_info;
20 if (!::VirtualQuery(address, &memory_info, sizeof(memory_info))) 37 if (!::VirtualQuery(address, &memory_info, sizeof(memory_info)))
21 return 0; 38 return 0;
22 return memory_info.RegionSize - (static_cast<char*>(address) - 39 return memory_info.RegionSize - (static_cast<char*>(address) -
23 static_cast<char*>(memory_info.AllocationBase)); 40 static_cast<char*>(memory_info.AllocationBase));
24 } 41 }
25 42
43 // Checks if the section object is safe to map. At the moment this just means
44 // it's not an image section.
45 bool IsSectionSafeToMap(HANDLE handle) {
46 static NtQuerySectionType nt_query_section_func;
47 if (!nt_query_section_func) {
48 nt_query_section_func = reinterpret_cast<NtQuerySectionType>(
49 ::GetProcAddress(::GetModuleHandle(L"ntdll.dll"), "NtQuerySection"));
50 DCHECK(nt_query_section_func);
51 }
52
53 // The handle must have SECTION_QUERY access for this to succeed.
54 SECTION_BASIC_INFORMATION basic_information = {};
55 ULONG status =
56 nt_query_section_func(handle, SectionBasicInformation, &basic_information,
57 sizeof(basic_information), nullptr);
58 if (status)
59 return false;
60 return (basic_information.Attributes & SEC_IMAGE) != SEC_IMAGE;
61 }
62
26 } // namespace. 63 } // namespace.
27 64
28 namespace base { 65 namespace base {
29 66
30 SharedMemoryCreateOptions::SharedMemoryCreateOptions() 67 SharedMemoryCreateOptions::SharedMemoryCreateOptions()
31 : name_deprecated(nullptr), 68 : name_deprecated(nullptr),
32 open_existing_deprecated(false), 69 open_existing_deprecated(false),
33 size(0), 70 size(0),
34 executable(false), 71 executable(false),
35 share_read_only(false) {} 72 share_read_only(false) {}
36 73
37 SharedMemory::SharedMemory() 74 SharedMemory::SharedMemory()
38 : mapped_file_(NULL), 75 : external_section_(false),
39 mapped_size_(0),
40 memory_(NULL),
41 read_only_(false),
42 requested_size_(0) {
43 }
44
45 SharedMemory::SharedMemory(const std::wstring& name)
46 : name_(name),
47 mapped_file_(NULL), 76 mapped_file_(NULL),
48 mapped_size_(0), 77 mapped_size_(0),
49 memory_(NULL), 78 memory_(NULL),
50 read_only_(false), 79 read_only_(false),
51 requested_size_(0) { 80 requested_size_(0) {}
52 } 81
82 SharedMemory::SharedMemory(const std::wstring& name)
83 : external_section_(false),
84 name_(name),
85 mapped_file_(NULL),
86 mapped_size_(0),
87 memory_(NULL),
88 read_only_(false),
89 requested_size_(0) {}
53 90
54 SharedMemory::SharedMemory(const SharedMemoryHandle& handle, bool read_only) 91 SharedMemory::SharedMemory(const SharedMemoryHandle& handle, bool read_only)
55 : mapped_file_(handle.GetHandle()), 92 : external_section_(true),
93 mapped_file_(handle.GetHandle()),
56 mapped_size_(0), 94 mapped_size_(0),
57 memory_(NULL), 95 memory_(NULL),
58 read_only_(read_only), 96 read_only_(read_only),
59 requested_size_(0) { 97 requested_size_(0) {
60 DCHECK(!handle.IsValid() || handle.BelongsToCurrentProcess()); 98 DCHECK(!handle.IsValid() || handle.BelongsToCurrentProcess());
61 } 99 }
62 100
63 SharedMemory::SharedMemory(const SharedMemoryHandle& handle, 101 SharedMemory::SharedMemory(const SharedMemoryHandle& handle,
64 bool read_only, 102 bool read_only,
65 ProcessHandle process) 103 ProcessHandle process)
66 : mapped_file_(NULL), 104 : external_section_(true),
105 mapped_file_(NULL),
67 mapped_size_(0), 106 mapped_size_(0),
68 memory_(NULL), 107 memory_(NULL),
69 read_only_(read_only), 108 read_only_(read_only),
70 requested_size_(0) { 109 requested_size_(0) {
71 ::DuplicateHandle( 110 DWORD access = FILE_MAP_READ | SECTION_QUERY;
72 process, handle.GetHandle(), GetCurrentProcess(), &mapped_file_, 111 ::DuplicateHandle(process, handle.GetHandle(), GetCurrentProcess(),
73 read_only_ ? FILE_MAP_READ : FILE_MAP_READ | FILE_MAP_WRITE, FALSE, 0); 112 &mapped_file_,
113 read_only_ ? access : access | FILE_MAP_WRITE, FALSE, 0);
74 } 114 }
75 115
76 SharedMemory::~SharedMemory() { 116 SharedMemory::~SharedMemory() {
77 Unmap(); 117 Unmap();
78 Close(); 118 Close();
79 } 119 }
80 120
81 // static 121 // static
82 bool SharedMemory::IsHandleValid(const SharedMemoryHandle& handle) { 122 bool SharedMemory::IsHandleValid(const SharedMemoryHandle& handle) {
83 return handle.IsValid(); 123 return handle.IsValid();
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
163 if (!mapped_file_) 203 if (!mapped_file_)
164 return false; 204 return false;
165 205
166 requested_size_ = options.size; 206 requested_size_ = options.size;
167 207
168 // Check if the shared memory pre-exists. 208 // Check if the shared memory pre-exists.
169 if (GetLastError() == ERROR_ALREADY_EXISTS) { 209 if (GetLastError() == ERROR_ALREADY_EXISTS) {
170 // If the file already existed, set requested_size_ to 0 to show that 210 // If the file already existed, set requested_size_ to 0 to show that
171 // we don't know the size. 211 // we don't know the size.
172 requested_size_ = 0; 212 requested_size_ = 0;
213 external_section_ = true;
173 if (!options.open_existing_deprecated) { 214 if (!options.open_existing_deprecated) {
174 Close(); 215 Close();
175 return false; 216 return false;
176 } 217 }
177 } 218 }
178 219
179 return true; 220 return true;
180 } 221 }
181 222
182 bool SharedMemory::Delete(const std::string& name) { 223 bool SharedMemory::Delete(const std::string& name) {
183 // intentionally empty -- there is nothing for us to do on Windows. 224 // intentionally empty -- there is nothing for us to do on Windows.
184 return true; 225 return true;
185 } 226 }
186 227
187 bool SharedMemory::Open(const std::string& name, bool read_only) { 228 bool SharedMemory::Open(const std::string& name, bool read_only) {
188 DCHECK(!mapped_file_); 229 DCHECK(!mapped_file_);
189 230 DWORD access = FILE_MAP_READ | SECTION_QUERY;
231 if (!read_only)
232 access |= FILE_MAP_WRITE;
190 name_ = ASCIIToUTF16(name); 233 name_ = ASCIIToUTF16(name);
191 read_only_ = read_only; 234 read_only_ = read_only;
192 mapped_file_ = OpenFileMapping( 235 mapped_file_ =
193 read_only_ ? FILE_MAP_READ : FILE_MAP_READ | FILE_MAP_WRITE, 236 OpenFileMapping(access, false, name_.empty() ? nullptr : name_.c_str());
194 false, name_.empty() ? NULL : name_.c_str()); 237 if (!mapped_file_)
195 if (mapped_file_ != NULL) { 238 return false;
196 // Note: size_ is not set in this case. 239 // If a name specified assume it's an external section.
197 return true; 240 if (!name_.empty())
198 } 241 external_section_ = true;
199 return false; 242 // Note: size_ is not set in this case.
243 return true;
200 } 244 }
201 245
202 bool SharedMemory::MapAt(off_t offset, size_t bytes) { 246 bool SharedMemory::MapAt(off_t offset, size_t bytes) {
203 if (mapped_file_ == NULL) 247 if (mapped_file_ == NULL)
204 return false; 248 return false;
205 249
206 if (bytes > static_cast<size_t>(std::numeric_limits<int>::max())) 250 if (bytes > static_cast<size_t>(std::numeric_limits<int>::max()))
207 return false; 251 return false;
208 252
209 if (memory_) 253 if (memory_)
210 return false; 254 return false;
211 255
256 if (external_section_ && !IsSectionSafeToMap(mapped_file_))
257 return false;
258
212 memory_ = MapViewOfFile(mapped_file_, 259 memory_ = MapViewOfFile(mapped_file_,
213 read_only_ ? FILE_MAP_READ : FILE_MAP_READ | 260 read_only_ ? FILE_MAP_READ : FILE_MAP_READ |
214 FILE_MAP_WRITE, 261 FILE_MAP_WRITE,
215 static_cast<uint64>(offset) >> 32, 262 static_cast<uint64>(offset) >> 32,
216 static_cast<DWORD>(offset), 263 static_cast<DWORD>(offset),
217 bytes); 264 bytes);
218 if (memory_ != NULL) { 265 if (memory_ != NULL) {
219 DCHECK_EQ(0U, reinterpret_cast<uintptr_t>(memory_) & 266 DCHECK_EQ(0U, reinterpret_cast<uintptr_t>(memory_) &
220 (SharedMemory::MAP_MINIMUM_ALIGNMENT - 1)); 267 (SharedMemory::MAP_MINIMUM_ALIGNMENT - 1));
221 mapped_size_ = GetMemorySectionSize(memory_); 268 mapped_size_ = GetMemorySectionSize(memory_);
222 return true; 269 return true;
223 } 270 }
224 return false; 271 return false;
225 } 272 }
226 273
227 bool SharedMemory::Unmap() { 274 bool SharedMemory::Unmap() {
228 if (memory_ == NULL) 275 if (memory_ == NULL)
229 return false; 276 return false;
230 277
231 UnmapViewOfFile(memory_); 278 UnmapViewOfFile(memory_);
232 memory_ = NULL; 279 memory_ = NULL;
233 return true; 280 return true;
234 } 281 }
235 282
236 bool SharedMemory::ShareToProcessCommon(ProcessHandle process, 283 bool SharedMemory::ShareToProcessCommon(ProcessHandle process,
237 SharedMemoryHandle* new_handle, 284 SharedMemoryHandle* new_handle,
238 bool close_self, 285 bool close_self,
239 ShareMode share_mode) { 286 ShareMode share_mode) {
240 *new_handle = SharedMemoryHandle(); 287 *new_handle = SharedMemoryHandle();
241 DWORD access = FILE_MAP_READ; 288 DWORD access = FILE_MAP_READ | SECTION_QUERY;
242 DWORD options = 0; 289 DWORD options = 0;
243 HANDLE mapped_file = mapped_file_; 290 HANDLE mapped_file = mapped_file_;
244 HANDLE result; 291 HANDLE result;
245 if (share_mode == SHARE_CURRENT_MODE && !read_only_) 292 if (share_mode == SHARE_CURRENT_MODE && !read_only_)
246 access |= FILE_MAP_WRITE; 293 access |= FILE_MAP_WRITE;
247 if (close_self) { 294 if (close_self) {
248 // DUPLICATE_CLOSE_SOURCE causes DuplicateHandle to close mapped_file. 295 // DUPLICATE_CLOSE_SOURCE causes DuplicateHandle to close mapped_file.
249 options = DUPLICATE_CLOSE_SOURCE; 296 options = DUPLICATE_CLOSE_SOURCE;
250 mapped_file_ = NULL; 297 mapped_file_ = NULL;
251 Unmap(); 298 Unmap();
(...skipping 18 matching lines...) Expand all
270 ::CloseHandle(mapped_file_); 317 ::CloseHandle(mapped_file_);
271 mapped_file_ = NULL; 318 mapped_file_ = NULL;
272 } 319 }
273 } 320 }
274 321
275 SharedMemoryHandle SharedMemory::handle() const { 322 SharedMemoryHandle SharedMemory::handle() const {
276 return SharedMemoryHandle(mapped_file_, base::GetCurrentProcId()); 323 return SharedMemoryHandle(mapped_file_, base::GetCurrentProcId());
277 } 324 }
278 325
279 } // namespace base 326 } // namespace base
OLDNEW
« no previous file with comments | « base/memory/shared_memory_unittest.cc ('k') | content/common/sandbox_init_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698