sandbox_nt_util.h 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. // Copyright (c) 2010 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef SANDBOX_WIN_SRC_SANDBOX_NT_UTIL_H_
  5. #define SANDBOX_WIN_SRC_SANDBOX_NT_UTIL_H_
  6. #include <intrin.h>
  7. #include <stddef.h>
  8. #include <stdint.h>
  9. #include <memory>
  10. #include "sandbox/win/src/nt_internals.h"
  11. #include "sandbox/win/src/sandbox_nt_types.h"
  12. // Placement new and delete to be used from ntdll interception code.
  13. void* __cdecl operator new(size_t size,
  14. sandbox::AllocationType type,
  15. void* near_to = nullptr);
  16. void __cdecl operator delete(void* memory, sandbox::AllocationType type);
  17. // Add operator delete that matches the placement form of the operator new
  18. // above. This is required by compiler to generate code to call operator delete
  19. // in case the object's constructor throws an exception.
  20. // See http://msdn.microsoft.com/en-us/library/cxdxz3x6.aspx
  21. void __cdecl operator delete(void* memory,
  22. sandbox::AllocationType type,
  23. void* near_to);
  24. // Regular placement new and delete
  25. void* __cdecl operator new(size_t size,
  26. void* buffer,
  27. sandbox::AllocationType type);
  28. void __cdecl operator delete(void* memory,
  29. void* buffer,
  30. sandbox::AllocationType type);
  31. // DCHECK_NT is defined to be pretty much an assert at this time because we
  32. // don't have logging from the ntdll layer on the child.
  33. //
  34. // VERIFY_NT and VERIFY_SUCCESS are the standard asserts on debug, but
  35. // execute the actual argument on release builds. VERIFY_NT expects an action
  36. // returning a bool, while VERIFY_SUCCESS expects an action returning
  37. // NTSTATUS.
  38. #ifndef NDEBUG
  39. #define DCHECK_NT(condition) \
  40. { (condition) ? (void)0 : __debugbreak(); }
  41. #define VERIFY(action) DCHECK_NT(action)
  42. #define VERIFY_SUCCESS(action) DCHECK_NT(NT_SUCCESS(action))
  43. #else
  44. #define DCHECK_NT(condition)
  45. #define VERIFY(action) (action)
  46. #define VERIFY_SUCCESS(action) (action)
  47. #endif
  48. #define CHECK_NT(condition) \
  49. { (condition) ? (void)0 : __debugbreak(); }
  50. #define NOTREACHED_NT() DCHECK_NT(false)
  51. namespace sandbox {
  52. #if defined(_M_X64) || defined(_M_ARM64)
  53. #pragma intrinsic(_InterlockedCompareExchange)
  54. #pragma intrinsic(_InterlockedCompareExchangePointer)
  55. #elif defined(_M_IX86)
  56. extern "C" long _InterlockedCompareExchange(long volatile* destination,
  57. long exchange,
  58. long comperand);
  59. #pragma intrinsic(_InterlockedCompareExchange)
  60. // We want to make sure that we use an intrinsic version of the function, not
  61. // the one provided by kernel32.
  62. __forceinline void* _InterlockedCompareExchangePointer(
  63. void* volatile* destination,
  64. void* exchange,
  65. void* comperand) {
  66. long ret = _InterlockedCompareExchange(
  67. reinterpret_cast<long volatile*>(destination),
  68. static_cast<long>(reinterpret_cast<size_t>(exchange)),
  69. static_cast<long>(reinterpret_cast<size_t>(comperand)));
  70. return reinterpret_cast<void*>(static_cast<size_t>(ret));
  71. }
  72. #else
  73. #error Architecture not supported.
  74. #endif
  75. struct NtAllocDeleter {
  76. inline void operator()(void* ptr) const {
  77. operator delete(ptr, AllocationType::NT_ALLOC);
  78. }
  79. };
  80. // Returns a pointer to the IPC shared memory.
  81. void* GetGlobalIPCMemory();
  82. // Returns a pointer to the Policy shared memory.
  83. void* GetGlobalPolicyMemory();
  84. // Returns a reference to imported NT functions.
  85. const NtExports* GetNtExports();
  86. enum RequiredAccess { READ, WRITE };
  87. // Performs basic user mode buffer validation. In any case, buffers access must
  88. // be protected by SEH. intent specifies if the buffer should be tested for read
  89. // or write.
  90. bool ValidParameter(void* buffer, size_t size, RequiredAccess intent);
  91. // Copies data from a user buffer to our buffer. Returns the operation status.
  92. NTSTATUS CopyData(void* destination, const void* source, size_t bytes);
  93. // Copies the name from an object attributes. |out_name| is a NUL terminated
  94. // string and |out_name_len| is the number of characters copied. |attributes|
  95. // is a copy of the attribute flags from |in_object|.
  96. NTSTATUS CopyNameAndAttributes(
  97. const OBJECT_ATTRIBUTES* in_object,
  98. std::unique_ptr<wchar_t, NtAllocDeleter>* out_name,
  99. size_t* out_name_len,
  100. uint32_t* attributes = nullptr);
  101. // Initializes our ntdll level heap
  102. bool InitHeap();
  103. // Returns true if the provided handle refers to the current process.
  104. bool IsSameProcess(HANDLE process);
  105. enum MappedModuleFlags {
  106. MODULE_IS_PE_IMAGE = 1, // Module is an executable.
  107. MODULE_HAS_ENTRY_POINT = 2, // Execution entry point found.
  108. MODULE_HAS_CODE = 4 // Non zero size of executable sections.
  109. };
  110. // Returns the name and characteristics for a given PE module. The return
  111. // value is the name as defined by the export table and the flags is any
  112. // combination of the MappedModuleFlags enumeration.
  113. //
  114. // The returned buffer must be freed with a placement delete from the ntdll
  115. // level allocator:
  116. //
  117. // UNICODE_STRING* name = GetPEImageInfoFromModule(HMODULE module, &flags);
  118. // if (!name) {
  119. // // probably not a valid dll
  120. // return;
  121. // }
  122. // InsertYourLogicHere(name);
  123. // operator delete(name, NT_ALLOC);
  124. UNICODE_STRING* GetImageInfoFromModule(HMODULE module, uint32_t* flags);
  125. // Returns the name and characteristics for a given PE module. The return
  126. // value is the name as defined by the export table.
  127. //
  128. // The returned buffer is within the PE module and must not be freed.
  129. const char* GetAnsiImageInfoFromModule(HMODULE module);
  130. // Returns the full path and filename for a given dll.
  131. // May return nullptr if the provided address is not backed by a named section,
  132. // or if the current OS version doesn't support the call. The returned buffer
  133. // must be freed with a placement delete (see GetImageNameFromModule example).
  134. UNICODE_STRING* GetBackingFilePath(PVOID address);
  135. // Returns the last component of a path that contains the module name.
  136. // It will return nullptr if the path ends with the path separator. The returned
  137. // buffer must be freed with a placement delete (see GetImageNameFromModule
  138. // example).
  139. UNICODE_STRING* ExtractModuleName(const UNICODE_STRING* module_path);
  140. // Returns true if the parameters correspond to a dll mapped as code.
  141. bool IsValidImageSection(HANDLE section,
  142. PVOID* base,
  143. PLARGE_INTEGER offset,
  144. PSIZE_T view_size);
  145. // Converts an ansi string to an UNICODE_STRING.
  146. UNICODE_STRING* AnsiToUnicode(const char* string);
  147. // Resolves a handle to an nt path. Returns true if the handle can be resolved.
  148. bool NtGetPathFromHandle(HANDLE handle,
  149. std::unique_ptr<wchar_t, NtAllocDeleter>* path);
  150. // Provides a simple way to temporarily change the protection of a memory page.
  151. class AutoProtectMemory {
  152. public:
  153. AutoProtectMemory()
  154. : changed_(false), address_(nullptr), bytes_(0), old_protect_(0) {}
  155. AutoProtectMemory(const AutoProtectMemory&) = delete;
  156. AutoProtectMemory& operator=(const AutoProtectMemory&) = delete;
  157. ~AutoProtectMemory() { RevertProtection(); }
  158. // Sets the desired protection of a given memory range.
  159. NTSTATUS ChangeProtection(void* address, size_t bytes, ULONG protect);
  160. // Restores the original page protection.
  161. NTSTATUS RevertProtection();
  162. private:
  163. bool changed_;
  164. void* address_;
  165. size_t bytes_;
  166. ULONG old_protect_;
  167. };
  168. // Returns true if the file_rename_information structure is supported by our
  169. // rename handler.
  170. bool IsSupportedRenameCall(FILE_RENAME_INFORMATION* file_info,
  171. DWORD length,
  172. uint32_t file_info_class);
  173. } // namespace sandbox
  174. #endif // SANDBOX_WIN_SRC_SANDBOX_NT_UTIL_H_