michael@0: // Copyright (c) 2010 The Chromium Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: michael@0: #ifndef SANDBOX_SRC_SANDBOX_NT_UTIL_H_ michael@0: #define SANDBOX_SRC_SANDBOX_NT_UTIL_H_ michael@0: michael@0: #include michael@0: michael@0: #include "base/basictypes.h" michael@0: #include "sandbox/win/src/nt_internals.h" michael@0: #include "sandbox/win/src/sandbox_nt_types.h" michael@0: michael@0: // Placement new and delete to be used from ntdll interception code. michael@0: void* __cdecl operator new(size_t size, sandbox::AllocationType type, michael@0: void* near_to = NULL); michael@0: void __cdecl operator delete(void* memory, sandbox::AllocationType type); michael@0: // Add operator delete that matches the placement form of the operator new michael@0: // above. This is required by compiler to generate code to call operator delete michael@0: // in case the object's constructor throws an exception. michael@0: // See http://msdn.microsoft.com/en-us/library/cxdxz3x6.aspx michael@0: void __cdecl operator delete(void* memory, sandbox::AllocationType type, michael@0: void* near_to); michael@0: michael@0: // Regular placement new and delete michael@0: void* __cdecl operator new(size_t size, void* buffer, michael@0: sandbox::AllocationType type); michael@0: void __cdecl operator delete(void* memory, void* buffer, michael@0: sandbox::AllocationType type); michael@0: michael@0: // DCHECK_NT is defined to be pretty much an assert at this time because we michael@0: // don't have logging from the ntdll layer on the child. michael@0: // michael@0: // VERIFY_NT and VERIFY_SUCCESS_NT are the standard asserts on debug, but michael@0: // execute the actual argument on release builds. VERIFY_NT expects an action michael@0: // returning a bool, while VERIFY_SUCCESS_NT expects an action returning michael@0: // NTSTATUS. michael@0: #ifndef NDEBUG michael@0: #define DCHECK_NT(condition) { (condition) ? (void)0 : __debugbreak(); } michael@0: #define VERIFY(action) DCHECK_NT(action) michael@0: #define VERIFY_SUCCESS(action) DCHECK_NT(NT_SUCCESS(action)) michael@0: #else michael@0: #define DCHECK_NT(condition) michael@0: #define VERIFY(action) (action) michael@0: #define VERIFY_SUCCESS(action) (action) michael@0: #endif michael@0: michael@0: #define NOTREACHED_NT() DCHECK_NT(false) michael@0: michael@0: namespace sandbox { michael@0: michael@0: #if defined(_M_X64) michael@0: #pragma intrinsic(_InterlockedCompareExchange) michael@0: #pragma intrinsic(_InterlockedCompareExchangePointer) michael@0: michael@0: #elif defined(_M_IX86) michael@0: extern "C" long _InterlockedCompareExchange(long volatile* destination, michael@0: long exchange, long comperand); michael@0: michael@0: #pragma intrinsic(_InterlockedCompareExchange) michael@0: michael@0: // We want to make sure that we use an intrinsic version of the function, not michael@0: // the one provided by kernel32. michael@0: __forceinline void* _InterlockedCompareExchangePointer( michael@0: void* volatile* destination, void* exchange, void* comperand) { michael@0: size_t ret = _InterlockedCompareExchange( michael@0: reinterpret_cast(destination), michael@0: static_cast(reinterpret_cast(exchange)), michael@0: static_cast(reinterpret_cast(comperand))); michael@0: michael@0: return reinterpret_cast(static_cast(ret)); michael@0: } michael@0: michael@0: #else michael@0: #error Architecture not supported. michael@0: michael@0: #endif michael@0: michael@0: // Returns a pointer to the IPC shared memory. michael@0: void* GetGlobalIPCMemory(); michael@0: michael@0: // Returns a pointer to the Policy shared memory. michael@0: void* GetGlobalPolicyMemory(); michael@0: michael@0: enum RequiredAccess { michael@0: READ, michael@0: WRITE michael@0: }; michael@0: michael@0: // Performs basic user mode buffer validation. In any case, buffers access must michael@0: // be protected by SEH. intent specifies if the buffer should be tested for read michael@0: // or write. michael@0: // Note that write intent implies destruction of the buffer content (we actually michael@0: // write) michael@0: bool ValidParameter(void* buffer, size_t size, RequiredAccess intent); michael@0: michael@0: michael@0: // Copies data from a user buffer to our buffer. Returns the operation status. michael@0: NTSTATUS CopyData(void* destination, const void* source, size_t bytes); michael@0: michael@0: // Copies the name from an object attributes. michael@0: NTSTATUS AllocAndCopyName(const OBJECT_ATTRIBUTES* in_object, michael@0: wchar_t** out_name, uint32* attributes, HANDLE* root); michael@0: michael@0: // Initializes our ntdll level heap michael@0: bool InitHeap(); michael@0: michael@0: // Returns true if the provided handle refers to the current process. michael@0: bool IsSameProcess(HANDLE process); michael@0: michael@0: enum MappedModuleFlags { michael@0: MODULE_IS_PE_IMAGE = 1, // Module is an executable. michael@0: MODULE_HAS_ENTRY_POINT = 2, // Execution entry point found. michael@0: MODULE_HAS_CODE = 4 // Non zero size of executable sections. michael@0: }; michael@0: michael@0: // Returns the name and characteristics for a given PE module. The return michael@0: // value is the name as defined by the export table and the flags is any michael@0: // combination of the MappedModuleFlags enumeration. michael@0: // michael@0: // The returned buffer must be freed with a placement delete from the ntdll michael@0: // level allocator: michael@0: // michael@0: // UNICODE_STRING* name = GetPEImageInfoFromModule(HMODULE module, &flags); michael@0: // if (!name) { michael@0: // // probably not a valid dll michael@0: // return; michael@0: // } michael@0: // InsertYourLogicHere(name); michael@0: // operator delete(name, NT_ALLOC); michael@0: UNICODE_STRING* GetImageInfoFromModule(HMODULE module, uint32* flags); michael@0: michael@0: // Returns the full path and filename for a given dll. michael@0: // May return NULL if the provided address is not backed by a named section, or michael@0: // if the current OS version doesn't support the call. The returned buffer must michael@0: // be freed with a placement delete (see GetImageNameFromModule example). michael@0: UNICODE_STRING* GetBackingFilePath(PVOID address); michael@0: michael@0: // Returns the last component of a path that contains the module name. michael@0: // It will return NULL if the path ends with the path separator. The returned michael@0: // buffer must be freed with a placement delete (see GetImageNameFromModule michael@0: // example). michael@0: UNICODE_STRING* ExtractModuleName(const UNICODE_STRING* module_path); michael@0: michael@0: // Returns true if the parameters correspond to a dll mapped as code. michael@0: bool IsValidImageSection(HANDLE section, PVOID *base, PLARGE_INTEGER offset, michael@0: PSIZE_T view_size); michael@0: michael@0: // Converts an ansi string to an UNICODE_STRING. michael@0: UNICODE_STRING* AnsiToUnicode(const char* string); michael@0: michael@0: // Provides a simple way to temporarily change the protection of a memory page. michael@0: class AutoProtectMemory { michael@0: public: michael@0: AutoProtectMemory() michael@0: : changed_(false), address_(NULL), bytes_(0), old_protect_(0) {} michael@0: michael@0: ~AutoProtectMemory() { michael@0: RevertProtection(); michael@0: } michael@0: michael@0: // Sets the desired protection of a given memory range. michael@0: NTSTATUS ChangeProtection(void* address, size_t bytes, ULONG protect); michael@0: michael@0: // Restores the original page protection. michael@0: NTSTATUS RevertProtection(); michael@0: michael@0: private: michael@0: bool changed_; michael@0: void* address_; michael@0: size_t bytes_; michael@0: ULONG old_protect_; michael@0: michael@0: DISALLOW_COPY_AND_ASSIGN(AutoProtectMemory); michael@0: }; michael@0: michael@0: // Returns true if the file_rename_information structure is supported by our michael@0: // rename handler. michael@0: bool IsSupportedRenameCall(FILE_RENAME_INFORMATION* file_info, DWORD length, michael@0: uint32 file_info_class); michael@0: michael@0: } // namespace sandbox michael@0: michael@0: michael@0: #endif // SANDBOX_SRC_SANDBOX_NT_UTIL_H__