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

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

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

Powered by Google App Engine
This is Rietveld 408576698