summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--content/browser/handle_enumerator_win.cc139
-rw-r--r--content/browser/handle_enumerator_win.h1
-rw-r--r--content/content_browser.gypi6
-rw-r--r--sandbox/sandbox.gyp3
-rw-r--r--sandbox/src/handle_table.cc195
-rw-r--r--sandbox/src/handle_table.h161
-rw-r--r--sandbox/src/handle_table_unittest.cc66
-rw-r--r--sandbox/src/nt_internals.h87
8 files changed, 566 insertions, 92 deletions
diff --git a/content/browser/handle_enumerator_win.cc b/content/browser/handle_enumerator_win.cc
index 3eec4c2..f16e491 100644
--- a/content/browser/handle_enumerator_win.cc
+++ b/content/browser/handle_enumerator_win.cc
@@ -5,6 +5,7 @@
#include "content/browser/handle_enumerator_win.h"
#include <windows.h>
+#include <map>
#include "base/logging.h"
#include "base/process.h"
@@ -15,7 +16,40 @@
#include "content/browser/browser_thread.h"
#include "content/browser/renderer_host/render_process_host.h"
#include "content/common/result_codes.h"
-#include "sandbox/tools/finder/ntundoc.h"
+#include "sandbox/src/handle_table.h"
+
+namespace {
+
+typedef std::map<const string16, content::HandleType> HandleTypeMap;
+
+HandleTypeMap& MakeHandleTypeMap() {
+ HandleTypeMap& handle_types = *(new HandleTypeMap());
+ handle_types[sandbox::HandleTable::kTypeProcess] = content::ProcessHandle;
+ handle_types[sandbox::HandleTable::kTypeThread] = content::ThreadHandle;
+ handle_types[sandbox::HandleTable::kTypeFile] = content::FileHandle;
+ handle_types[sandbox::HandleTable::kTypeDirectory] =
+ content::DirectoryHandle;
+ handle_types[sandbox::HandleTable::kTypeKey] = content::KeyHandle;
+ handle_types[sandbox::HandleTable::kTypeWindowStation] =
+ content::WindowStationHandle;
+ handle_types[sandbox::HandleTable::kTypeDesktop] = content::DesktopHandle;
+ handle_types[sandbox::HandleTable::kTypeService] = content::ServiceHandle;
+ handle_types[sandbox::HandleTable::kTypeMutex] = content::MutexHandle;
+ handle_types[sandbox::HandleTable::kTypeSemaphore] =
+ content::SemaphoreHandle;
+ handle_types[sandbox::HandleTable::kTypeEvent] = content::EventHandle;
+ handle_types[sandbox::HandleTable::kTypeTimer] = content::TimerHandle;
+ handle_types[sandbox::HandleTable::kTypeNamedPipe] =
+ content::NamedPipeHandle;
+ handle_types[sandbox::HandleTable::kTypeJobObject] = content::JobHandle;
+ handle_types[sandbox::HandleTable::kTypeFileMap] = content::FileMapHandle;
+ handle_types[sandbox::HandleTable::kTypeAlpcPort] =
+ content::AlpcPortHandle;
+
+ return handle_types;
+}
+
+} // namespace
namespace content {
@@ -23,65 +57,14 @@ const wchar_t kNtdllDllName[] = L"ntdll.dll";
const size_t kMaxHandleNameLength = 1024;
void HandleEnumerator::EnumerateHandles() {
- ULONG pid = 0;
- pid = ::GetProcessId(handle_);
- if (!pid)
- return;
- ULONG handle_info_size = 0x10000;
- HMODULE ntdll = ::GetModuleHandle(kNtdllDllName);
- if (!ntdll)
- return;
-
- NTQUERYSYSTEMINFORMATION NtQuerySystemInformation =
- reinterpret_cast<NTQUERYSYSTEMINFORMATION>(
- GetProcAddress(ntdll, "NtQuerySystemInformation"));
- NTQUERYOBJECT NtQueryObject =
- reinterpret_cast<NTQUERYOBJECT>(GetProcAddress(ntdll, "NtQueryObject"));
-
- if (!NtQuerySystemInformation || !NtQueryObject)
- return;
-
- SYSTEM_HANDLE_INFORMATION_EX* handle_info =
- reinterpret_cast<SYSTEM_HANDLE_INFORMATION_EX*>(
- new BYTE[handle_info_size]);
- while (NtQuerySystemInformation(SystemHandleInformation,
- handle_info,
- handle_info_size,
- &handle_info_size)
- == STATUS_INFO_LENGTH_MISMATCH) {
- delete handle_info;
- handle_info = reinterpret_cast<SYSTEM_HANDLE_INFORMATION_EX*>
- (new BYTE[handle_info_size]);
- }
+ sandbox::HandleTable handles;
string16 output = ProcessTypeString(type_);
output.append(ASCIIToUTF16(" Process - Handles at shutdown:\n"));
- for (UINT i = 0; i < handle_info->NumberOfHandles; i++) {
- SYSTEM_HANDLE_INFORMATION sys_handle = handle_info->Information[i];
- HANDLE handle = reinterpret_cast<HANDLE>(sys_handle.Handle);
- if (sys_handle.ProcessId != pid)
- continue;
-
- OBJECT_TYPE_INFORMATION* type_info =
- reinterpret_cast<OBJECT_TYPE_INFORMATION*>(
- new BYTE[sizeof(OBJECT_TYPE_INFORMATION) + kMaxHandleNameLength]);
- if (NtQueryObject(handle, ObjectTypeInformation, type_info,
- sizeof(OBJECT_TYPE_INFORMATION) + kMaxHandleNameLength, NULL) < 0)
- return;
-
- UNICODE_STRING* name = reinterpret_cast<UNICODE_STRING*>(
- new BYTE[kMaxHandleNameLength]);
- if (NtQueryObject(handle, ObjectNameInformation, name,
- kMaxHandleNameLength, NULL) < 0)
- return;
-
- string16 handle_type;
- string16 handle_name;
- WideToUTF16(type_info->Name.Buffer,
- type_info->Name.Length/2, &handle_type);
- WideToUTF16(name->Buffer, name->Length/2, &handle_name);
-
- HandleType current_type = StringToHandleType(handle_type);
+ for (sandbox::HandleTable::Iterator sys_handle
+ = handles.HandlesForProcess(::GetProcessId(handle_));
+ sys_handle != handles.end(); ++sys_handle) {
+ HandleType current_type = StringToHandleType(sys_handle->Type());
if (!all_handles_ && (current_type != ProcessHandle &&
current_type != FileHandle &&
current_type != DirectoryHandle &&
@@ -92,13 +75,13 @@ void HandleEnumerator::EnumerateHandles() {
continue;
output += ASCIIToUTF16("[");
- output += handle_type;
+ output += sys_handle->Type();
output += ASCIIToUTF16("] (");
- output += handle_name;
+ output += sys_handle->Name();
output += ASCIIToUTF16(")\n");
- output += GetAccessString(current_type, sys_handle.GrantedAccess);
+ output += GetAccessString(current_type,
+ sys_handle->handle_entry()->GrantedAccess);
}
- delete handle_info;
LOG(INFO) << output;
}
@@ -213,37 +196,9 @@ string16 ProcessTypeString(ChildProcessInfo::ProcessType process_type) {
}
HandleType StringToHandleType(const string16& type) {
- if (!type.compare(ASCIIToUTF16("Process")))
- return ProcessHandle;
- else if (!type.compare(ASCIIToUTF16("Thread")))
- return ThreadHandle;
- else if (!type.compare(ASCIIToUTF16("File")))
- return FileHandle;
- else if (!type.compare(ASCIIToUTF16("Directory")))
- return DirectoryHandle;
- else if (!type.compare(ASCIIToUTF16("Key")))
- return KeyHandle;
- else if (!type.compare(ASCIIToUTF16("WindowStation")))
- return WindowStationHandle;
- else if (!type.compare(ASCIIToUTF16("Desktop")))
- return DesktopHandle;
- else if (!type.compare(ASCIIToUTF16("Service")))
- return ServiceHandle;
- else if (!type.compare(ASCIIToUTF16("Mutex")))
- return MutexHandle;
- else if (!type.compare(ASCIIToUTF16("Semaphore")))
- return SemaphoreHandle;
- else if (!type.compare(ASCIIToUTF16("Event")))
- return EventHandle;
- else if (!type.compare(ASCIIToUTF16("Timer")))
- return TimerHandle;
- else if (!type.compare(ASCIIToUTF16("NamedPipe")))
- return NamedPipeHandle;
- else if (!type.compare(ASCIIToUTF16("JobObject")))
- return JobHandle;
- else if (!type.compare(ASCIIToUTF16("FileMap")))
- return FileMapHandle;
- return OtherHandle;
+ static HandleTypeMap handle_types = MakeHandleTypeMap();
+ HandleTypeMap::iterator result = handle_types.find(type);
+ return result != handle_types.end() ? result->second : OtherHandle;
}
string16 GetAccessString(HandleType handle_type,
diff --git a/content/browser/handle_enumerator_win.h b/content/browser/handle_enumerator_win.h
index 8b49d1f..12b426c 100644
--- a/content/browser/handle_enumerator_win.h
+++ b/content/browser/handle_enumerator_win.h
@@ -27,6 +27,7 @@ enum HandleType {
NamedPipeHandle,
JobHandle,
FileMapHandle,
+ AlpcPortHandle,
OtherHandle
};
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index e41827f..909478f 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -422,6 +422,12 @@
'browser/renderer_host/p2p/socket_dispatcher_host.h',
],
}],
+ ['OS=="win"', {
+ 'dependencies': [
+ # For enable-handle-auditing switch
+ '../sandbox/sandbox.gyp:sandbox',
+ ],
+ }],
['toolkit_uses_gtk == 1', {
'dependencies': [
'../build/linux/system.gyp:dbus-glib',
diff --git a/sandbox/sandbox.gyp b/sandbox/sandbox.gyp
index 6a91af6..914a9d7 100644
--- a/sandbox/sandbox.gyp
+++ b/sandbox/sandbox.gyp
@@ -33,6 +33,8 @@
'src/filesystem_interception.h',
'src/filesystem_policy.cc',
'src/filesystem_policy.h',
+ 'src/handle_table.cc',
+ 'src/handle_table.h',
'src/interception.cc',
'src/interception.h',
'src/interception_agent.cc',
@@ -317,6 +319,7 @@
'tests/common/test_utils.cc',
'tests/common/test_utils.h',
'tests/unit_tests/unit_tests.cc',
+ 'src/handle_table_unittest.cc',
'src/interception_unittest.cc',
'src/service_resolver_unittest.cc',
'src/restricted_token_unittest.cc',
diff --git a/sandbox/src/handle_table.cc b/sandbox/src/handle_table.cc
new file mode 100644
index 0000000..be84fa3
--- /dev/null
+++ b/sandbox/src/handle_table.cc
@@ -0,0 +1,195 @@
+// Copyright (c) 2011 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/src/handle_table.h"
+
+#include <algorithm>
+#include <cstdlib>
+
+#include "base/memory/scoped_ptr.h"
+
+namespace {
+
+const wchar_t kNtdllDllName[] = L"ntdll.dll";
+
+bool CompareHandleEntries(const SYSTEM_HANDLE_INFORMATION& a,
+ const SYSTEM_HANDLE_INFORMATION& b) {
+ return a.ProcessId < b.ProcessId;
+}
+
+} // namespace
+
+namespace sandbox {
+
+HMODULE HandleTable::ntdll_ = 0;
+const char16* HandleTable::kTypeProcess = L"Process";
+const char16* HandleTable::kTypeThread = L"Thread";
+const char16* HandleTable::kTypeFile = L"File";
+const char16* HandleTable::kTypeDirectory = L"Directory";
+const char16* HandleTable::kTypeKey = L"Key";
+const char16* HandleTable::kTypeWindowStation = L"WindowStation";
+const char16* HandleTable::kTypeDesktop = L"Desktop";
+const char16* HandleTable::kTypeService = L"Service";
+const char16* HandleTable::kTypeMutex = L"Mutex";
+const char16* HandleTable::kTypeSemaphore = L"Semaphore";
+const char16* HandleTable::kTypeEvent = L"Event";
+const char16* HandleTable::kTypeTimer = L"Timer";
+const char16* HandleTable::kTypeNamedPipe = L"NamedPipe";
+const char16* HandleTable::kTypeJobObject = L"JobObject";
+const char16* HandleTable::kTypeFileMap = L"FileMap";
+const char16* HandleTable::kTypeAlpcPort = L"ALPC Port";
+
+HandleTable::HandleTable() {
+ static NtQuerySystemInformation QuerySystemInformation;
+ if (!QuerySystemInformation) {
+ if (!ntdll_ && !(ntdll_ = ::GetModuleHandle(kNtdllDllName)))
+ return;
+ QuerySystemInformation = reinterpret_cast<NtQuerySystemInformation>(
+ ::GetProcAddress(ntdll_, "NtQuerySystemInformation"));
+ if (!QuerySystemInformation)
+ return;
+ }
+
+ ULONG size = 0x15000;
+ NTSTATUS result;
+ do {
+ handle_info_buffer_.resize(size);
+ result = QuerySystemInformation(SystemHandleInformation,
+ handle_info_internal(), size, &size);
+ } while (result == STATUS_INFO_LENGTH_MISMATCH);
+
+ // We failed, so make an empty table.
+ if (!NT_SUCCESS(result)) {
+ handle_info_buffer_.resize(0);
+ return;
+ }
+
+ // Sort it to make process lookups faster.
+ std::sort(handle_info_internal()->Information,
+ handle_info_internal()->Information +
+ handle_info_internal()->NumberOfHandles, CompareHandleEntries);
+}
+
+HandleTable::Iterator HandleTable::HandlesForProcess(ULONG process_id) const {
+ SYSTEM_HANDLE_INFORMATION key;
+ key.ProcessId = process_id;
+
+ const SYSTEM_HANDLE_INFORMATION* start = handle_info()->Information;
+ const SYSTEM_HANDLE_INFORMATION* finish =
+ &handle_info()->Information[handle_info()->NumberOfHandles];
+
+ start = std::lower_bound(start, finish, key, CompareHandleEntries);
+ if (start->ProcessId != process_id)
+ return Iterator(*this, finish, finish);
+ finish = std::upper_bound(start, finish, key, CompareHandleEntries);
+ return Iterator(*this, start, finish);
+}
+
+HandleTable::HandleEntry::HandleEntry(
+ const SYSTEM_HANDLE_INFORMATION* handle_info_entry)
+ : handle_entry_(handle_info_entry), last_entry_(0) {
+}
+
+void HandleTable::HandleEntry::UpdateInfo(UpdateType flag) {
+ static NtQueryObject QueryObject;
+ if (!QueryObject) {
+ if (!ntdll_ && !(ntdll_ = ::GetModuleHandle(kNtdllDllName)))
+ return;
+ QueryObject = reinterpret_cast<NtQueryObject>(::GetProcAddress(ntdll_,
+ "NtQueryObject"));
+ if (!QueryObject)
+ return;
+ }
+
+ NTSTATUS result;
+
+ // Always update the basic type info, but grab the names as needed.
+ if (needs_info_update()) {
+ handle_name_.clear();
+ type_name_.clear();
+ last_entry_ = handle_entry_;
+
+ // Most handle names are very short, so start small and reuse this buffer.
+ if (type_info_buffer_.empty())
+ type_info_buffer_.resize(sizeof(OBJECT_TYPE_INFORMATION)
+ + (32 * sizeof(wchar_t)));
+ ULONG size = static_cast<ULONG>(type_info_buffer_.size());
+ result = QueryObject(reinterpret_cast<HANDLE>(handle_entry_->Handle),
+ ObjectTypeInformation, type_info_internal(), size, &size);
+ while (result == STATUS_INFO_LENGTH_MISMATCH) {
+ type_info_buffer_.resize(size);
+ result = QueryObject(reinterpret_cast<HANDLE>(handle_entry_->Handle),
+ ObjectTypeInformation, type_info_internal(), size, &size);
+ }
+
+ if (!NT_SUCCESS(result)) {
+ type_info_buffer_.clear();
+ return;
+ }
+ }
+
+ // Don't bother copying out names until we ask for them, and then cache them.
+ switch (flag) {
+ case UPDATE_INFO_AND_NAME:
+ if (type_info_buffer_.size() && handle_name_.empty()) {
+ ULONG size = MAX_PATH;
+ scoped_ptr<UNICODE_STRING> name;
+ do {
+ name.reset(reinterpret_cast<UNICODE_STRING*>(new BYTE[size]));
+ result = QueryObject(reinterpret_cast<HANDLE>(
+ handle_entry_->Handle), ObjectNameInformation, name.get(),
+ size, &size);
+ } while (result == STATUS_INFO_LENGTH_MISMATCH);
+
+ if (NT_SUCCESS(result)) {
+ handle_name_.assign(name->Buffer, name->Length / sizeof(wchar_t));
+ }
+ }
+ break;
+
+ case UPDATE_INFO_AND_TYPE_NAME:
+ if (!type_info_buffer_.empty() && type_info_internal()->Name.Buffer &&
+ type_name_.empty()) {
+ type_name_.assign(type_info_internal()->Name.Buffer,
+ type_info_internal()->Name.Length / sizeof(wchar_t));
+ }
+ break;
+ }
+}
+
+const OBJECT_TYPE_INFORMATION* HandleTable::HandleEntry::TypeInfo() {
+ UpdateInfo(UPDATE_INFO_ONLY);
+ return type_info_buffer_.empty() ? NULL : type_info_internal();
+}
+
+const string16& HandleTable::HandleEntry::Name() {
+ UpdateInfo(UPDATE_INFO_AND_NAME);
+ return handle_name_;
+}
+
+const string16& HandleTable::HandleEntry::Type() {
+ UpdateInfo(UPDATE_INFO_AND_TYPE_NAME);
+ return type_name_;
+}
+
+bool HandleTable::HandleEntry::IsType(const string16& type_string) {
+ UpdateInfo(UPDATE_INFO_ONLY);
+ if (type_info_buffer_.empty())
+ return false;
+ return type_string.compare(0,
+ type_info_internal()->Name.Length / sizeof(wchar_t),
+ type_info_internal()->Name.Buffer) == 0;
+}
+
+HandleTable::Iterator::Iterator(const HandleTable& table,
+ const SYSTEM_HANDLE_INFORMATION* start,
+ const SYSTEM_HANDLE_INFORMATION* end)
+ : table_(table), current_(start), end_(end) {
+}
+
+HandleTable::Iterator::Iterator(const Iterator& it)
+ : table_(it.table_), current_(it.current_.handle_entry_), end_(it.end_) {
+}
+
+} // namespace sandbox
diff --git a/sandbox/src/handle_table.h b/sandbox/src/handle_table.h
new file mode 100644
index 0000000..8d24524
--- /dev/null
+++ b/sandbox/src/handle_table.h
@@ -0,0 +1,161 @@
+// Copyright (c) 2011 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.
+
+#ifndef SANDBOX_SRC_HANDLE_TABLE_H_
+#define SANDBOX_SRC_HANDLE_TABLE_H_
+#pragma once
+
+#include <windows.h>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/string16.h"
+#include "sandbox/src/nt_internals.h"
+
+namespace sandbox {
+
+// HandleTable retrieves the global handle table and provides helper classes
+// for iterating through the table and retrieving handle info.
+class HandleTable {
+ public:
+ static const char16* HandleTable::kTypeProcess;
+ static const char16* HandleTable::kTypeThread;
+ static const char16* HandleTable::kTypeFile;
+ static const char16* HandleTable::kTypeDirectory;
+ static const char16* HandleTable::kTypeKey;
+ static const char16* HandleTable::kTypeWindowStation;
+ static const char16* HandleTable::kTypeDesktop;
+ static const char16* HandleTable::kTypeService;
+ static const char16* HandleTable::kTypeMutex;
+ static const char16* HandleTable::kTypeSemaphore;
+ static const char16* HandleTable::kTypeEvent;
+ static const char16* HandleTable::kTypeTimer;
+ static const char16* HandleTable::kTypeNamedPipe;
+ static const char16* HandleTable::kTypeJobObject;
+ static const char16* HandleTable::kTypeFileMap;
+ static const char16* HandleTable::kTypeAlpcPort;
+
+ class Iterator;
+
+ // Used by the iterator to provide simple caching accessors to handle data.
+ class HandleEntry {
+ public:
+ bool operator==(const HandleEntry& rhs) const {
+ return handle_entry_ == rhs.handle_entry_;
+ }
+
+ bool operator!=(const HandleEntry& rhs) const {
+ return handle_entry_ != rhs.handle_entry_;
+ }
+
+ const SYSTEM_HANDLE_INFORMATION* handle_entry() const {
+ return handle_entry_;
+ }
+
+ const OBJECT_TYPE_INFORMATION* TypeInfo();
+
+ const string16& Name();
+
+ const string16& Type();
+
+ bool IsType(const string16& type_string);
+
+ private:
+ friend class Iterator;
+ friend class HandleTable;
+
+ enum UpdateType {
+ UPDATE_INFO_ONLY,
+ UPDATE_INFO_AND_NAME,
+ UPDATE_INFO_AND_TYPE_NAME,
+ };
+
+ explicit HandleEntry(const SYSTEM_HANDLE_INFORMATION* handle_info_entry);
+
+ bool needs_info_update() { return handle_entry_ != last_entry_; }
+
+ void UpdateInfo(UpdateType flag);
+
+ OBJECT_TYPE_INFORMATION* type_info_internal() {
+ return reinterpret_cast<OBJECT_TYPE_INFORMATION*>(
+ &(type_info_buffer_[0]));
+ }
+
+ const SYSTEM_HANDLE_INFORMATION* handle_entry_;
+ const SYSTEM_HANDLE_INFORMATION* last_entry_;
+ std::vector<BYTE> type_info_buffer_;
+ string16 handle_name_;
+ string16 type_name_;
+
+ DISALLOW_COPY_AND_ASSIGN(HandleEntry);
+ };
+
+ class Iterator {
+ public:
+ Iterator(const HandleTable& table, const SYSTEM_HANDLE_INFORMATION* start,
+ const SYSTEM_HANDLE_INFORMATION* stop);
+
+ Iterator(const Iterator& it);
+
+ Iterator& operator++() {
+ if (++(current_.handle_entry_) == end_)
+ current_.handle_entry_ = table_.end();
+ return *this;
+ }
+
+ bool operator==(const Iterator& rhs) const {
+ return current_ == rhs.current_;
+ }
+
+ bool operator!=(const Iterator& rhs) const {
+ return current_ != rhs.current_;
+ }
+
+ HandleEntry& operator*() { return current_; }
+
+ operator const SYSTEM_HANDLE_INFORMATION*() {
+ return current_.handle_entry_;
+ }
+
+ HandleEntry* operator->() { return &current_; }
+
+ private:
+ const HandleTable& table_;
+ HandleEntry current_;
+ const SYSTEM_HANDLE_INFORMATION* end_;
+ };
+
+ HandleTable();
+
+ Iterator begin() const {
+ return Iterator(*this, handle_info()->Information,
+ &handle_info()->Information[handle_info()->NumberOfHandles]);
+ }
+
+ const SYSTEM_HANDLE_INFORMATION_EX* handle_info() const {
+ return reinterpret_cast<const SYSTEM_HANDLE_INFORMATION_EX*>(
+ &(handle_info_buffer_[0]));
+ }
+
+ // Returns an iterator to the handles for only the supplied process ID.
+ Iterator HandlesForProcess(ULONG process_id) const;
+ const SYSTEM_HANDLE_INFORMATION* end() const {
+ return &handle_info()->Information[handle_info()->NumberOfHandles];
+ }
+
+ private:
+ SYSTEM_HANDLE_INFORMATION_EX* handle_info_internal() {
+ return reinterpret_cast<SYSTEM_HANDLE_INFORMATION_EX*>(
+ &(handle_info_buffer_[0]));
+ }
+
+ std::vector<BYTE> handle_info_buffer_;
+ static HMODULE ntdll_;
+
+ DISALLOW_COPY_AND_ASSIGN(HandleTable);
+};
+
+} // namespace sandbox
+
+#endif // SANDBOX_SRC_HANDLE_TABLE_H_
diff --git a/sandbox/src/handle_table_unittest.cc b/sandbox/src/handle_table_unittest.cc
new file mode 100644
index 0000000..696037f
--- /dev/null
+++ b/sandbox/src/handle_table_unittest.cc
@@ -0,0 +1,66 @@
+// Copyright (c) 2011 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 <windows.h>
+
+#include "sandbox/src/handle_table.h"
+#include "sandbox/tests/common/test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+TEST(HandleTable, IsTableValid) {
+ using sandbox::HandleTable;
+ const ULONG my_process_id = ::GetCurrentProcessId();
+ ULONG last_process_id = 0;
+ ULONG total_handles = 0;
+ bool found_my_process = false;
+ bool found_other_process = false;
+
+ HandleTable handles;
+ EXPECT_NE(0u, handles.handle_info()->NumberOfHandles);
+
+ for (HandleTable::Iterator it = handles.begin(); it != handles.end(); ++it) {
+ ULONG process_id = it->handle_entry()->ProcessId;
+ bool is_current_process = process_id == my_process_id;
+ found_my_process |= is_current_process;
+ found_other_process |= !is_current_process;
+
+ EXPECT_LE(last_process_id, process_id);
+ last_process_id = process_id;
+ total_handles++;
+ }
+
+ EXPECT_EQ(handles.handle_info()->NumberOfHandles, total_handles);
+ EXPECT_TRUE(found_my_process);
+ EXPECT_TRUE(found_other_process);
+}
+
+TEST(HandleTable, FindHandle) {
+ using sandbox::HandleTable;
+
+ // Create a temp file so we have a handle to find.
+ wchar_t temp_directory[MAX_PATH];
+ wchar_t my_file[MAX_PATH];
+ ASSERT_NE(::GetTempPath(MAX_PATH, temp_directory), 0u);
+ ASSERT_NE(::GetTempFileName(temp_directory, L"test", 0, my_file), 0u);
+ HANDLE file = ::CreateFile(my_file, FILE_ALL_ACCESS,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+ OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, NULL);
+ EXPECT_NE(INVALID_HANDLE_VALUE, file);
+
+ // Look for the handle in our process
+ bool handle_found = false;
+ HandleTable handles;
+ for (HandleTable::Iterator it =
+ handles.HandlesForProcess(::GetCurrentProcessId());
+ it != handles.end(); ++it) {
+ if (it->IsType(HandleTable::kTypeFile) && it->Name().compare(my_file)) {
+ handle_found = true;
+ break;
+ }
+ }
+ EXPECT_TRUE(handle_found);
+
+ // Clean up the file we made.
+ EXPECT_TRUE(::CloseHandle(file));
+}
diff --git a/sandbox/src/nt_internals.h b/sandbox/src/nt_internals.h
index fa6b59e..08bf1a1 100644
--- a/sandbox/src/nt_internals.h
+++ b/sandbox/src/nt_internals.h
@@ -16,6 +16,7 @@ typedef LONG NTSTATUS;
#define STATUS_BUFFER_OVERFLOW ((NTSTATUS)0x80000005L)
#define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L)
#define STATUS_NOT_IMPLEMENTED ((NTSTATUS)0xC0000002L)
+#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
#ifndef STATUS_INVALID_PARAMETER
// It is now defined in Windows 2008 SDK.
#define STATUS_INVALID_PARAMETER ((NTSTATUS)0xC000000DL)
@@ -441,6 +442,35 @@ typedef enum _OBJECT_INFORMATION_CLASS {
ObjectDataInformation
} OBJECT_INFORMATION_CLASS, *POBJECT_INFORMATION_CLASS;
+typedef struct _OBJDIR_INFORMATION {
+ UNICODE_STRING ObjectName;
+ UNICODE_STRING ObjectTypeName;
+ BYTE Data[1];
+} OBJDIR_INFORMATION;
+
+typedef struct _PUBLIC_OBJECT_BASIC_INFORMATION {
+ ULONG Attributes;
+ ACCESS_MASK GrantedAccess;
+ ULONG HandleCount;
+ ULONG PointerCount;
+ ULONG Reserved[10]; // reserved for internal use
+ } PUBLIC_OBJECT_BASIC_INFORMATION, *PPUBLIC_OBJECT_BASIC_INFORMATION;
+
+typedef struct __PUBLIC_OBJECT_TYPE_INFORMATION {
+ UNICODE_STRING TypeName;
+ ULONG Reserved[22]; // reserved for internal use
+} PUBLIC_OBJECT_TYPE_INFORMATION, *PPUBLIC_OBJECT_TYPE_INFORMATION;
+
+typedef enum _POOL_TYPE {
+ NonPagedPool,
+ PagedPool,
+ NonPagedPoolMustSucceed,
+ ReservedType,
+ NonPagedPoolCacheAligned,
+ PagedPoolCacheAligned,
+ NonPagedPoolCacheAlignedMustS
+} POOL_TYPE;
+
typedef struct _OBJECT_BASIC_INFORMATION {
ULONG Attributes;
ACCESS_MASK GrantedAccess;
@@ -455,6 +485,50 @@ typedef struct _OBJECT_BASIC_INFORMATION {
LARGE_INTEGER CreateTime;
} OBJECT_BASIC_INFORMATION, *POBJECT_BASIC_INFORMATION;
+typedef struct _OBJECT_TYPE_INFORMATION {
+ UNICODE_STRING Name;
+ ULONG TotalNumberOfObjects;
+ ULONG TotalNumberOfHandles;
+ ULONG TotalPagedPoolUsage;
+ ULONG TotalNonPagedPoolUsage;
+ ULONG TotalNamePoolUsage;
+ ULONG TotalHandleTableUsage;
+ ULONG HighWaterNumberOfObjects;
+ ULONG HighWaterNumberOfHandles;
+ ULONG HighWaterPagedPoolUsage;
+ ULONG HighWaterNonPagedPoolUsage;
+ ULONG HighWaterNamePoolUsage;
+ ULONG HighWaterHandleTableUsage;
+ ULONG InvalidAttributes;
+ GENERIC_MAPPING GenericMapping;
+ ULONG ValidAccess;
+ BOOLEAN SecurityRequired;
+ BOOLEAN MaintainHandleCount;
+ USHORT MaintainTypeList;
+ POOL_TYPE PoolType;
+ ULONG PagedPoolUsage;
+ ULONG NonPagedPoolUsage;
+} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION;
+
+typedef enum _SYSTEM_INFORMATION_CLASS {
+ SystemHandleInformation = 16
+} SYSTEM_INFORMATION_CLASS;
+
+typedef struct _SYSTEM_HANDLE_INFORMATION {
+ USHORT ProcessId;
+ USHORT CreatorBackTraceIndex;
+ UCHAR ObjectTypeNumber;
+ UCHAR Flags;
+ USHORT Handle;
+ PVOID Object;
+ ACCESS_MASK GrantedAccess;
+} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
+
+typedef struct _SYSTEM_HANDLE_INFORMATION_EX {
+ ULONG NumberOfHandles;
+ SYSTEM_HANDLE_INFORMATION Information[1];
+} SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX;
+
typedef struct _OBJECT_NAME_INFORMATION {
UNICODE_STRING ObjectName;
} OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION;
@@ -481,6 +555,19 @@ typedef NTSTATUS (WINAPI *NtSignalAndWaitForSingleObjectFunction)(
IN BOOLEAN Alertable,
IN PLARGE_INTEGER Timeout OPTIONAL);
+typedef NTSTATUS (WINAPI *NtQuerySystemInformation)(
+ IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
+ OUT PVOID SystemInformation,
+ IN ULONG SystemInformationLength,
+ OUT PULONG ReturnLength);
+
+typedef NTSTATUS (WINAPI *NtQueryObject)(
+ IN HANDLE Handle,
+ IN OBJECT_INFORMATION_CLASS ObjectInformationClass,
+ OUT PVOID ObjectInformation,
+ IN ULONG ObjectInformationLength,
+ OUT PULONG ReturnLength);
+
// -----------------------------------------------------------------------
// Strings