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

Side by Side Diff: sandbox/win/src/sandbox_nt_util.cc

Issue 84063004: Restructure sandbox code to reduce dependencies pulled in by intercept code. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remove sandbox re-libification Created 7 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "sandbox/win/src/sandbox_nt_util.h" 5 #include "sandbox/win/src/sandbox_nt_util.h"
6 6
7 #include "base/win/pe_image.h" 7 #include "base/win/pe_image.h"
8 #include "sandbox/win/src/sandbox_factory.h" 8 #include "sandbox/win/src/sandbox_factory.h"
9 #include "sandbox/win/src/target_services.h" 9 #include "sandbox/win/src/target_services.h"
10 10
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 } 100 }
101 #endif // defined(_WIN64). 101 #endif // defined(_WIN64).
102 102
103 } // namespace. 103 } // namespace.
104 104
105 namespace sandbox { 105 namespace sandbox {
106 106
107 // Handle for our private heap. 107 // Handle for our private heap.
108 void* g_heap = NULL; 108 void* g_heap = NULL;
109 109
110 SANDBOX_INTERCEPT HANDLE g_shared_section;
111 SANDBOX_INTERCEPT size_t g_shared_IPC_size = 0;
112 SANDBOX_INTERCEPT size_t g_shared_policy_size = 0;
113
114 void* volatile g_shared_policy_memory = NULL;
115 void* volatile g_shared_IPC_memory = NULL;
116
117 // Both the IPC and the policy share a single region of memory in which the IPC
118 // memory is first and the policy memory is last.
119 bool MapGlobalMemory() {
rvargas (doing something else) 2013/11/26 20:42:12 I don't see anything in this block of code that sh
robertshield 2013/11/27 20:28:01 The code in just this block doesn't actually pull
120 if (NULL == g_shared_IPC_memory) {
121 void* memory = NULL;
122 SIZE_T size = 0;
123 // Map the entire shared section from the start.
124 NTSTATUS ret = g_nt.MapViewOfSection(g_shared_section, NtCurrentProcess,
125 &memory, 0, 0, NULL, &size, ViewUnmap,
126 0, PAGE_READWRITE);
127
128 if (!NT_SUCCESS(ret) || NULL == memory) {
129 NOTREACHED_NT();
130 return false;
131 }
132
133 if (NULL != _InterlockedCompareExchangePointer(&g_shared_IPC_memory,
134 memory, NULL)) {
135 // Somebody beat us to the memory setup.
136 ret = g_nt.UnmapViewOfSection(NtCurrentProcess, memory);
137 VERIFY_SUCCESS(ret);
138 }
139 DCHECK_NT(g_shared_IPC_size > 0);
140 g_shared_policy_memory = reinterpret_cast<char*>(g_shared_IPC_memory)
141 + g_shared_IPC_size;
142 }
143 DCHECK_NT(g_shared_policy_memory);
144 DCHECK_NT(g_shared_policy_size > 0);
145 return true;
146 }
147
148 void* GetGlobalIPCMemory() {
149 if (!MapGlobalMemory())
150 return NULL;
151 return g_shared_IPC_memory;
152 }
153
154 void* GetGlobalPolicyMemory() {
155 if (!MapGlobalMemory())
156 return NULL;
157 return g_shared_policy_memory;
158 }
159
160 bool InitHeap() { 110 bool InitHeap() {
161 if (!g_heap) { 111 if (!g_heap) {
162 // Create a new heap using default values for everything. 112 // Create a new heap using default values for everything.
163 void* heap = g_nt.RtlCreateHeap(HEAP_GROWABLE, NULL, 0, 0, NULL, NULL); 113 void* heap = g_nt.RtlCreateHeap(HEAP_GROWABLE, NULL, 0, 0, NULL, NULL);
164 if (!heap) 114 if (!heap)
165 return false; 115 return false;
166 116
167 if (NULL != _InterlockedCompareExchangePointer(&g_heap, heap, NULL)) { 117 if (NULL != _InterlockedCompareExchangePointer(&g_heap, heap, NULL)) {
168 // Somebody beat us to the memory setup. 118 // Somebody beat us to the memory setup.
169 g_nt.RtlDestroyHeap(heap); 119 g_nt.RtlDestroyHeap(heap);
(...skipping 28 matching lines...) Expand all
198 bool ValidParameter(void* buffer, size_t size, RequiredAccess intent) { 148 bool ValidParameter(void* buffer, size_t size, RequiredAccess intent) {
199 DCHECK_NT(size); 149 DCHECK_NT(size);
200 __try { 150 __try {
201 TouchMemory(buffer, size, intent); 151 TouchMemory(buffer, size, intent);
202 } __except(EXCEPTION_EXECUTE_HANDLER) { 152 } __except(EXCEPTION_EXECUTE_HANDLER) {
203 return false; 153 return false;
204 } 154 }
205 return true; 155 return true;
206 } 156 }
207 157
208 NTSTATUS CopyData(void* destination, const void* source, size_t bytes) {
209 NTSTATUS ret = STATUS_SUCCESS;
210 __try {
211 if (SandboxFactory::GetTargetServices()->GetState()->InitCalled()) {
rvargas (doing something else) 2013/11/26 20:42:12 Same thing here... and ExtractModuleName... is it
robertshield 2013/11/27 20:28:01 Yes, the GetTargetServices() call is the problem.
rvargas (doing something else) 2013/11/27 23:53:50 Carlos may have an opinion here, but I'd say we co
robertshield 2013/11/29 01:21:26 I believe this is now solved by your observation t
212 memcpy(destination, source, bytes);
213 } else {
214 const char* from = reinterpret_cast<const char*>(source);
215 char* to = reinterpret_cast<char*>(destination);
216 for (size_t i = 0; i < bytes; i++) {
217 to[i] = from[i];
218 }
219 }
220 } __except(EXCEPTION_EXECUTE_HANDLER) {
221 ret = GetExceptionCode();
222 }
223 return ret;
224 }
225
226 // Hacky code... replace with AllocAndCopyObjectAttributes.
227 NTSTATUS AllocAndCopyName(const OBJECT_ATTRIBUTES* in_object,
228 wchar_t** out_name, uint32* attributes,
229 HANDLE* root) {
230 if (!InitHeap())
231 return STATUS_NO_MEMORY;
232
233 DCHECK_NT(out_name);
234 *out_name = NULL;
235 NTSTATUS ret = STATUS_UNSUCCESSFUL;
236 __try {
237 do {
238 if (in_object->RootDirectory != static_cast<HANDLE>(0) && !root)
239 break;
240 if (NULL == in_object->ObjectName)
241 break;
242 if (NULL == in_object->ObjectName->Buffer)
243 break;
244
245 size_t size = in_object->ObjectName->Length + sizeof(wchar_t);
246 *out_name = new(NT_ALLOC) wchar_t[size/sizeof(wchar_t)];
247 if (NULL == *out_name)
248 break;
249
250 ret = CopyData(*out_name, in_object->ObjectName->Buffer,
251 size - sizeof(wchar_t));
252 if (!NT_SUCCESS(ret))
253 break;
254
255 (*out_name)[size / sizeof(wchar_t) - 1] = L'\0';
256
257 if (attributes)
258 *attributes = in_object->Attributes;
259
260 if (root)
261 *root = in_object->RootDirectory;
262 ret = STATUS_SUCCESS;
263 } while (false);
264 } __except(EXCEPTION_EXECUTE_HANDLER) {
265 ret = GetExceptionCode();
266 }
267
268 if (!NT_SUCCESS(ret) && *out_name) {
269 operator delete(*out_name, NT_ALLOC);
270 *out_name = NULL;
271 }
272
273 return ret;
274 }
275
276 NTSTATUS GetProcessId(HANDLE process, ULONG *process_id) { 158 NTSTATUS GetProcessId(HANDLE process, ULONG *process_id) {
277 PROCESS_BASIC_INFORMATION proc_info; 159 PROCESS_BASIC_INFORMATION proc_info;
278 ULONG bytes_returned; 160 ULONG bytes_returned;
279 161
280 NTSTATUS ret = g_nt.QueryInformationProcess(process, ProcessBasicInformation, 162 NTSTATUS ret = g_nt.QueryInformationProcess(process, ProcessBasicInformation,
281 &proc_info, sizeof(proc_info), 163 &proc_info, sizeof(proc_info),
282 &bytes_returned); 164 &bytes_returned);
283 if (!NT_SUCCESS(ret) || sizeof(proc_info) != bytes_returned) 165 if (!NT_SUCCESS(ret) || sizeof(proc_info) != bytes_returned)
284 return ret; 166 return ret;
285 167
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
424 } 306 }
425 if (!NT_SUCCESS(ret)) { 307 if (!NT_SUCCESS(ret)) {
426 operator delete(section_name, NT_ALLOC); 308 operator delete(section_name, NT_ALLOC);
427 return NULL; 309 return NULL;
428 } 310 }
429 311
430 return reinterpret_cast<UNICODE_STRING*>(section_name); 312 return reinterpret_cast<UNICODE_STRING*>(section_name);
431 } 313 }
432 } 314 }
433 315
434 UNICODE_STRING* ExtractModuleName(const UNICODE_STRING* module_path) {
435 if ((!module_path) || (!module_path->Buffer))
436 return NULL;
437
438 wchar_t* sep = NULL;
439 int start_pos = module_path->Length / sizeof(wchar_t) - 1;
440 int ix = start_pos;
441
442 for (; ix >= 0; --ix) {
443 if (module_path->Buffer[ix] == L'\\') {
444 sep = &module_path->Buffer[ix];
445 break;
446 }
447 }
448
449 // Ends with path separator. Not a valid module name.
450 if ((ix == start_pos) && sep)
451 return NULL;
452
453 // No path separator found. Use the entire name.
454 if (!sep) {
455 sep = &module_path->Buffer[-1];
456 }
457
458 // Add one to the size so we can null terminate the string.
459 size_t size_bytes = (start_pos - ix + 1) * sizeof(wchar_t);
460
461 // Based on the code above, size_bytes should always be small enough
462 // to make the static_cast below safe.
463 DCHECK_NT(kuint16max > size_bytes);
464 char* str_buffer = new(NT_ALLOC) char[size_bytes + sizeof(UNICODE_STRING)];
465 if (!str_buffer)
466 return NULL;
467
468 UNICODE_STRING* out_string = reinterpret_cast<UNICODE_STRING*>(str_buffer);
469 out_string->Buffer = reinterpret_cast<wchar_t*>(&out_string[1]);
470 out_string->Length = static_cast<USHORT>(size_bytes - sizeof(wchar_t));
471 out_string->MaximumLength = static_cast<USHORT>(size_bytes);
472
473 NTSTATUS ret = CopyData(out_string->Buffer, &sep[1], out_string->Length);
474 if (!NT_SUCCESS(ret)) {
475 operator delete(out_string, NT_ALLOC);
476 return NULL;
477 }
478
479 out_string->Buffer[out_string->Length / sizeof(wchar_t)] = L'\0';
480 return out_string;
481 }
482
483 NTSTATUS AutoProtectMemory::ChangeProtection(void* address, size_t bytes, 316 NTSTATUS AutoProtectMemory::ChangeProtection(void* address, size_t bytes,
484 ULONG protect) { 317 ULONG protect) {
485 DCHECK_NT(!changed_); 318 DCHECK_NT(!changed_);
486 SIZE_T new_bytes = bytes; 319 SIZE_T new_bytes = bytes;
487 NTSTATUS ret = g_nt.ProtectVirtualMemory(NtCurrentProcess, &address, 320 NTSTATUS ret = g_nt.ProtectVirtualMemory(NtCurrentProcess, &address,
488 &new_bytes, protect, &old_protect_); 321 &new_bytes, protect, &old_protect_);
489 if (NT_SUCCESS(ret)) { 322 if (NT_SUCCESS(ret)) {
490 changed_ = true; 323 changed_ = true;
491 address_ = address; 324 address_ = address;
492 bytes_ = new_bytes; 325 bytes_ = new_bytes;
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
539 372
540 if (file_info->FileName[0] != L'\\' || 373 if (file_info->FileName[0] != L'\\' ||
541 file_info->FileName[1] != L'?' || 374 file_info->FileName[1] != L'?' ||
542 file_info->FileName[2] != L'?' || 375 file_info->FileName[2] != L'?' ||
543 file_info->FileName[3] != L'\\') 376 file_info->FileName[3] != L'\\')
544 return false; 377 return false;
545 378
546 return true; 379 return true;
547 } 380 }
548 381
382 bool WriteProtectedChildMemory(HANDLE child_process, void* address,
383 const void* buffer, size_t length) {
384 // First, remove the protections.
385 DWORD old_protection;
386 if (!::VirtualProtectEx(child_process, address, length,
rvargas (doing something else) 2013/11/26 20:42:12 This, on the other hand, is not part of the nt lay
robertshield 2013/11/27 20:28:01 Moved it back.
387 PAGE_WRITECOPY, &old_protection))
388 return false;
389
390 SIZE_T written;
391 bool ok = ::WriteProcessMemory(child_process, address, buffer, length,
392 &written) && (length == written);
393
394 // Always attempt to restore the original protection.
395 if (!::VirtualProtectEx(child_process, address, length,
396 old_protection, &old_protection))
397 return false;
398
399 return ok;
400 }
401
549 } // namespace sandbox 402 } // namespace sandbox
550 403
551 void* operator new(size_t size, sandbox::AllocationType type, 404 void* operator new(size_t size, sandbox::AllocationType type,
552 void* near_to) { 405 void* near_to) {
553 using namespace sandbox; 406 using namespace sandbox;
554 407
555 if (NT_ALLOC == type) { 408 if (NT_ALLOC == type) {
556 if (!InitHeap()) 409 if (!InitHeap())
557 return NULL; 410 return NULL;
558 411
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
593 UNREFERENCED_PARAMETER(type); 446 UNREFERENCED_PARAMETER(type);
594 return buffer; 447 return buffer;
595 } 448 }
596 449
597 void __cdecl operator delete(void* memory, void* buffer, 450 void __cdecl operator delete(void* memory, void* buffer,
598 sandbox::AllocationType type) { 451 sandbox::AllocationType type) {
599 UNREFERENCED_PARAMETER(memory); 452 UNREFERENCED_PARAMETER(memory);
600 UNREFERENCED_PARAMETER(buffer); 453 UNREFERENCED_PARAMETER(buffer);
601 UNREFERENCED_PARAMETER(type); 454 UNREFERENCED_PARAMETER(type);
602 } 455 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698