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_SRC_POLICY_ENGINE_PROCESSOR_H__
6#define SANDBOX_SRC_POLICY_ENGINE_PROCESSOR_H__
7
8#include "base/basictypes.h"
9#include "sandbox/win/src/policy_engine_params.h"
10#include "sandbox/win/src/policy_engine_opcodes.h"
11
12namespace sandbox {
13
14// This header contains the core policy evaluator. In its simplest form
15// it evaluates a stream of opcodes assuming that they are laid out in
16// memory as opcode groups.
17//
18// An opcode group has N comparison opcodes plus 1 action opcode. For
19// example here we have 3 opcode groups (A, B,C):
20//
21// [comparison 1]  <-- group A start
22// [comparison 2]
23// [comparison 3]
24// [action A    ]
25// [comparison 1]  <-- group B start
26// [action B    ]
27// [comparison 1]  <-- group C start
28// [comparison 2]
29// [action C    ]
30//
31// The opcode evaluator proceeds from the top, evaluating each opcode in
32// sequence. An opcode group is evaluated until the first comparison that
33// returns false. At that point the rest of the group is skipped and evaluation
34// resumes with the first comparison of the next group. When all the comparisons
35// in a group have evaluated to true and the action is reached. The group is
36// considered a matching group.
37//
38// In the 'ShortEval' mode evaluation stops when it reaches the end or the first
39// matching group. The action opcode from this group is the resulting policy
40// action.
41//
42// In the 'RankedEval' mode evaluation stops only when it reaches the end of the
43// the opcode stream. In the process all matching groups are saved and at the
44// end the 'best' group is selected (what makes the best is TBD) and the action
45// from this group is the resulting policy action.
46//
47// As explained above, the policy evaluation of a group is a logical AND of
48// the evaluation of each opcode. However an opcode can request kPolUseOREval
49// which makes the evaluation to use logical OR. Given that each opcode can
50// request its evaluation result to be negated with kPolNegateEval you can
51// achieve the negation of the total group evaluation. This means that if you
52// need to express:
53//             if (!(c1 && c2 && c3))
54// You can do it by:
55//             if ((!c1) || (!c2) || (!c3))
56//
57
58// Possible outcomes of policy evaluation.
59enum PolicyResult {
60  NO_POLICY_MATCH,
61  POLICY_MATCH,
62  POLICY_ERROR
63};
64
65// Policy evaluation flags
66// TODO(cpu): implement the options 0 & 4.
67//
68// Stop evaluating as soon as an error is encountered.
69const uint32 kStopOnErrors = 0;
70// Ignore all non fatal opcode evaluation errors.
71const uint32 kIgnoreErrors = 1;
72// Short-circuit evaluation: Only evaluate until opcode group that
73// evaluated to true has been found.
74const uint32 kShortEval = 2;
75// Discussed briefly at the policy design meeting. It will evaluate
76// all rules and then return the 'best' rule that evaluated true.
77const uint32 kRankedEval = 4;
78
79// This class evaluates a policy-opcode stream given the memory where the
80// opcodes are and an input 'parameter set'.
81//
82// This class is designed to be callable from interception points
83// as low as the NtXXXX service level (it is not currently safe, but
84// it is designed to be made safe).
85//
86// Its usage in an interception is:
87//
88//   POLPARAMS_BEGIN(eval_params)
89//     POLPARAM(param1)
90//     POLPARAM(param2)
91//     POLPARAM(param3)
92//     POLPARAM(param4)
93//     POLPARAM(param5)
94//   POLPARAMS_END;
95//
96//   PolicyProcessor pol_evaluator(policy_memory);
97//   PolicyResult pr = pol_evaluator.Evaluate(ShortEval, eval_params,
98//                                            _countof(eval_params));
99//   if (NO_POLICY_MATCH == pr) {
100//     EvalResult policy_action =  pol_evaluator.GetAction();
101//     // apply policy here...
102//   }
103//
104// Where the POLPARAM() arguments are derived from the intercepted function
105// arguments, and represent all the 'interesting' policy inputs, and
106// policy_memory is a memory buffer containing the opcode stream that is the
107// relevant policy for this intercept.
108class PolicyProcessor {
109 public:
110  // policy_buffer contains opcodes made with OpcodeFactory. They are usually
111  // created in the broker process and evaluated in the target process.
112
113  // This constructor is just a variant of the previous constructor.
114  explicit PolicyProcessor(PolicyBuffer* policy)
115      : policy_(policy) {
116    SetInternalState(0, EVAL_FALSE);
117  }
118
119  // Evaluates a policy-opcode stream. See the comments at the top of this
120  // class for more info. Returns POLICY_MATCH if a rule set was found that
121  // matches an active policy.
122  PolicyResult Evaluate(uint32 options,
123                        ParameterSet* parameters,
124                        size_t parameter_count);
125
126  // If the result of Evaluate() was POLICY_MATCH, calling this function returns
127  // the recommended policy action.
128  EvalResult GetAction() const;
129
130 private:
131  struct {
132    size_t current_index_;
133    EvalResult current_result_;
134  } state_;
135
136  // Sets the currently matching action result.
137  void SetInternalState(size_t index, EvalResult result);
138
139  PolicyBuffer* policy_;
140  DISALLOW_COPY_AND_ASSIGN(PolicyProcessor);
141};
142
143}  // namespace sandbox
144
145#endif  // SANDBOX_SRC_POLICY_ENGINE_PROCESSOR_H__
146