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