OLD | NEW |
| (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/policy_engine_processor.h" | |
6 | |
7 namespace sandbox { | |
8 | |
9 void PolicyProcessor::SetInternalState(size_t index, EvalResult result) { | |
10 state_.current_index_ = index; | |
11 state_.current_result_ = result; | |
12 } | |
13 | |
14 EvalResult PolicyProcessor::GetAction() const { | |
15 return state_.current_result_; | |
16 } | |
17 | |
18 // Decides if an opcode can be skipped (not evaluated) or not. The function | |
19 // takes as inputs the opcode and the current evaluation context and returns | |
20 // true if the opcode should be skipped or not and also can set keep_skipping | |
21 // to false to signal that the current instruction should be skipped but not | |
22 // the next after the current one. | |
23 bool SkipOpcode(PolicyOpcode& opcode, MatchContext* context, | |
24 bool* keep_skipping) { | |
25 if (opcode.IsAction()) { | |
26 uint32 options = context->options; | |
27 context->Clear(); | |
28 *keep_skipping = false; | |
29 return (kPolUseOREval == options)? false : true; | |
30 } | |
31 *keep_skipping = true; | |
32 return true; | |
33 } | |
34 | |
35 PolicyResult PolicyProcessor::Evaluate(uint32 options, | |
36 ParameterSet* parameters, | |
37 size_t param_count) { | |
38 if (NULL == policy_) { | |
39 return NO_POLICY_MATCH; | |
40 } | |
41 if (0 == policy_->opcode_count) { | |
42 return NO_POLICY_MATCH; | |
43 } | |
44 if (!(kShortEval & options)) { | |
45 return POLICY_ERROR; | |
46 } | |
47 | |
48 MatchContext context; | |
49 bool evaluation = false; | |
50 bool skip_group = false; | |
51 SetInternalState(0, EVAL_FALSE); | |
52 size_t count = policy_->opcode_count; | |
53 | |
54 // Loop over all the opcodes Evaluating in sequence. Since we only support | |
55 // short circuit evaluation, we stop as soon as we find an 'action' opcode | |
56 // and the current evaluation is true. | |
57 // | |
58 // Skipping opcodes can happen when we are in AND mode (!kPolUseOREval) and | |
59 // have got EVAL_FALSE or when we are in OR mode (kPolUseOREval) and got | |
60 // EVAL_TRUE. Skipping will stop at the next action opcode or at the opcode | |
61 // after the action depending on kPolUseOREval. | |
62 | |
63 for (size_t ix = 0; ix != count; ++ix) { | |
64 PolicyOpcode& opcode = policy_->opcodes[ix]; | |
65 // Skipping block. | |
66 if (skip_group) { | |
67 if (SkipOpcode(opcode, &context, &skip_group)) { | |
68 continue; | |
69 } | |
70 } | |
71 // Evaluation block. | |
72 EvalResult result = opcode.Evaluate(parameters, param_count, &context); | |
73 switch (result) { | |
74 case EVAL_FALSE: | |
75 evaluation = false; | |
76 if (kPolUseOREval != context.options) { | |
77 skip_group = true; | |
78 } | |
79 break; | |
80 case EVAL_ERROR: | |
81 if (kStopOnErrors & options) { | |
82 return POLICY_ERROR; | |
83 } | |
84 break; | |
85 case EVAL_TRUE: | |
86 evaluation = true; | |
87 if (kPolUseOREval == context.options) { | |
88 skip_group = true; | |
89 } | |
90 break; | |
91 default: | |
92 // We have evaluated an action. | |
93 SetInternalState(ix, result); | |
94 return POLICY_MATCH; | |
95 } | |
96 } | |
97 | |
98 if (evaluation) { | |
99 // Reaching the end of the policy with a positive evaluation is probably | |
100 // an error: we did not find a final action opcode? | |
101 return POLICY_ERROR; | |
102 } | |
103 return NO_POLICY_MATCH; | |
104 } | |
105 | |
106 | |
107 } // namespace sandbox | |
OLD | NEW |