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

Side by Side Diff: sandbox/src/sidestep_resolver.cc

Issue 10783004: Move Windows Sandbox, trybots version (don't commit me!) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase to top of tree Created 8 years, 5 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 | Annotate | Revision Log
« no previous file with comments | « sandbox/src/sidestep_resolver.h ('k') | sandbox/src/sync_dispatcher.h » ('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) 2006-2008 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 #include "sandbox/src/sidestep_resolver.h"
6
7 #include "base/win/pe_image.h"
8 #include "sandbox/src/sandbox_nt_util.h"
9 #include "sandbox/src/sidestep/preamble_patcher.h"
10
11 namespace {
12
13 const size_t kSizeOfSidestepStub = sidestep::kMaxPreambleStubSize;
14
15 struct SidestepThunk {
16 char sidestep[kSizeOfSidestepStub]; // Storage for the sidestep stub.
17 int internal_thunk; // Dummy member to the beginning of the internal thunk.
18 };
19
20 struct SmartThunk {
21 const void* module_base; // Target module's base.
22 const void* interceptor; // Real interceptor.
23 SidestepThunk sidestep; // Standard sidestep thunk.
24 };
25
26 } // namespace
27
28 namespace sandbox {
29
30 NTSTATUS SidestepResolverThunk::Setup(const void* target_module,
31 const void* interceptor_module,
32 const char* target_name,
33 const char* interceptor_name,
34 const void* interceptor_entry_point,
35 void* thunk_storage,
36 size_t storage_bytes,
37 size_t* storage_used) {
38 NTSTATUS ret = Init(target_module, interceptor_module, target_name,
39 interceptor_name, interceptor_entry_point,
40 thunk_storage, storage_bytes);
41 if (!NT_SUCCESS(ret))
42 return ret;
43
44 SidestepThunk* thunk = reinterpret_cast<SidestepThunk*>(thunk_storage);
45
46 size_t internal_bytes = storage_bytes - kSizeOfSidestepStub;
47 if (!SetInternalThunk(&thunk->internal_thunk, internal_bytes, thunk_storage,
48 interceptor_))
49 return STATUS_BUFFER_TOO_SMALL;
50
51 AutoProtectMemory memory;
52 memory.ChangeProtection(target_, kSizeOfSidestepStub, PAGE_READWRITE);
53
54 sidestep::SideStepError rv = sidestep::PreamblePatcher::Patch(
55 target_, reinterpret_cast<void*>(&thunk->internal_thunk), thunk_storage,
56 kSizeOfSidestepStub);
57
58 if (sidestep::SIDESTEP_INSUFFICIENT_BUFFER == rv)
59 return STATUS_BUFFER_TOO_SMALL;
60
61 if (sidestep::SIDESTEP_SUCCESS != rv)
62 return STATUS_UNSUCCESSFUL;
63
64 if (storage_used)
65 *storage_used = GetThunkSize();
66
67 return ret;
68 }
69
70 size_t SidestepResolverThunk::GetThunkSize() const {
71 return GetInternalThunkSize() + kSizeOfSidestepStub;
72 }
73
74 // This is basically a wrapper around the normal sidestep patch that extends
75 // the thunk to use a chained interceptor. It uses the fact that
76 // SetInternalThunk generates the code to pass as the first parameter whatever
77 // it receives as original_function; we let SidestepResolverThunk set this value
78 // to its saved code, and then we change it to our thunk data.
79 NTSTATUS SmartSidestepResolverThunk::Setup(const void* target_module,
80 const void* interceptor_module,
81 const char* target_name,
82 const char* interceptor_name,
83 const void* interceptor_entry_point,
84 void* thunk_storage,
85 size_t storage_bytes,
86 size_t* storage_used) {
87 if (storage_bytes < GetThunkSize())
88 return STATUS_BUFFER_TOO_SMALL;
89
90 SmartThunk* thunk = reinterpret_cast<SmartThunk*>(thunk_storage);
91 thunk->module_base = target_module;
92
93 NTSTATUS ret;
94 if (interceptor_entry_point) {
95 thunk->interceptor = interceptor_entry_point;
96 } else {
97 ret = ResolveInterceptor(interceptor_module, interceptor_name,
98 &thunk->interceptor);
99 if (!NT_SUCCESS(ret))
100 return ret;
101 }
102
103 // Perform a standard sidestep patch on the last part of the thunk, but point
104 // to our internal smart interceptor.
105 size_t standard_bytes = storage_bytes - offsetof(SmartThunk, sidestep);
106 ret = SidestepResolverThunk::Setup(target_module, interceptor_module,
107 target_name, NULL, &SmartStub,
108 &thunk->sidestep, standard_bytes, NULL);
109 if (!NT_SUCCESS(ret))
110 return ret;
111
112 // Fix the internal thunk to pass the whole buffer to the interceptor.
113 SetInternalThunk(&thunk->sidestep.internal_thunk, GetInternalThunkSize(),
114 thunk_storage, &SmartStub);
115
116 if (storage_used)
117 *storage_used = GetThunkSize();
118
119 return ret;
120 }
121
122 size_t SmartSidestepResolverThunk::GetThunkSize() const {
123 return GetInternalThunkSize() + kSizeOfSidestepStub +
124 offsetof(SmartThunk, sidestep);
125 }
126
127 // This code must basically either call the intended interceptor or skip the
128 // call and invoke instead the original function. In any case, we are saving
129 // the registers that may be trashed by our c++ code.
130 //
131 // This function is called with a first parameter inserted by us, that points
132 // to our SmartThunk. When we call the interceptor we have to replace this
133 // parameter with the one expected by that function (stored inside our
134 // structure); on the other hand, when we skip the interceptor we have to remove
135 // that extra argument before calling the original function.
136 //
137 // When we skip the interceptor, the transformation of the stack looks like:
138 // On Entry: On Use: On Exit:
139 // [param 2] = first real argument [param 2] (esp+1c) [param 2]
140 // [param 1] = our SmartThunk [param 1] (esp+18) [ret address]
141 // [ret address] = real caller [ret address] (esp+14) [xxx]
142 // [xxx] [addr to jump to] (esp+10) [xxx]
143 // [xxx] [saved eax] [xxx]
144 // [xxx] [saved ebx] [xxx]
145 // [xxx] [saved ecx] [xxx]
146 // [xxx] [saved edx] [xxx]
147 __declspec(naked)
148 void SmartSidestepResolverThunk::SmartStub() {
149 __asm {
150 push eax // Space for the jump.
151 push eax // Save registers.
152 push ebx
153 push ecx
154 push edx
155 mov ebx, [esp + 0x18] // First parameter = SmartThunk.
156 mov edx, [esp + 0x14] // Get the return address.
157 mov eax, [ebx]SmartThunk.module_base
158 push edx
159 push eax
160 call SmartSidestepResolverThunk::IsInternalCall
161 add esp, 8
162
163 test eax, eax
164 lea edx, [ebx]SmartThunk.sidestep // The original function.
165 jz call_interceptor
166
167 // Skip this call
168 mov ecx, [esp + 0x14] // Return address.
169 mov [esp + 0x18], ecx // Remove first parameter.
170 mov [esp + 0x10], edx
171 pop edx // Restore registers.
172 pop ecx
173 pop ebx
174 pop eax
175 ret 4 // Jump to original function.
176
177 call_interceptor:
178 mov ecx, [ebx]SmartThunk.interceptor
179 mov [esp + 0x18], edx // Replace first parameter.
180 mov [esp + 0x10], ecx
181 pop edx // Restore registers.
182 pop ecx
183 pop ebx
184 pop eax
185 ret // Jump to original function.
186 }
187 }
188
189 bool SmartSidestepResolverThunk::IsInternalCall(const void* base,
190 void* return_address) {
191 DCHECK_NT(base);
192 DCHECK_NT(return_address);
193
194 base::win::PEImage pe(base);
195 if (pe.GetImageSectionFromAddr(return_address))
196 return true;
197 return false;
198 }
199
200 } // namespace sandbox
OLDNEW
« no previous file with comments | « sandbox/src/sidestep_resolver.h ('k') | sandbox/src/sync_dispatcher.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698