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

Side by Side Diff: sandbox/win/src/crosscall_server.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/crosscall_server.h ('k') | sandbox/win/src/eat_resolver.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) 2012 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/crosscall_server.h"
6
7 #include <stddef.h>
8 #include <stdint.h>
9
10 #include <string>
11 #include <vector>
12
13 #include "base/logging.h"
14 #include "sandbox/win/src/crosscall_client.h"
15 #include "sandbox/win/src/crosscall_params.h"
16
17 // This code performs the ipc message validation. Potential security flaws
18 // on the ipc are likelier to be found in this code than in the rest of
19 // the ipc code.
20
21 namespace {
22
23 // The buffer for a message must match the max channel size.
24 const size_t kMaxBufferSize = sandbox::kIPCChannelSize;
25
26 }
27
28 namespace sandbox {
29
30 // Returns the actual size for the parameters in an IPC buffer. Returns
31 // zero if the |param_count| is zero or too big.
32 uint32_t GetActualBufferSize(uint32_t param_count, void* buffer_base) {
33 // The template types are used to calculate the maximum expected size.
34 typedef ActualCallParams<1, kMaxBufferSize> ActualCP1;
35 typedef ActualCallParams<2, kMaxBufferSize> ActualCP2;
36 typedef ActualCallParams<3, kMaxBufferSize> ActualCP3;
37 typedef ActualCallParams<4, kMaxBufferSize> ActualCP4;
38 typedef ActualCallParams<5, kMaxBufferSize> ActualCP5;
39 typedef ActualCallParams<6, kMaxBufferSize> ActualCP6;
40 typedef ActualCallParams<7, kMaxBufferSize> ActualCP7;
41 typedef ActualCallParams<8, kMaxBufferSize> ActualCP8;
42 typedef ActualCallParams<9, kMaxBufferSize> ActualCP9;
43
44 // Retrieve the actual size and the maximum size of the params buffer.
45 switch (param_count) {
46 case 0:
47 return 0;
48 case 1:
49 return reinterpret_cast<ActualCP1*>(buffer_base)->GetSize();
50 case 2:
51 return reinterpret_cast<ActualCP2*>(buffer_base)->GetSize();
52 case 3:
53 return reinterpret_cast<ActualCP3*>(buffer_base)->GetSize();
54 case 4:
55 return reinterpret_cast<ActualCP4*>(buffer_base)->GetSize();
56 case 5:
57 return reinterpret_cast<ActualCP5*>(buffer_base)->GetSize();
58 case 6:
59 return reinterpret_cast<ActualCP6*>(buffer_base)->GetSize();
60 case 7:
61 return reinterpret_cast<ActualCP7*>(buffer_base)->GetSize();
62 case 8:
63 return reinterpret_cast<ActualCP8*>(buffer_base)->GetSize();
64 case 9:
65 return reinterpret_cast<ActualCP9*>(buffer_base)->GetSize();
66 default:
67 return 0;
68 }
69 }
70
71 // Verifies that the declared sizes of an IPC buffer are within range.
72 bool IsSizeWithinRange(uint32_t buffer_size,
73 uint32_t min_declared_size,
74 uint32_t declared_size) {
75 if ((buffer_size < min_declared_size) ||
76 (sizeof(CrossCallParamsEx) > min_declared_size)) {
77 // Minimal computed size bigger than existing buffer or param_count
78 // integer overflow.
79 return false;
80 }
81
82 if ((declared_size > buffer_size) || (declared_size < min_declared_size)) {
83 // Declared size is bigger than buffer or smaller than computed size
84 // or param_count is equal to 0 or bigger than 9.
85 return false;
86 }
87
88 return true;
89 }
90
91 CrossCallParamsEx::CrossCallParamsEx()
92 :CrossCallParams(0, 0) {
93 }
94
95 // We override the delete operator because the object's backing memory
96 // is hand allocated in CreateFromBuffer. We don't override the new operator
97 // because the constructors are private so there is no way to mismatch
98 // new & delete.
99 void CrossCallParamsEx::operator delete(void* raw_memory) throw() {
100 if (NULL == raw_memory) {
101 // C++ standard allows 'delete 0' behavior.
102 return;
103 }
104 delete[] reinterpret_cast<char*>(raw_memory);
105 }
106
107 // This function uses a SEH try block so cannot use C++ objects that
108 // have destructors or else you get Compiler Error C2712. So no DCHECKs
109 // inside this function.
110 CrossCallParamsEx* CrossCallParamsEx::CreateFromBuffer(void* buffer_base,
111 uint32_t buffer_size,
112 uint32_t* output_size) {
113 // IMPORTANT: Everything inside buffer_base and derived from it such
114 // as param_count and declared_size is untrusted.
115 if (NULL == buffer_base) {
116 return NULL;
117 }
118 if (buffer_size < sizeof(CrossCallParams)) {
119 return NULL;
120 }
121 if (buffer_size > kMaxBufferSize) {
122 return NULL;
123 }
124
125 char* backing_mem = NULL;
126 uint32_t param_count = 0;
127 uint32_t declared_size;
128 uint32_t min_declared_size;
129 CrossCallParamsEx* copied_params = NULL;
130
131 // Touching the untrusted buffer is done under a SEH try block. This
132 // will catch memory access violations so we don't crash.
133 __try {
134 CrossCallParams* call_params =
135 reinterpret_cast<CrossCallParams*>(buffer_base);
136
137 // Check against the minimum size given the number of stated params
138 // if too small we bail out.
139 param_count = call_params->GetParamsCount();
140 min_declared_size = sizeof(CrossCallParams) +
141 ((param_count + 1) * sizeof(ParamInfo));
142
143 // Retrieve the declared size which if it fails returns 0.
144 declared_size = GetActualBufferSize(param_count, buffer_base);
145
146 if (!IsSizeWithinRange(buffer_size, min_declared_size, declared_size))
147 return NULL;
148
149 // Now we copy the actual amount of the message.
150 *output_size = declared_size;
151 backing_mem = new char[declared_size];
152 copied_params = reinterpret_cast<CrossCallParamsEx*>(backing_mem);
153 memcpy(backing_mem, call_params, declared_size);
154
155 // Avoid compiler optimizations across this point. Any value stored in
156 // memory should be stored for real, and values previously read from memory
157 // should be actually read.
158 _ReadWriteBarrier();
159
160 min_declared_size = sizeof(CrossCallParams) +
161 ((param_count + 1) * sizeof(ParamInfo));
162
163 // Check that the copied buffer is still valid.
164 if (copied_params->GetParamsCount() != param_count ||
165 GetActualBufferSize(param_count, backing_mem) != declared_size ||
166 !IsSizeWithinRange(buffer_size, min_declared_size, declared_size)) {
167 delete [] backing_mem;
168 return NULL;
169 }
170
171 } __except(EXCEPTION_EXECUTE_HANDLER) {
172 // In case of a windows exception we know it occurred while touching the
173 // untrusted buffer so we bail out as is.
174 delete [] backing_mem;
175 return NULL;
176 }
177
178 const char* last_byte = &backing_mem[declared_size];
179 const char* first_byte = &backing_mem[min_declared_size];
180
181 // Verify here that all and each parameters make sense. This is done in the
182 // local copy.
183 for (uint32_t ix = 0; ix != param_count; ++ix) {
184 uint32_t size = 0;
185 ArgType type;
186 char* address = reinterpret_cast<char*>(
187 copied_params->GetRawParameter(ix, &size, &type));
188 if ((NULL == address) || // No null params.
189 (INVALID_TYPE >= type) || (LAST_TYPE <= type) || // Unknown type.
190 (address < backing_mem) || // Start cannot point before buffer.
191 (address < first_byte) || // Start cannot point too low.
192 (address > last_byte) || // Start cannot point past buffer.
193 ((address + size) < address) || // Invalid size.
194 ((address + size) > last_byte)) { // End cannot point past buffer.
195 // Malformed.
196 delete[] backing_mem;
197 return NULL;
198 }
199 }
200 // The parameter buffer looks good.
201 return copied_params;
202 }
203
204 // Accessors to the parameters in the raw buffer.
205 void* CrossCallParamsEx::GetRawParameter(uint32_t index,
206 uint32_t* size,
207 ArgType* type) {
208 if (index >= GetParamsCount()) {
209 return NULL;
210 }
211 // The size is always computed from the parameter minus the next
212 // parameter, this works because the message has an extra parameter slot
213 *size = param_info_[index].size_;
214 *type = param_info_[index].type_;
215
216 return param_info_[index].offset_ + reinterpret_cast<char*>(this);
217 }
218
219 // Covers common case for 32 bit integers.
220 bool CrossCallParamsEx::GetParameter32(uint32_t index, uint32_t* param) {
221 uint32_t size = 0;
222 ArgType type;
223 void* start = GetRawParameter(index, &size, &type);
224 if ((NULL == start) || (4 != size) || (UINT32_TYPE != type)) {
225 return false;
226 }
227 // Copy the 4 bytes.
228 *(reinterpret_cast<uint32_t*>(param)) = *(reinterpret_cast<uint32_t*>(start));
229 return true;
230 }
231
232 bool CrossCallParamsEx::GetParameterVoidPtr(uint32_t index, void** param) {
233 uint32_t size = 0;
234 ArgType type;
235 void* start = GetRawParameter(index, &size, &type);
236 if ((NULL == start) || (sizeof(void*) != size) || (VOIDPTR_TYPE != type)) {
237 return false;
238 }
239 *param = *(reinterpret_cast<void**>(start));
240 return true;
241 }
242
243 // Covers the common case of reading a string. Note that the string is not
244 // scanned for invalid characters.
245 bool CrossCallParamsEx::GetParameterStr(uint32_t index,
246 base::string16* string) {
247 uint32_t size = 0;
248 ArgType type;
249 void* start = GetRawParameter(index, &size, &type);
250 if (WCHAR_TYPE != type) {
251 return false;
252 }
253
254 // Check if this is an empty string.
255 if (size == 0) {
256 *string = L"";
257 return true;
258 }
259
260 if ((NULL == start) || ((size % sizeof(wchar_t)) != 0)) {
261 return false;
262 }
263 string->append(reinterpret_cast<wchar_t*>(start), size/(sizeof(wchar_t)));
264 return true;
265 }
266
267 bool CrossCallParamsEx::GetParameterPtr(uint32_t index,
268 uint32_t expected_size,
269 void** pointer) {
270 uint32_t size = 0;
271 ArgType type;
272 void* start = GetRawParameter(index, &size, &type);
273
274 if ((size != expected_size) || (INOUTPTR_TYPE != type)) {
275 return false;
276 }
277
278 if (NULL == start) {
279 return false;
280 }
281
282 *pointer = start;
283 return true;
284 }
285
286 void SetCallError(ResultCode error, CrossCallReturn* call_return) {
287 call_return->call_outcome = error;
288 call_return->extended_count = 0;
289 }
290
291 void SetCallSuccess(CrossCallReturn* call_return) {
292 call_return->call_outcome = SBOX_ALL_OK;
293 }
294
295 Dispatcher* Dispatcher::OnMessageReady(IPCParams* ipc,
296 CallbackGeneric* callback) {
297 DCHECK(callback);
298 std::vector<IPCCall>::iterator it = ipc_calls_.begin();
299 for (; it != ipc_calls_.end(); ++it) {
300 if (it->params.Matches(ipc)) {
301 *callback = it->callback;
302 return this;
303 }
304 }
305 return NULL;
306 }
307
308 Dispatcher::Dispatcher() {
309 }
310
311 Dispatcher::~Dispatcher() {
312 }
313
314 } // namespace sandbox
OLDNEW
« no previous file with comments | « sandbox/win/src/crosscall_server.h ('k') | sandbox/win/src/eat_resolver.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698