| 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
|
|
|