Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 |
| 11 namespace sandbox { | 11 namespace sandbox { |
| 12 | 12 |
| 13 // This is the list of all imported symbols from ntdll.dll. | 13 // This is the list of all imported symbols from ntdll.dll. |
| 14 SANDBOX_INTERCEPT NtExports g_nt = { NULL }; | 14 SANDBOX_INTERCEPT NtExports g_nt; |
| 15 | 15 |
| 16 } // namespace sandbox | 16 } // namespace sandbox |
| 17 | 17 |
| 18 namespace { | 18 namespace { |
| 19 | 19 |
| 20 #if defined(_WIN64) | 20 #if defined(_WIN64) |
| 21 void* AllocateNearTo(void* source, size_t size) { | 21 void* AllocateNearTo(void* source, size_t size) { |
| 22 using sandbox::g_nt; | 22 using sandbox::g_nt; |
| 23 | 23 |
| 24 // Start with 1 GB above the source. | 24 // Start with 1 GB above the source. |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 97 if (!NT_SUCCESS(ret)) | 97 if (!NT_SUCCESS(ret)) |
| 98 return NULL; | 98 return NULL; |
| 99 return base; | 99 return base; |
| 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 // This is the list of all imported symbols from ntdll.dll. |
| 108 void* g_heap = NULL; | 108 SANDBOX_INTERCEPT NtExports g_nt; |
|
rvargas (doing something else)
2013/11/27 23:53:51
This is already defined up there
robertshield
2013/11/29 01:21:26
Done.
| |
| 109 | 109 |
| 110 SANDBOX_INTERCEPT HANDLE g_shared_section; | 110 SANDBOX_INTERCEPT HANDLE g_shared_section; |
| 111 SANDBOX_INTERCEPT size_t g_shared_IPC_size = 0; | 111 SANDBOX_INTERCEPT size_t g_shared_IPC_size = 0; |
| 112 SANDBOX_INTERCEPT size_t g_shared_policy_size = 0; | 112 SANDBOX_INTERCEPT size_t g_shared_policy_size = 0; |
| 113 | 113 |
| 114 void* volatile g_shared_policy_memory = NULL; | 114 void* volatile g_shared_policy_memory = NULL; |
| 115 void* volatile g_shared_IPC_memory = NULL; | 115 void* volatile g_shared_IPC_memory = NULL; |
| 116 | 116 |
| 117 // Both the IPC and the policy share a single region of memory in which the IPC | 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. | 118 // memory is first and the policy memory is last. |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 150 return NULL; | 150 return NULL; |
| 151 return g_shared_IPC_memory; | 151 return g_shared_IPC_memory; |
| 152 } | 152 } |
| 153 | 153 |
| 154 void* GetGlobalPolicyMemory() { | 154 void* GetGlobalPolicyMemory() { |
| 155 if (!MapGlobalMemory()) | 155 if (!MapGlobalMemory()) |
| 156 return NULL; | 156 return NULL; |
| 157 return g_shared_policy_memory; | 157 return g_shared_policy_memory; |
| 158 } | 158 } |
| 159 | 159 |
| 160 // Handle for our private heap. | |
| 161 void* g_heap = NULL; | |
|
rvargas (doing something else)
2013/11/27 23:53:51
don't move this to the middle of the file. The com
robertshield
2013/11/29 01:21:26
Done.
| |
| 162 | |
| 160 bool InitHeap() { | 163 bool InitHeap() { |
| 161 if (!g_heap) { | 164 if (!g_heap) { |
| 162 // Create a new heap using default values for everything. | 165 // Create a new heap using default values for everything. |
| 163 void* heap = g_nt.RtlCreateHeap(HEAP_GROWABLE, NULL, 0, 0, NULL, NULL); | 166 void* heap = g_nt.RtlCreateHeap(HEAP_GROWABLE, NULL, 0, 0, NULL, NULL); |
| 164 if (!heap) | 167 if (!heap) |
| 165 return false; | 168 return false; |
| 166 | 169 |
| 167 if (NULL != _InterlockedCompareExchangePointer(&g_heap, heap, NULL)) { | 170 if (NULL != _InterlockedCompareExchangePointer(&g_heap, heap, NULL)) { |
| 168 // Somebody beat us to the memory setup. | 171 // Somebody beat us to the memory setup. |
| 169 g_nt.RtlDestroyHeap(heap); | 172 g_nt.RtlDestroyHeap(heap); |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 198 bool ValidParameter(void* buffer, size_t size, RequiredAccess intent) { | 201 bool ValidParameter(void* buffer, size_t size, RequiredAccess intent) { |
| 199 DCHECK_NT(size); | 202 DCHECK_NT(size); |
| 200 __try { | 203 __try { |
| 201 TouchMemory(buffer, size, intent); | 204 TouchMemory(buffer, size, intent); |
| 202 } __except(EXCEPTION_EXECUTE_HANDLER) { | 205 } __except(EXCEPTION_EXECUTE_HANDLER) { |
| 203 return false; | 206 return false; |
| 204 } | 207 } |
| 205 return true; | 208 return true; |
| 206 } | 209 } |
| 207 | 210 |
| 208 NTSTATUS CopyData(void* destination, const void* source, size_t bytes) { | |
|
rvargas (doing something else)
2013/11/27 23:53:51
I presume this is being moved to nt_util_base. I h
rvargas (doing something else)
2013/11/27 23:53:51
After looking at the whole patch I see that interc
rvargas (doing something else)
2013/11/27 23:58:52
There is nt!memcpy (at least on Win7 but i expect
robertshield
2013/11/29 01:21:26
Done.
robertshield
2013/11/29 01:21:26
Done.
robertshield
2013/11/29 01:21:26
And this solves all known problems. Using nt's mem
| |
| 209 NTSTATUS ret = STATUS_SUCCESS; | |
| 210 __try { | |
| 211 if (SandboxFactory::GetTargetServices()->GetState()->InitCalled()) { | |
| 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) { | 211 NTSTATUS GetProcessId(HANDLE process, ULONG *process_id) { |
| 277 PROCESS_BASIC_INFORMATION proc_info; | 212 PROCESS_BASIC_INFORMATION proc_info; |
| 278 ULONG bytes_returned; | 213 ULONG bytes_returned; |
| 279 | 214 |
| 280 NTSTATUS ret = g_nt.QueryInformationProcess(process, ProcessBasicInformation, | 215 NTSTATUS ret = g_nt.QueryInformationProcess(process, ProcessBasicInformation, |
| 281 &proc_info, sizeof(proc_info), | 216 &proc_info, sizeof(proc_info), |
| 282 &bytes_returned); | 217 &bytes_returned); |
| 283 if (!NT_SUCCESS(ret) || sizeof(proc_info) != bytes_returned) | 218 if (!NT_SUCCESS(ret) || sizeof(proc_info) != bytes_returned) |
| 284 return ret; | 219 return ret; |
| 285 | 220 |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 424 } | 359 } |
| 425 if (!NT_SUCCESS(ret)) { | 360 if (!NT_SUCCESS(ret)) { |
| 426 operator delete(section_name, NT_ALLOC); | 361 operator delete(section_name, NT_ALLOC); |
| 427 return NULL; | 362 return NULL; |
| 428 } | 363 } |
| 429 | 364 |
| 430 return reinterpret_cast<UNICODE_STRING*>(section_name); | 365 return reinterpret_cast<UNICODE_STRING*>(section_name); |
| 431 } | 366 } |
| 432 } | 367 } |
| 433 | 368 |
| 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, | 369 NTSTATUS AutoProtectMemory::ChangeProtection(void* address, size_t bytes, |
| 484 ULONG protect) { | 370 ULONG protect) { |
| 485 DCHECK_NT(!changed_); | 371 DCHECK_NT(!changed_); |
| 486 SIZE_T new_bytes = bytes; | 372 SIZE_T new_bytes = bytes; |
| 487 NTSTATUS ret = g_nt.ProtectVirtualMemory(NtCurrentProcess, &address, | 373 NTSTATUS ret = g_nt.ProtectVirtualMemory(NtCurrentProcess, &address, |
| 488 &new_bytes, protect, &old_protect_); | 374 &new_bytes, protect, &old_protect_); |
| 489 if (NT_SUCCESS(ret)) { | 375 if (NT_SUCCESS(ret)) { |
| 490 changed_ = true; | 376 changed_ = true; |
| 491 address_ = address; | 377 address_ = address; |
| 492 bytes_ = new_bytes; | 378 bytes_ = new_bytes; |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 593 UNREFERENCED_PARAMETER(type); | 479 UNREFERENCED_PARAMETER(type); |
| 594 return buffer; | 480 return buffer; |
| 595 } | 481 } |
| 596 | 482 |
| 597 void __cdecl operator delete(void* memory, void* buffer, | 483 void __cdecl operator delete(void* memory, void* buffer, |
| 598 sandbox::AllocationType type) { | 484 sandbox::AllocationType type) { |
| 599 UNREFERENCED_PARAMETER(memory); | 485 UNREFERENCED_PARAMETER(memory); |
| 600 UNREFERENCED_PARAMETER(buffer); | 486 UNREFERENCED_PARAMETER(buffer); |
| 601 UNREFERENCED_PARAMETER(type); | 487 UNREFERENCED_PARAMETER(type); |
| 602 } | 488 } |
| OLD | NEW |