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.
15void* __cdecl operator new(size_t size, sandbox::AllocationType type,
16                           void* near_to = NULL);
17void __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
22void __cdecl operator delete(void* memory, sandbox::AllocationType type,
23                             void* near_to);
24
25// Regular placement new and delete
26void* __cdecl operator new(size_t size, void* buffer,
27                           sandbox::AllocationType type);
28void __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
52namespace sandbox {
53
54#if defined(_M_X64)
55#pragma intrinsic(_InterlockedCompareExchange)
56#pragma intrinsic(_InterlockedCompareExchangePointer)
57
58#elif defined(_M_IX86)
59extern "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.
82void* GetGlobalIPCMemory();
83
84// Returns a pointer to the Policy shared memory.
85void* GetGlobalPolicyMemory();
86
87enum 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)
97bool ValidParameter(void* buffer, size_t size, RequiredAccess intent);
98
99// Copies data from a user buffer to our buffer. Returns the operation status.
100NTSTATUS CopyData(void* destination, const void* source, size_t bytes);
101
102// Copies the name from an object attributes.
103NTSTATUS AllocAndCopyName(const OBJECT_ATTRIBUTES* in_object,
104                          wchar_t** out_name, uint32* attributes, HANDLE* root);
105
106// Initializes our ntdll level heap
107bool InitHeap();
108
109// Returns true if the provided handle refers to the current process.
110bool IsSameProcess(HANDLE process);
111
112enum 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);
132UNICODE_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).
138UNICODE_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).
144UNICODE_STRING* ExtractModuleName(const UNICODE_STRING* module_path);
145
146// Returns true if the parameters correspond to a dll mapped as code.
147bool IsValidImageSection(HANDLE section, PVOID *base, PLARGE_INTEGER offset,
148                         PSIZE_T view_size);
149
150// Converts an ansi string to an UNICODE_STRING.
151UNICODE_STRING* AnsiToUnicode(const char* string);
152
153// Provides a simple way to temporarily change the protection of a memory page.
154class 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.
180bool 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