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

Side by Side Diff: sandbox/win/src/policy_engine_opcodes.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/policy_broker.cc ('k') | sandbox/win/src/policy_engine_opcodes.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) 2010 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 #ifndef SANDBOX_WIN_SRC_POLICY_ENGINE_OPCODES_H_
6 #define SANDBOX_WIN_SRC_POLICY_ENGINE_OPCODES_H_
7
8 #include <stddef.h>
9 #include <stdint.h>
10
11 #include "base/macros.h"
12 #include "base/numerics/safe_conversions.h"
13 #include "sandbox/win/src/policy_engine_params.h"
14
15 // The low-level policy is implemented using the concept of policy 'opcodes'.
16 // An opcode is a structure that contains enough information to perform one
17 // comparison against one single input parameter. For example, an opcode can
18 // encode just one of the following comparison:
19 //
20 // - Is input parameter 3 not equal to NULL?
21 // - Does input parameter 2 start with L"c:\\"?
22 // - Is input parameter 5, bit 3 is equal 1?
23 //
24 // Each opcode is in fact equivalent to a function invocation where all
25 // the parameters are known by the opcode except one. So say you have a
26 // function of this form:
27 // bool fn(a, b, c, d) with 4 arguments
28 //
29 // Then an opcode is:
30 // op(fn, b, c, d)
31 // Which stores the function to call and its 3 last arguments
32 //
33 // Then and opcode evaluation is:
34 // op.eval(a) ------------------------> fn(a,b,c,d)
35 // internally calls
36 //
37 // The idea is that complex policy rules can be split into streams of
38 // opcodes which are evaluated in sequence. The evaluation is done in
39 // groups of opcodes that have N comparison opcodes plus 1 action opcode:
40 //
41 // [comparison 1][comparison 2]...[comparison N][action][comparison 1]...
42 // ----- evaluation order----------->
43 //
44 // Each opcode group encodes one high-level policy rule. The rule applies
45 // only if all the conditions on the group evaluate to true. The action
46 // opcode contains the policy outcome for that particular rule.
47 //
48 // Note that this header contains the main building blocks of low-level policy
49 // but not the low level policy class.
50 namespace sandbox {
51
52 // These are the possible policy outcomes. Note that some of them might
53 // not apply and can be removed. Also note that The following values only
54 // specify what to do, not how to do it and it is acceptable given specific
55 // cases to ignore the policy outcome.
56 enum EvalResult {
57 // Comparison opcode values:
58 EVAL_TRUE, // Opcode condition evaluated true.
59 EVAL_FALSE, // Opcode condition evaluated false.
60 EVAL_ERROR, // Opcode condition generated an error while evaluating.
61 // Action opcode values:
62 ASK_BROKER, // The target must generate an IPC to the broker. On the broker
63 // side, this means grant access to the resource.
64 DENY_ACCESS, // No access granted to the resource.
65 GIVE_READONLY, // Give readonly access to the resource.
66 GIVE_ALLACCESS, // Give full access to the resource.
67 GIVE_CACHED, // IPC is not required. Target can return a cached handle.
68 GIVE_FIRST, // TODO(cpu)
69 SIGNAL_ALARM, // Unusual activity. Generate an alarm.
70 FAKE_SUCCESS, // Do not call original function. Just return 'success'.
71 FAKE_ACCESS_DENIED, // Do not call original function. Just return 'denied'
72 // and do not do IPC.
73 TERMINATE_PROCESS, // Destroy target process. Do IPC as well.
74 };
75
76 // The following are the implemented opcodes.
77 enum OpcodeID {
78 OP_ALWAYS_FALSE, // Evaluates to false (EVAL_FALSE).
79 OP_ALWAYS_TRUE, // Evaluates to true (EVAL_TRUE).
80 OP_NUMBER_MATCH, // Match a 32-bit integer as n == a.
81 OP_NUMBER_MATCH_RANGE, // Match a 32-bit integer as a <= n <= b.
82 OP_NUMBER_AND_MATCH, // Match using bitwise AND; as in: n & a != 0.
83 OP_WSTRING_MATCH, // Match a string for equality.
84 OP_ACTION // Evaluates to an action opcode.
85 };
86
87 // Options that apply to every opcode. They are specified when creating
88 // each opcode using OpcodeFactory::MakeOpXXXXX() family of functions
89 // Do nothing special.
90 const uint32_t kPolNone = 0;
91
92 // Convert EVAL_TRUE into EVAL_FALSE and vice-versa. This allows to express
93 // negated conditions such as if ( a && !b).
94 const uint32_t kPolNegateEval = 1;
95
96 // Zero the MatchContext context structure. This happens after the opcode
97 // is evaluated.
98 const uint32_t kPolClearContext = 2;
99
100 // Use OR when evaluating this set of opcodes. The policy evaluator by default
101 // uses AND when evaluating. Very helpful when
102 // used with kPolNegateEval. For example if you have a condition best expressed
103 // as if(! (a && b && c)), the use of this flags allows it to be expressed as
104 // if ((!a) || (!b) || (!c)).
105 const uint32_t kPolUseOREval = 4;
106
107 // Keeps the evaluation state between opcode evaluations. This is used
108 // for string matching where the next opcode needs to continue matching
109 // from the last character position from the current opcode. The match
110 // context is preserved across opcode evaluation unless an opcode specifies
111 // as an option kPolClearContext.
112 struct MatchContext {
113 size_t position;
114 uint32_t options;
115
116 MatchContext() {
117 Clear();
118 }
119
120 void Clear() {
121 position = 0;
122 options = 0;
123 }
124 };
125
126 // Models a policy opcode; that is a condition evaluation were all the
127 // arguments but one are stored in objects of this class. Use OpcodeFactory
128 // to create objects of this type.
129 // This class is just an implementation artifact and not exposed to the
130 // API clients or visible in the intercepted service. Internally, an
131 // opcode is just:
132 // - An integer that identifies the actual opcode.
133 // - An index to indicate which one is the input argument
134 // - An array of arguments.
135 // While an OO hierarchy of objects would have been a natural choice, the fact
136 // that 1) this code can execute before the CRT is loaded, presents serious
137 // problems in terms of guarantees about the actual state of the vtables and
138 // 2) because the opcode objects are generated in the broker process, we need to
139 // use plain objects. To preserve some minimal type safety templates are used
140 // when possible.
141 class PolicyOpcode {
142 friend class OpcodeFactory;
143 public:
144 // Evaluates the opcode. For a typical comparison opcode the return value
145 // is EVAL_TRUE or EVAL_FALSE. If there was an error in the evaluation the
146 // the return is EVAL_ERROR. If the opcode is an action opcode then the
147 // return can take other values such as ASK_BROKER.
148 // parameters: An array of all input parameters. This argument is normally
149 // created by the macros POLPARAMS_BEGIN() POLPARAMS_END.
150 // count: The number of parameters passed as first argument.
151 // match: The match context that is persisted across the opcode evaluation
152 // sequence.
153 EvalResult Evaluate(const ParameterSet* parameters, size_t count,
154 MatchContext* match);
155
156 // Retrieves a stored argument by index. Valid index values are
157 // from 0 to < kArgumentCount.
158 template <typename T>
159 void GetArgument(size_t index, T* argument) const {
160 static_assert(sizeof(T) <= sizeof(arguments_[0]), "invalid size");
161 *argument = *reinterpret_cast<const T*>(&arguments_[index].mem);
162 }
163
164 // Sets a stored argument by index. Valid index values are
165 // from 0 to < kArgumentCount.
166 template <typename T>
167 void SetArgument(size_t index, const T& argument) {
168 static_assert(sizeof(T) <= sizeof(arguments_[0]), "invalid size");
169 *reinterpret_cast<T*>(&arguments_[index].mem) = argument;
170 }
171
172 // Retrieves the actual address of an string argument. When using
173 // GetArgument() to retrieve an index that contains a string, the returned
174 // value is just an offset to the actual string.
175 // index: the stored string index. Valid values are from 0
176 // to < kArgumentCount.
177 const wchar_t* GetRelativeString(size_t index) const {
178 ptrdiff_t str_delta = 0;
179 GetArgument(index, &str_delta);
180 const char* delta = reinterpret_cast<const char*>(this) + str_delta;
181 return reinterpret_cast<const wchar_t*>(delta);
182 }
183
184 // Returns true if this opcode is an action opcode without actually
185 // evaluating it. Used to do a quick scan forward to the next opcode group.
186 bool IsAction() const {
187 return (OP_ACTION == opcode_id_);
188 };
189
190 // Returns the opcode type.
191 OpcodeID GetID() const {
192 return opcode_id_;
193 }
194
195 // Returns the stored options such as kPolNegateEval and others.
196 uint32_t GetOptions() const { return options_; }
197
198 // Sets the stored options such as kPolNegateEval.
199 void SetOptions(uint32_t options) {
200 options_ = base::checked_cast<uint16_t>(options);
201 }
202
203 private:
204
205 static const size_t kArgumentCount = 4; // The number of supported argument.
206
207 struct OpcodeArgument {
208 UINT_PTR mem;
209 };
210
211 // Better define placement new in the class instead of relying on the
212 // global definition which seems to be fubared.
213 void* operator new(size_t, void* location) {
214 return location;
215 }
216
217 // Helper function to evaluate the opcode. The parameters have the same
218 // meaning that in Evaluate().
219 EvalResult EvaluateHelper(const ParameterSet* parameters,
220 MatchContext* match);
221 OpcodeID opcode_id_;
222 int16_t parameter_;
223 // TODO(cpu): Making |options_| a uint32_t would avoid casting, but causes
224 // test failures. Somewhere code is relying on the size of this struct.
225 // http://crbug.com/420296
226 uint16_t options_;
227 OpcodeArgument arguments_[PolicyOpcode::kArgumentCount];
228 };
229
230 enum StringMatchOptions {
231 CASE_SENSITIVE = 0, // Pay or Not attention to the case as defined by
232 CASE_INSENSITIVE = 1, // RtlCompareUnicodeString windows API.
233 EXACT_LENGHT = 2 // Don't do substring match. Do full string match.
234 };
235
236 // Opcodes that do string comparisons take a parameter that is the starting
237 // position to perform the comparison so we can do substring matching. There
238 // are two special values:
239 //
240 // Start from the current position and compare strings advancing forward until
241 // a match is found if any. Similar to CRT strstr().
242 const int kSeekForward = -1;
243 // Perform a match with the end of the string. It only does a single comparison.
244 const int kSeekToEnd = 0xfffff;
245
246
247 // A PolicyBuffer is a variable size structure that contains all the opcodes
248 // that are to be created or evaluated in sequence.
249 struct PolicyBuffer {
250 size_t opcode_count;
251 PolicyOpcode opcodes[1];
252 };
253
254 // Helper class to create any opcode sequence. This class is normally invoked
255 // only by the high level policy module or when you need to handcraft a special
256 // policy.
257 // The factory works by creating the opcodes using a chunk of memory given
258 // in the constructor. The opcodes themselves are allocated from the beginning
259 // (top) of the memory, while any string that an opcode needs is allocated from
260 // the end (bottom) of the memory.
261 //
262 // In essence:
263 //
264 // low address ---> [opcode 1]
265 // [opcode 2]
266 // [opcode 3]
267 // | | <--- memory_top_
268 // | free |
269 // | |
270 // | | <--- memory_bottom_
271 // [string 1]
272 // high address --> [string 2]
273 //
274 // Note that this class does not keep track of the number of opcodes made and
275 // it is designed to be a building block for low-level policy.
276 //
277 // Note that any of the MakeOpXXXXX member functions below can return NULL on
278 // failure. When that happens opcode sequence creation must be aborted.
279 class OpcodeFactory {
280 public:
281 // memory: base pointer to a chunk of memory where the opcodes are created.
282 // memory_size: the size in bytes of the memory chunk.
283 OpcodeFactory(char* memory, size_t memory_size)
284 : memory_top_(memory) {
285 memory_bottom_ = &memory_top_[memory_size];
286 }
287
288 // policy: contains the raw memory where the opcodes are created.
289 // memory_size: contains the actual size of the policy argument.
290 OpcodeFactory(PolicyBuffer* policy, size_t memory_size) {
291 memory_top_ = reinterpret_cast<char*>(&policy->opcodes[0]);
292 memory_bottom_ = &memory_top_[memory_size];
293 }
294
295 // Returns the available memory to make opcodes.
296 size_t memory_size() const {
297 return memory_bottom_ - memory_top_;
298 }
299
300 // Creates an OpAlwaysFalse opcode.
301 PolicyOpcode* MakeOpAlwaysFalse(uint32_t options);
302
303 // Creates an OpAlwaysFalse opcode.
304 PolicyOpcode* MakeOpAlwaysTrue(uint32_t options);
305
306 // Creates an OpAction opcode.
307 // action: The action to return when Evaluate() is called.
308 PolicyOpcode* MakeOpAction(EvalResult action, uint32_t options);
309
310 // Creates an OpNumberMatch opcode.
311 // selected_param: index of the input argument. It must be a uint32_t or the
312 // evaluation result will generate a EVAL_ERROR.
313 // match: the number to compare against the selected_param.
314 PolicyOpcode* MakeOpNumberMatch(int16_t selected_param,
315 uint32_t match,
316 uint32_t options);
317
318 // Creates an OpNumberMatch opcode (void pointers are cast to numbers).
319 // selected_param: index of the input argument. It must be an void* or the
320 // evaluation result will generate a EVAL_ERROR.
321 // match: the pointer numeric value to compare against selected_param.
322 PolicyOpcode* MakeOpVoidPtrMatch(int16_t selected_param,
323 const void* match,
324 uint32_t options);
325
326 // Creates an OpNumberMatchRange opcode using the memory passed in the ctor.
327 // selected_param: index of the input argument. It must be a uint32_t or the
328 // evaluation result will generate a EVAL_ERROR.
329 // lower_bound, upper_bound: the range to compare against selected_param.
330 PolicyOpcode* MakeOpNumberMatchRange(int16_t selected_param,
331 uint32_t lower_bound,
332 uint32_t upper_bound,
333 uint32_t options);
334
335 // Creates an OpWStringMatch opcode using the raw memory passed in the ctor.
336 // selected_param: index of the input argument. It must be a wide string
337 // pointer or the evaluation result will generate a EVAL_ERROR.
338 // match_str: string to compare against selected_param.
339 // start_position: when its value is from 0 to < 0x7fff it indicates an
340 // offset from the selected_param string where to perform the comparison. If
341 // the value is SeekForward then a substring search is performed. If the
342 // value is SeekToEnd the comparison is performed against the last part of
343 // the selected_param string.
344 // Note that the range in the position (0 to 0x7fff) is dictated by the
345 // current implementation.
346 // match_opts: Indicates additional matching flags. Currently CaseInsensitive
347 // is supported.
348 PolicyOpcode* MakeOpWStringMatch(int16_t selected_param,
349 const wchar_t* match_str,
350 int start_position,
351 StringMatchOptions match_opts,
352 uint32_t options);
353
354 // Creates an OpNumberAndMatch opcode using the raw memory passed in the ctor.
355 // selected_param: index of the input argument. It must be uint32_t or the
356 // evaluation result will generate a EVAL_ERROR.
357 // match: the value to bitwise AND against selected_param.
358 PolicyOpcode* MakeOpNumberAndMatch(int16_t selected_param,
359 uint32_t match,
360 uint32_t options);
361
362 private:
363 // Constructs the common part of every opcode. selected_param is the index
364 // of the input param to use when evaluating the opcode. Pass -1 in
365 // selected_param to indicate that no input parameter is required.
366 PolicyOpcode* MakeBase(OpcodeID opcode_id,
367 uint32_t options,
368 int16_t selected_param);
369
370 // Allocates (and copies) a string (of size length) inside the buffer and
371 // returns the displacement with respect to start.
372 ptrdiff_t AllocRelative(void* start, const wchar_t* str, size_t lenght);
373
374 // Points to the lowest currently available address of the memory
375 // used to make the opcodes. This pointer increments as opcodes are made.
376 char* memory_top_;
377
378 // Points to the highest currently available address of the memory
379 // used to make the opcodes. This pointer decrements as opcode strings are
380 // allocated.
381 char* memory_bottom_;
382
383 DISALLOW_COPY_AND_ASSIGN(OpcodeFactory);
384 };
385
386 } // namespace sandbox
387
388 #endif // SANDBOX_WIN_SRC_POLICY_ENGINE_OPCODES_H_
OLDNEW
« no previous file with comments | « sandbox/win/src/policy_broker.cc ('k') | sandbox/win/src/policy_engine_opcodes.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698