Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(82)

Side by Side Diff: sandbox/win/src/interception.h

Issue 1851213002: Remove sandbox on Windows. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix nacl compile issues Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « sandbox/win/src/integrity_level_test.cc ('k') | sandbox/win/src/interception.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 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 // Defines InterceptionManager, the class in charge of setting up interceptions
6 // for the sandboxed process. For more details see
7 // http://dev.chromium.org/developers/design-documents/sandbox .
8
9 #ifndef SANDBOX_SRC_INTERCEPTION_H_
10 #define SANDBOX_SRC_INTERCEPTION_H_
11
12 #include <stddef.h>
13
14 #include <list>
15 #include <string>
16
17 #include "base/gtest_prod_util.h"
18 #include "base/macros.h"
19 #include "base/strings/string16.h"
20 #include "sandbox/win/src/sandbox_types.h"
21
22 namespace sandbox {
23
24 class TargetProcess;
25 enum InterceptorId;
26
27 // Internal structures used for communication between the broker and the target.
28 struct DllPatchInfo;
29 struct DllInterceptionData;
30
31 // The InterceptionManager executes on the parent application, and it is in
32 // charge of setting up the desired interceptions, and placing the Interception
33 // Agent into the child application.
34 //
35 // The exposed API consists of two methods: AddToPatchedFunctions to set up a
36 // particular interception, and InitializeInterceptions to actually go ahead and
37 // perform all interceptions and transfer data to the child application.
38 //
39 // The typical usage is something like this:
40 //
41 // InterceptionManager interception_manager(child);
42 // if (!interception_manager.AddToPatchedFunctions(
43 // L"ntdll.dll", "NtCreateFile",
44 // sandbox::INTERCEPTION_SERVICE_CALL, &MyNtCreateFile, MY_ID_1))
45 // return false;
46 //
47 // if (!interception_manager.AddToPatchedFunctions(
48 // L"kernel32.dll", "CreateDirectoryW",
49 // sandbox::INTERCEPTION_EAT, L"MyCreateDirectoryW@12", MY_ID_2))
50 // return false;
51 //
52 // if (!interception_manager.InitializeInterceptions()) {
53 // DWORD error = ::GetLastError();
54 // return false;
55 // }
56 //
57 // Any required syncronization must be performed outside this class. Also, it is
58 // not possible to perform further interceptions after InitializeInterceptions
59 // is called.
60 //
61 class InterceptionManager {
62 // The unit test will access private members.
63 // Allow tests to be marked DISABLED_. Note that FLAKY_ and FAILS_ prefixes
64 // do not work with sandbox tests.
65 FRIEND_TEST_ALL_PREFIXES(InterceptionManagerTest, BufferLayout1);
66 FRIEND_TEST_ALL_PREFIXES(InterceptionManagerTest, BufferLayout2);
67
68 public:
69 // An interception manager performs interceptions on a given child process.
70 // If we are allowed to intercept functions that have been patched by somebody
71 // else, relaxed should be set to true.
72 // Note: We increase the child's reference count internally.
73 InterceptionManager(TargetProcess* child_process, bool relaxed);
74 ~InterceptionManager();
75
76 // Patches function_name inside dll_name to point to replacement_code_address.
77 // function_name has to be an exported symbol of dll_name.
78 // Returns true on success.
79 //
80 // The new function should match the prototype and calling convention of the
81 // function to intercept except for one extra argument (the first one) that
82 // contains a pointer to the original function, to simplify the development
83 // of interceptors (for IA32). In x64, there is no extra argument to the
84 // interceptor, so the provided InterceptorId is used to keep a table of
85 // intercepted functions so that the interceptor can index that table to get
86 // the pointer that would have been the first argument (g_originals[id]).
87 //
88 // For example, to intercept NtClose, the following code could be used:
89 //
90 // typedef NTSTATUS (WINAPI *NtCloseFunction) (IN HANDLE Handle);
91 // NTSTATUS WINAPI MyNtCose(IN NtCloseFunction OriginalClose,
92 // IN HANDLE Handle) {
93 // // do something
94 // // call the original function
95 // return OriginalClose(Handle);
96 // }
97 //
98 // And in x64:
99 //
100 // typedef NTSTATUS (WINAPI *NtCloseFunction) (IN HANDLE Handle);
101 // NTSTATUS WINAPI MyNtCose64(IN HANDLE Handle) {
102 // // do something
103 // // call the original function
104 // NtCloseFunction OriginalClose = g_originals[NT_CLOSE_ID];
105 // return OriginalClose(Handle);
106 // }
107 bool AddToPatchedFunctions(const wchar_t* dll_name,
108 const char* function_name,
109 InterceptionType interception_type,
110 const void* replacement_code_address,
111 InterceptorId id);
112
113 // Patches function_name inside dll_name to point to
114 // replacement_function_name.
115 bool AddToPatchedFunctions(const wchar_t* dll_name,
116 const char* function_name,
117 InterceptionType interception_type,
118 const char* replacement_function_name,
119 InterceptorId id);
120
121 // The interception agent will unload the dll with dll_name.
122 bool AddToUnloadModules(const wchar_t* dll_name);
123
124 // Initializes all interceptions on the client.
125 // Returns true on success.
126 //
127 // The child process must be created suspended, and cannot be resumed until
128 // after this method returns. In addition, no action should be performed on
129 // the child that may cause it to resume momentarily, such as injecting
130 // threads or APCs.
131 //
132 // This function must be called only once, after all interceptions have been
133 // set up using AddToPatchedFunctions.
134 bool InitializeInterceptions();
135
136 private:
137 // Used to store the interception information until the actual set-up.
138 struct InterceptionData {
139 InterceptionData();
140 ~InterceptionData();
141
142 InterceptionType type; // Interception type.
143 InterceptorId id; // Interceptor id.
144 base::string16 dll; // Name of dll to intercept.
145 std::string function; // Name of function to intercept.
146 std::string interceptor; // Name of interceptor function.
147 const void* interceptor_address; // Interceptor's entry point.
148 };
149
150 // Calculates the size of the required configuration buffer.
151 size_t GetBufferSize() const;
152
153 // Rounds up the size of a given buffer, considering alignment (padding).
154 // value is the current size of the buffer, and alignment is specified in
155 // bytes.
156 static inline size_t RoundUpToMultiple(size_t value, size_t alignment) {
157 return ((value + alignment -1) / alignment) * alignment;
158 }
159
160 // Sets up a given buffer with all the information that has to be transfered
161 // to the child.
162 // Returns true on success.
163 //
164 // The buffer size should be at least the value returned by GetBufferSize
165 bool SetupConfigBuffer(void* buffer, size_t buffer_bytes);
166
167 // Fills up the part of the transfer buffer that corresponds to information
168 // about one dll to patch.
169 // data is the first recorded interception for this dll.
170 // Returns true on success.
171 //
172 // On successful return, buffer will be advanced from it's current position
173 // to the point where the next block of configuration data should be written
174 // (the actual interception info), and the current size of the buffer will
175 // decrease to account the space used by this method.
176 bool SetupDllInfo(const InterceptionData& data,
177 void** buffer, size_t* buffer_bytes) const;
178
179 // Fills up the part of the transfer buffer that corresponds to a single
180 // function to patch.
181 // dll_info points to the dll being updated with the interception stored on
182 // data. The buffer pointer and remaining size are updated by this call.
183 // Returns true on success.
184 bool SetupInterceptionInfo(const InterceptionData& data, void** buffer,
185 size_t* buffer_bytes,
186 DllPatchInfo* dll_info) const;
187
188 // Returns true if this interception is to be performed by the child
189 // as opposed to from the parent.
190 bool IsInterceptionPerformedByChild(const InterceptionData& data) const;
191
192 // Allocates a buffer on the child's address space (returned on
193 // remote_buffer), and fills it with the contents of a local buffer.
194 // Returns true on success.
195 bool CopyDataToChild(const void* local_buffer, size_t buffer_bytes,
196 void** remote_buffer) const;
197
198 // Performs the cold patch (from the parent) of ntdll.
199 // Returns true on success.
200 //
201 // This method will insert additional interceptions to launch the interceptor
202 // agent on the child process, if there are additional interceptions to do.
203 bool PatchNtdll(bool hot_patch_needed);
204
205 // Peforms the actual interceptions on ntdll.
206 // thunks is the memory to store all the thunks for this dll (on the child),
207 // and dll_data is a local buffer to hold global dll interception info.
208 // Returns true on success.
209 bool PatchClientFunctions(DllInterceptionData* thunks,
210 size_t thunk_bytes,
211 DllInterceptionData* dll_data);
212
213 // The process to intercept.
214 TargetProcess* child_;
215 // Holds all interception info until the call to initialize (perform the
216 // actual patch).
217 std::list<InterceptionData> interceptions_;
218
219 // Keep track of patches added by name.
220 bool names_used_;
221
222 // true if we are allowed to patch already-patched functions.
223 bool relaxed_;
224
225 DISALLOW_COPY_AND_ASSIGN(InterceptionManager);
226 };
227
228 // This macro simply calls interception_manager.AddToPatchedFunctions with
229 // the given service to intercept (INTERCEPTION_SERVICE_CALL), and assumes that
230 // the interceptor is called "TargetXXX", where XXX is the name of the service.
231 // Note that num_params is the number of bytes to pop out of the stack for
232 // the exported interceptor, following the calling convention of a service call
233 // (WINAPI = with the "C" underscore).
234 #if SANDBOX_EXPORTS
235 #if defined(_WIN64)
236 #define MAKE_SERVICE_NAME(service, params) "Target" # service "64"
237 #else
238 #define MAKE_SERVICE_NAME(service, params) "_Target" # service "@" # params
239 #endif
240
241 #define ADD_NT_INTERCEPTION(service, id, num_params) \
242 AddToPatchedFunctions(kNtdllName, #service, \
243 sandbox::INTERCEPTION_SERVICE_CALL, \
244 MAKE_SERVICE_NAME(service, num_params), id)
245
246 #define INTERCEPT_NT(manager, service, id, num_params) \
247 ((&Target##service) ? \
248 manager->ADD_NT_INTERCEPTION(service, id, num_params) : false)
249
250 // When intercepting the EAT it is important that the patched version of the
251 // function not call any functions imported from system libraries unless
252 // |TargetServices::InitCalled()| returns true, because it is only then that
253 // we are guaranteed that our IAT has been initialized.
254 #define INTERCEPT_EAT(manager, dll, function, id, num_params) \
255 ((&Target##function) ? \
256 manager->AddToPatchedFunctions(dll, #function, sandbox::INTERCEPTION_EAT, \
257 MAKE_SERVICE_NAME(function, num_params), \
258 id) : \
259 false)
260 #else // SANDBOX_EXPORTS
261 #if defined(_WIN64)
262 #define MAKE_SERVICE_NAME(service) &Target##service##64
263 #else
264 #define MAKE_SERVICE_NAME(service) &Target##service
265 #endif
266
267 #define ADD_NT_INTERCEPTION(service, id, num_params) \
268 AddToPatchedFunctions(kNtdllName, #service, \
269 sandbox::INTERCEPTION_SERVICE_CALL, \
270 MAKE_SERVICE_NAME(service), id)
271
272 #define INTERCEPT_NT(manager, service, id, num_params) \
273 manager->ADD_NT_INTERCEPTION(service, id, num_params)
274
275 // When intercepting the EAT it is important that the patched version of the
276 // function not call any functions imported from system libraries unless
277 // |TargetServices::InitCalled()| returns true, because it is only then that
278 // we are guaranteed that our IAT has been initialized.
279 #define INTERCEPT_EAT(manager, dll, function, id, num_params) \
280 manager->AddToPatchedFunctions(dll, #function, sandbox::INTERCEPTION_EAT, \
281 MAKE_SERVICE_NAME(function), id)
282 #endif // SANDBOX_EXPORTS
283
284 } // namespace sandbox
285
286 #endif // SANDBOX_SRC_INTERCEPTION_H_
OLDNEW
« no previous file with comments | « sandbox/win/src/integrity_level_test.cc ('k') | sandbox/win/src/interception.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698