Index: sandbox/win/src/sandbox_utils.cc |
diff --git a/sandbox/win/src/sandbox_utils.cc b/sandbox/win/src/sandbox_utils.cc |
index f4511a475136b2edec8fce1f1886f34d78b904b2..c3f7dbbdf5d582a0068ecc47068f0a80d487c979 100644 |
--- a/sandbox/win/src/sandbox_utils.cc |
+++ b/sandbox/win/src/sandbox_utils.cc |
@@ -1,17 +1,191 @@ |
-// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
+// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
#include "sandbox/win/src/sandbox_utils.h" |
-#include <windows.h> |
- |
#include "base/logging.h" |
#include "base/win/windows_version.h" |
#include "sandbox/win/src/internal_types.h" |
+#include "sandbox/win/src/sandbox_factory.h" |
+#include "sandbox/win/src/sandbox_nt_types.h" |
+#include "sandbox/win/src/sandbox_nt_util.h" |
+#include "sandbox/win/src/target_services.h" |
namespace sandbox { |
+// This is the list of all imported symbols from ntdll.dll. |
+SANDBOX_INTERCEPT NtExports g_nt; |
+ |
+SANDBOX_INTERCEPT HANDLE g_shared_section; |
+SANDBOX_INTERCEPT size_t g_shared_IPC_size = 0; |
+SANDBOX_INTERCEPT size_t g_shared_policy_size = 0; |
+ |
+void* volatile g_shared_policy_memory = NULL; |
+void* volatile g_shared_IPC_memory = NULL; |
+ |
+// Both the IPC and the policy share a single region of memory in which the IPC |
+// memory is first and the policy memory is last. |
+bool MapGlobalMemory() { |
+ if (NULL == g_shared_IPC_memory) { |
+ void* memory = NULL; |
+ SIZE_T size = 0; |
+ // Map the entire shared section from the start. |
+ NTSTATUS ret = g_nt.MapViewOfSection(g_shared_section, NtCurrentProcess, |
+ &memory, 0, 0, NULL, &size, ViewUnmap, |
+ 0, PAGE_READWRITE); |
+ |
+ if (!NT_SUCCESS(ret) || NULL == memory) { |
+ NOTREACHED_NT(); |
+ return false; |
+ } |
+ |
+ if (NULL != _InterlockedCompareExchangePointer(&g_shared_IPC_memory, |
+ memory, NULL)) { |
+ // Somebody beat us to the memory setup. |
+ ret = g_nt.UnmapViewOfSection(NtCurrentProcess, memory); |
+ VERIFY_SUCCESS(ret); |
+ } |
+ DCHECK_NT(g_shared_IPC_size > 0); |
+ g_shared_policy_memory = reinterpret_cast<char*>(g_shared_IPC_memory) |
+ + g_shared_IPC_size; |
+ } |
+ DCHECK_NT(g_shared_policy_memory); |
+ DCHECK_NT(g_shared_policy_size > 0); |
+ return true; |
+} |
+ |
+void* GetGlobalIPCMemory() { |
+ if (!MapGlobalMemory()) |
+ return NULL; |
+ return g_shared_IPC_memory; |
+} |
+ |
+void* GetGlobalPolicyMemory() { |
+ if (!MapGlobalMemory()) |
+ return NULL; |
+ return g_shared_policy_memory; |
+} |
+ |
+NTSTATUS CopyData(void* destination, const void* source, size_t bytes) { |
+ NTSTATUS ret = STATUS_SUCCESS; |
+ __try { |
+ if (SandboxFactory::GetTargetServices()->GetState()->InitCalled()) { |
+ memcpy(destination, source, bytes); |
+ } else { |
+ const char* from = reinterpret_cast<const char*>(source); |
+ char* to = reinterpret_cast<char*>(destination); |
+ for (size_t i = 0; i < bytes; i++) { |
+ to[i] = from[i]; |
+ } |
+ } |
+ } __except(EXCEPTION_EXECUTE_HANDLER) { |
+ ret = GetExceptionCode(); |
+ } |
+ return ret; |
+} |
+ |
+ |
+// Hacky code... replace with AllocAndCopyObjectAttributes. |
+NTSTATUS AllocAndCopyName(const OBJECT_ATTRIBUTES* in_object, |
+ wchar_t** out_name, uint32* attributes, |
+ HANDLE* root) { |
+ if (!InitHeap()) |
+ return STATUS_NO_MEMORY; |
+ |
+ DCHECK_NT(out_name); |
+ *out_name = NULL; |
+ NTSTATUS ret = STATUS_UNSUCCESSFUL; |
+ __try { |
+ do { |
+ if (in_object->RootDirectory != static_cast<HANDLE>(0) && !root) |
+ break; |
+ if (NULL == in_object->ObjectName) |
+ break; |
+ if (NULL == in_object->ObjectName->Buffer) |
+ break; |
+ |
+ size_t size = in_object->ObjectName->Length + sizeof(wchar_t); |
+ *out_name = new(NT_ALLOC) wchar_t[size/sizeof(wchar_t)]; |
+ if (NULL == *out_name) |
+ break; |
+ |
+ ret = CopyData(*out_name, in_object->ObjectName->Buffer, |
+ size - sizeof(wchar_t)); |
+ if (!NT_SUCCESS(ret)) |
+ break; |
+ |
+ (*out_name)[size / sizeof(wchar_t) - 1] = L'\0'; |
+ |
+ if (attributes) |
+ *attributes = in_object->Attributes; |
+ |
+ if (root) |
+ *root = in_object->RootDirectory; |
+ ret = STATUS_SUCCESS; |
+ } while (false); |
+ } __except(EXCEPTION_EXECUTE_HANDLER) { |
+ ret = GetExceptionCode(); |
+ } |
+ |
+ if (!NT_SUCCESS(ret) && *out_name) { |
+ operator delete(*out_name, NT_ALLOC); |
+ *out_name = NULL; |
+ } |
+ |
+ return ret; |
+} |
+ |
+ |
+UNICODE_STRING* ExtractModuleName(const UNICODE_STRING* module_path) { |
+ if ((!module_path) || (!module_path->Buffer)) |
+ return NULL; |
+ |
+ wchar_t* sep = NULL; |
+ int start_pos = module_path->Length / sizeof(wchar_t) - 1; |
+ int ix = start_pos; |
+ |
+ for (; ix >= 0; --ix) { |
+ if (module_path->Buffer[ix] == L'\\') { |
+ sep = &module_path->Buffer[ix]; |
+ break; |
+ } |
+ } |
+ |
+ // Ends with path separator. Not a valid module name. |
+ if ((ix == start_pos) && sep) |
+ return NULL; |
+ |
+ // No path separator found. Use the entire name. |
+ if (!sep) { |
+ sep = &module_path->Buffer[-1]; |
+ } |
+ |
+ // Add one to the size so we can null terminate the string. |
+ size_t size_bytes = (start_pos - ix + 1) * sizeof(wchar_t); |
+ |
+ // Based on the code above, size_bytes should always be small enough |
+ // to make the static_cast below safe. |
+ DCHECK_NT(kuint16max > size_bytes); |
+ char* str_buffer = new(NT_ALLOC) char[size_bytes + sizeof(UNICODE_STRING)]; |
+ if (!str_buffer) |
+ return NULL; |
+ |
+ UNICODE_STRING* out_string = reinterpret_cast<UNICODE_STRING*>(str_buffer); |
+ out_string->Buffer = reinterpret_cast<wchar_t*>(&out_string[1]); |
+ out_string->Length = static_cast<USHORT>(size_bytes - sizeof(wchar_t)); |
+ out_string->MaximumLength = static_cast<USHORT>(size_bytes); |
+ |
+ NTSTATUS ret = CopyData(out_string->Buffer, &sep[1], out_string->Length); |
+ if (!NT_SUCCESS(ret)) { |
+ operator delete(out_string, NT_ALLOC); |
+ return NULL; |
+ } |
+ |
+ out_string->Buffer[out_string->Length / sizeof(wchar_t)] = L'\0'; |
+ return out_string; |
+} |
+ |
bool IsXPSP2OrLater() { |
base::win::Version version = base::win::GetVersion(); |
return (version > base::win::VERSION_XP) || |
@@ -19,7 +193,7 @@ bool IsXPSP2OrLater() { |
(base::win::OSInfo::GetInstance()->service_pack().major >= 2)); |
} |
-void InitObjectAttribs(const std::wstring& name, |
+void InitObjectAttribs(const string16& name, |
ULONG attributes, |
HANDLE root, |
OBJECT_ATTRIBUTES* obj_attr, |
@@ -28,11 +202,11 @@ void InitObjectAttribs(const std::wstring& name, |
if (!RtlInitUnicodeString) { |
HMODULE ntdll = ::GetModuleHandle(kNtdllName); |
RtlInitUnicodeString = reinterpret_cast<RtlInitUnicodeStringFunction>( |
- GetProcAddress(ntdll, "RtlInitUnicodeString")); |
+ GetProcAddress(ntdll, "RtlInitUnicodeString")); |
DCHECK(RtlInitUnicodeString); |
} |
RtlInitUnicodeString(uni_name, name.c_str()); |
InitializeObjectAttributes(obj_attr, uni_name, attributes, root, NULL); |
} |
-}; // namespace sandbox |
+} // namespace sandbox |