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_processor.h"
6
7 namespace sandbox {
8
SetInternalState(size_t index,EvalResult result)9 void PolicyProcessor::SetInternalState(size_t index, EvalResult result) {
10 state_.current_index_ = index;
11 state_.current_result_ = result;
12 }
13
GetAction() const14 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.
SkipOpcode(const PolicyOpcode & opcode,MatchContext * context,bool * keep_skipping)23 bool SkipOpcode(const 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);
30 }
31 *keep_skipping = true;
32 return true;
33 }
34
Evaluate(uint32 options,ParameterSet * parameters,size_t param_count)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
108