• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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