diff options
-rw-r--r-- | content/browser/handle_enumerator_win.cc | 139 | ||||
-rw-r--r-- | content/browser/handle_enumerator_win.h | 1 | ||||
-rw-r--r-- | content/content_browser.gypi | 6 | ||||
-rw-r--r-- | sandbox/sandbox.gyp | 3 | ||||
-rw-r--r-- | sandbox/src/handle_table.cc | 195 | ||||
-rw-r--r-- | sandbox/src/handle_table.h | 161 | ||||
-rw-r--r-- | sandbox/src/handle_table_unittest.cc | 66 | ||||
-rw-r--r-- | sandbox/src/nt_internals.h | 87 |
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 ¤t_; } + + 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 |