summaryrefslogtreecommitdiffstats
path: root/sandbox/src/policy_engine_processor.cc
blob: ffc51ec25969761f4bcc804bb78808a3bd024322 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//    * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//    * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//    * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "sandbox/src/policy_engine_processor.h"

namespace sandbox {

void PolicyProcessor::SetInternalState(size_t index, EvalResult result) {
  state_.current_index_ = index;
  state_.current_result_ = result;
}

EvalResult PolicyProcessor::GetAction() const {
  return state_.current_result_;
}

// Decides if an opcode can be skipped (not evaluated) or not. The function
// takes as inputs the opcode and the current evaluation context and returns
// true if the opcode should be skipped or not and also can set keep_skipping
// to false to signal that the current instruction should be skipped but not
// the next after the current one.
bool SkipOpcode(PolicyOpcode& opcode, MatchContext* context,
                bool* keep_skipping) {
  if (opcode.IsAction()) {
    uint32 options = context->options;
    context->Clear();
    *keep_skipping = false;
    return (kPolUseOREval == options)? false : true;
  }
  *keep_skipping = true;
  return true;
}

PolicyResult PolicyProcessor::Evaluate(uint32 options,
                                       ParameterSet* parameters,
                                       size_t param_count) {
  if (NULL == policy_) {
    return NO_POLICY_MATCH;
  }
  if (0 == policy_->opcode_count) {
    return NO_POLICY_MATCH;
  }
  if (!(kShortEval & options)) {
    return POLICY_ERROR;
  }

  MatchContext context;
  bool evaluation = false;
  bool skip_group = false;
  SetInternalState(0, EVAL_FALSE);
  size_t count = policy_->opcode_count;

  // Loop over all the opcodes Evaluating in sequence. Since we only support
  // short circuit evaluation, we stop as soon as we find an 'action' opcode
  // and the current evaluation is true.
  //
  // Skipping opcodes can happen when we are in AND mode (!kPolUseOREval) and
  // have got EVAL_FALSE or when we are in OR mode (kPolUseOREval) and got
  // EVAL_TRUE. Skipping will stop at the next action opcode or at the opcode
  // after the action depending on kPolUseOREval.

  for (size_t ix = 0; ix != count; ++ix) {
    PolicyOpcode& opcode = policy_->opcodes[ix];
    // Skipping block.
    if (skip_group) {
      if (SkipOpcode(opcode, &context, &skip_group)) {
        continue;
      }
    }
    // Evaluation block.
    EvalResult result = opcode.Evaluate(parameters, param_count, &context);
    switch (result) {
      case EVAL_FALSE:
        evaluation = false;
        if (kPolUseOREval != context.options) {
          skip_group = true;
        }
        break;
      case EVAL_ERROR:
        if (kStopOnErrors & options) {
          return POLICY_ERROR;
        }
        break;
      case EVAL_TRUE:
        evaluation = true;
        if (kPolUseOREval == context.options) {
          skip_group = true;
        }
        break;
      default:
        // We have evaluated an action.
        SetInternalState(ix, result);
        return POLICY_MATCH;
    }
  }

  if (evaluation) {
    // Reaching the end of the policy with a positive evaluation is probably
    // an error: we did not find a final action opcode?
    return POLICY_ERROR;
  }
  return NO_POLICY_MATCH;
}


}  // namespace sandbox