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/policy_engine_opcodes.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/policy_engine_opcodes.h ('k') | sandbox/win/src/policy_engine_params.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/policy_engine_opcodes.h"
6
7 #include <stddef.h>
8 #include <stdint.h>
9
10 #include "sandbox/win/src/sandbox_nt_types.h"
11 #include "sandbox/win/src/sandbox_types.h"
12
13 namespace {
14 const unsigned short kMaxUniStrSize = 0xfffc / sizeof(wchar_t);
15
16 bool InitStringUnicode(const wchar_t* source, size_t length,
17 UNICODE_STRING* ustring) {
18 if (length > kMaxUniStrSize) {
19 return false;
20 }
21 ustring->Buffer = const_cast<wchar_t*>(source);
22 ustring->Length = static_cast<USHORT>(length) * sizeof(wchar_t);
23 ustring->MaximumLength = (NULL != source) ?
24 ustring->Length + sizeof(wchar_t) : 0;
25 return true;
26 }
27
28 } // namespace
29
30 namespace sandbox {
31
32 SANDBOX_INTERCEPT NtExports g_nt;
33
34 // Note: The opcodes are implemented as functions (as opposed to classes derived
35 // from PolicyOpcode) because you should not add more member variables to the
36 // PolicyOpcode class since it would cause object slicing on the target. So to
37 // enforce that (instead of just trusting the developer) the opcodes became
38 // just functions.
39 //
40 // In the code that follows I have keep the evaluation function and the factory
41 // function together to stress the close relationship between both. For example,
42 // only the factory method and the evaluation function know the stored argument
43 // order and meaning.
44
45 template <int>
46 EvalResult OpcodeEval(PolicyOpcode* opcode, const ParameterSet* pp,
47 MatchContext* match);
48
49 //////////////////////////////////////////////////////////////////////////////
50 // Opcode OpAlwaysFalse:
51 // Does not require input parameter.
52
53 PolicyOpcode* OpcodeFactory::MakeOpAlwaysFalse(uint32_t options) {
54 return MakeBase(OP_ALWAYS_FALSE, options, -1);
55 }
56
57 template <>
58 EvalResult OpcodeEval<OP_ALWAYS_FALSE>(PolicyOpcode* opcode,
59 const ParameterSet* param,
60 MatchContext* context) {
61 return EVAL_FALSE;
62 }
63
64 //////////////////////////////////////////////////////////////////////////////
65 // Opcode OpAlwaysTrue:
66 // Does not require input parameter.
67
68 PolicyOpcode* OpcodeFactory::MakeOpAlwaysTrue(uint32_t options) {
69 return MakeBase(OP_ALWAYS_TRUE, options, -1);
70 }
71
72 template <>
73 EvalResult OpcodeEval<OP_ALWAYS_TRUE>(PolicyOpcode* opcode,
74 const ParameterSet* param,
75 MatchContext* context) {
76 return EVAL_TRUE;
77 }
78
79 //////////////////////////////////////////////////////////////////////////////
80 // Opcode OpAction:
81 // Does not require input parameter.
82 // Argument 0 contains the actual action to return.
83
84 PolicyOpcode* OpcodeFactory::MakeOpAction(EvalResult action, uint32_t options) {
85 PolicyOpcode* opcode = MakeBase(OP_ACTION, options, 0);
86 if (NULL == opcode) return NULL;
87 opcode->SetArgument(0, action);
88 return opcode;
89 }
90
91 template <>
92 EvalResult OpcodeEval<OP_ACTION>(PolicyOpcode* opcode,
93 const ParameterSet* param,
94 MatchContext* context) {
95 int action = 0;
96 opcode->GetArgument(0, &action);
97 return static_cast<EvalResult>(action);
98 }
99
100 //////////////////////////////////////////////////////////////////////////////
101 // Opcode OpNumberMatch:
102 // Requires a uint32_t or void* in selected_param
103 // Argument 0 is the stored number to match.
104 // Argument 1 is the C++ type of the 0th argument.
105
106 PolicyOpcode* OpcodeFactory::MakeOpNumberMatch(int16_t selected_param,
107 uint32_t match,
108 uint32_t options) {
109 PolicyOpcode* opcode = MakeBase(OP_NUMBER_MATCH, options, selected_param);
110 if (NULL == opcode) return NULL;
111 opcode->SetArgument(0, match);
112 opcode->SetArgument(1, UINT32_TYPE);
113 return opcode;
114 }
115
116 PolicyOpcode* OpcodeFactory::MakeOpVoidPtrMatch(int16_t selected_param,
117 const void* match,
118 uint32_t options) {
119 PolicyOpcode* opcode = MakeBase(OP_NUMBER_MATCH, options, selected_param);
120 if (NULL == opcode) return NULL;
121 opcode->SetArgument(0, match);
122 opcode->SetArgument(1, VOIDPTR_TYPE);
123 return opcode;
124 }
125
126 template <>
127 EvalResult OpcodeEval<OP_NUMBER_MATCH>(PolicyOpcode* opcode,
128 const ParameterSet* param,
129 MatchContext* context) {
130 uint32_t value_uint32 = 0;
131 if (param->Get(&value_uint32)) {
132 uint32_t match_uint32 = 0;
133 opcode->GetArgument(0, &match_uint32);
134 return (match_uint32 != value_uint32)? EVAL_FALSE : EVAL_TRUE;
135 } else {
136 const void* value_ptr = NULL;
137 if (param->Get(&value_ptr)) {
138 const void* match_ptr = NULL;
139 opcode->GetArgument(0, &match_ptr);
140 return (match_ptr != value_ptr)? EVAL_FALSE : EVAL_TRUE;
141 }
142 }
143 return EVAL_ERROR;
144 }
145
146 //////////////////////////////////////////////////////////////////////////////
147 // Opcode OpNumberMatchRange
148 // Requires a uint32_t in selected_param.
149 // Argument 0 is the stored lower bound to match.
150 // Argument 1 is the stored upper bound to match.
151
152 PolicyOpcode* OpcodeFactory::MakeOpNumberMatchRange(int16_t selected_param,
153 uint32_t lower_bound,
154 uint32_t upper_bound,
155 uint32_t options) {
156 if (lower_bound > upper_bound) {
157 return NULL;
158 }
159 PolicyOpcode* opcode = MakeBase(OP_NUMBER_MATCH_RANGE, options,
160 selected_param);
161 if (NULL == opcode) return NULL;
162 opcode->SetArgument(0, lower_bound);
163 opcode->SetArgument(1, upper_bound);
164 return opcode;
165 }
166
167 template <>
168 EvalResult OpcodeEval<OP_NUMBER_MATCH_RANGE>(PolicyOpcode* opcode,
169 const ParameterSet* param,
170 MatchContext* context) {
171 uint32_t value = 0;
172 if (!param->Get(&value)) return EVAL_ERROR;
173
174 uint32_t lower_bound = 0;
175 uint32_t upper_bound = 0;
176 opcode->GetArgument(0, &lower_bound);
177 opcode->GetArgument(1, &upper_bound);
178 return((lower_bound <= value) && (upper_bound >= value))?
179 EVAL_TRUE : EVAL_FALSE;
180 }
181
182 //////////////////////////////////////////////////////////////////////////////
183 // Opcode OpNumberAndMatch:
184 // Requires a uint32_t in selected_param.
185 // Argument 0 is the stored number to match.
186
187 PolicyOpcode* OpcodeFactory::MakeOpNumberAndMatch(int16_t selected_param,
188 uint32_t match,
189 uint32_t options) {
190 PolicyOpcode* opcode = MakeBase(OP_NUMBER_AND_MATCH, options, selected_param);
191 if (NULL == opcode) return NULL;
192 opcode->SetArgument(0, match);
193 return opcode;
194 }
195
196 template <>
197 EvalResult OpcodeEval<OP_NUMBER_AND_MATCH>(PolicyOpcode* opcode,
198 const ParameterSet* param,
199 MatchContext* context) {
200 uint32_t value = 0;
201 if (!param->Get(&value)) return EVAL_ERROR;
202
203 uint32_t number = 0;
204 opcode->GetArgument(0, &number);
205 return (number & value)? EVAL_TRUE : EVAL_FALSE;
206 }
207
208 //////////////////////////////////////////////////////////////////////////////
209 // Opcode OpWStringMatch:
210 // Requires a wchar_t* in selected_param.
211 // Argument 0 is the byte displacement of the stored string.
212 // Argument 1 is the lenght in chars of the stored string.
213 // Argument 2 is the offset to apply on the input string. It has special values.
214 // as noted in the header file.
215 // Argument 3 is the string matching options.
216
217 PolicyOpcode* OpcodeFactory::MakeOpWStringMatch(int16_t selected_param,
218 const wchar_t* match_str,
219 int start_position,
220 StringMatchOptions match_opts,
221 uint32_t options) {
222 if (NULL == match_str) {
223 return NULL;
224 }
225 if ('\0' == match_str[0]) {
226 return NULL;
227 }
228
229 int lenght = lstrlenW(match_str);
230
231 PolicyOpcode* opcode = MakeBase(OP_WSTRING_MATCH, options, selected_param);
232 if (NULL == opcode) {
233 return NULL;
234 }
235 ptrdiff_t delta_str = AllocRelative(opcode, match_str, wcslen(match_str)+1);
236 if (0 == delta_str) {
237 return NULL;
238 }
239 opcode->SetArgument(0, delta_str);
240 opcode->SetArgument(1, lenght);
241 opcode->SetArgument(2, start_position);
242 opcode->SetArgument(3, match_opts);
243 return opcode;
244 }
245
246 template<>
247 EvalResult OpcodeEval<OP_WSTRING_MATCH>(PolicyOpcode* opcode,
248 const ParameterSet* param,
249 MatchContext* context) {
250 if (NULL == context) {
251 return EVAL_ERROR;
252 }
253 const wchar_t* source_str = NULL;
254 if (!param->Get(&source_str)) return EVAL_ERROR;
255
256 int start_position = 0;
257 int match_len = 0;
258 unsigned int match_opts = 0;
259 opcode->GetArgument(1, &match_len);
260 opcode->GetArgument(2, &start_position);
261 opcode->GetArgument(3, &match_opts);
262
263 const wchar_t* match_str = opcode->GetRelativeString(0);
264 // Advance the source string to the last successfully evaluated position
265 // according to the match context.
266 source_str = &source_str[context->position];
267 int source_len = static_cast<int>(g_nt.wcslen(source_str));
268
269 if (0 == source_len) {
270 // If we reached the end of the source string there is nothing we can
271 // match against.
272 return EVAL_FALSE;
273 }
274 if (match_len > source_len) {
275 // There can't be a positive match when the target string is bigger than
276 // the source string
277 return EVAL_FALSE;
278 }
279
280 BOOLEAN case_sensitive = (match_opts & CASE_INSENSITIVE) ? TRUE : FALSE;
281
282 // We have three cases, depending on the value of start_pos:
283 // Case 1. We skip N characters and compare once.
284 // Case 2: We skip to the end and compare once.
285 // Case 3: We match the first substring (if we find any).
286 if (start_position >= 0) {
287 if (kSeekToEnd == start_position) {
288 start_position = source_len - match_len;
289 } else if (match_opts & EXACT_LENGHT) {
290 // A sub-case of case 3 is when the EXACT_LENGHT flag is on
291 // the match needs to be not just substring but full match.
292 if ((match_len + start_position) != source_len) {
293 return EVAL_FALSE;
294 }
295 }
296
297 // Advance start_pos characters. Warning! this does not consider
298 // utf16 encodings (surrogate pairs) or other Unicode 'features'.
299 source_str += start_position;
300
301 // Since we skipped, lets reevaluate just the lengths again.
302 if ((match_len + start_position) > source_len) {
303 return EVAL_FALSE;
304 }
305
306 UNICODE_STRING match_ustr;
307 UNICODE_STRING source_ustr;
308 if (!InitStringUnicode(match_str, match_len, &match_ustr) ||
309 !InitStringUnicode(source_str, match_len, &source_ustr))
310 return EVAL_ERROR;
311
312 if (0 == g_nt.RtlCompareUnicodeString(&match_ustr, &source_ustr,
313 case_sensitive)) {
314 // Match! update the match context.
315 context->position += start_position + match_len;
316 return EVAL_TRUE;
317 } else {
318 return EVAL_FALSE;
319 }
320 } else if (start_position < 0) {
321 UNICODE_STRING match_ustr;
322 UNICODE_STRING source_ustr;
323 if (!InitStringUnicode(match_str, match_len, &match_ustr) ||
324 !InitStringUnicode(source_str, match_len, &source_ustr))
325 return EVAL_ERROR;
326
327 do {
328 if (0 == g_nt.RtlCompareUnicodeString(&match_ustr, &source_ustr,
329 case_sensitive)) {
330 // Match! update the match context.
331 context->position += (source_ustr.Buffer - source_str) + match_len;
332 return EVAL_TRUE;
333 }
334 ++source_ustr.Buffer;
335 --source_len;
336 } while (source_len >= match_len);
337 }
338 return EVAL_FALSE;
339 }
340
341 //////////////////////////////////////////////////////////////////////////////
342 // OpcodeMaker (other member functions).
343
344 PolicyOpcode* OpcodeFactory::MakeBase(OpcodeID opcode_id,
345 uint32_t options,
346 int16_t selected_param) {
347 if (memory_size() < sizeof(PolicyOpcode)) {
348 return NULL;
349 }
350
351 // Create opcode using placement-new on the buffer memory.
352 PolicyOpcode* opcode = new(memory_top_) PolicyOpcode();
353
354 // Fill in the standard fields, that every opcode has.
355 memory_top_ += sizeof(PolicyOpcode);
356 opcode->opcode_id_ = opcode_id;
357 opcode->SetOptions(options);
358 opcode->parameter_ = selected_param;
359 return opcode;
360 }
361
362 ptrdiff_t OpcodeFactory::AllocRelative(void* start, const wchar_t* str,
363 size_t lenght) {
364 size_t bytes = lenght * sizeof(wchar_t);
365 if (memory_size() < bytes) {
366 return 0;
367 }
368 memory_bottom_ -= bytes;
369 if (reinterpret_cast<UINT_PTR>(memory_bottom_) & 1) {
370 // TODO(cpu) replace this for something better.
371 ::DebugBreak();
372 }
373 memcpy(memory_bottom_, str, bytes);
374 ptrdiff_t delta = memory_bottom_ - reinterpret_cast<char*>(start);
375 return delta;
376 }
377
378 //////////////////////////////////////////////////////////////////////////////
379 // Opcode evaluation dispatchers.
380
381 // This function is the one and only entry for evaluating any opcode. It is
382 // in charge of applying any relevant opcode options and calling EvaluateInner
383 // were the actual dispatch-by-id is made. It would seem at first glance that
384 // the dispatch should be done by virtual function (vtable) calls but you have
385 // to remember that the opcodes are made in the broker process and copied as
386 // raw memory to the target process.
387
388 EvalResult PolicyOpcode::Evaluate(const ParameterSet* call_params,
389 size_t param_count, MatchContext* match) {
390 if (NULL == call_params) {
391 return EVAL_ERROR;
392 }
393 const ParameterSet* selected_param = NULL;
394 if (parameter_ >= 0) {
395 if (static_cast<size_t>(parameter_) >= param_count) {
396 return EVAL_ERROR;
397 }
398 selected_param = &call_params[parameter_];
399 }
400 EvalResult result = EvaluateHelper(selected_param, match);
401
402 // Apply the general options regardless of the particular type of opcode.
403 if (kPolNone == options_) {
404 return result;
405 }
406
407 if (options_ & kPolNegateEval) {
408 if (EVAL_TRUE == result) {
409 result = EVAL_FALSE;
410 } else if (EVAL_FALSE == result) {
411 result = EVAL_TRUE;
412 } else if (EVAL_ERROR != result) {
413 result = EVAL_ERROR;
414 }
415 }
416 if (NULL != match) {
417 if (options_ & kPolClearContext) {
418 match->Clear();
419 }
420 if (options_ & kPolUseOREval) {
421 match->options = kPolUseOREval;
422 }
423 }
424 return result;
425 }
426
427 #define OPCODE_EVAL(op, x, y, z) case op: return OpcodeEval<op>(x, y, z)
428
429 EvalResult PolicyOpcode::EvaluateHelper(const ParameterSet* parameters,
430 MatchContext* match) {
431 switch (opcode_id_) {
432 OPCODE_EVAL(OP_ALWAYS_FALSE, this, parameters, match);
433 OPCODE_EVAL(OP_ALWAYS_TRUE, this, parameters, match);
434 OPCODE_EVAL(OP_NUMBER_MATCH, this, parameters, match);
435 OPCODE_EVAL(OP_NUMBER_MATCH_RANGE, this, parameters, match);
436 OPCODE_EVAL(OP_NUMBER_AND_MATCH, this, parameters, match);
437 OPCODE_EVAL(OP_WSTRING_MATCH, this, parameters, match);
438 OPCODE_EVAL(OP_ACTION, this, parameters, match);
439 default:
440 return EVAL_ERROR;
441 }
442 }
443
444 #undef OPCODE_EVAL
445
446 } // namespace sandbox
OLDNEW
« no previous file with comments | « sandbox/win/src/policy_engine_opcodes.h ('k') | sandbox/win/src/policy_engine_params.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698