|
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 |
|
12 namespace 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. |
|
59 enum 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. |
|
69 const uint32 kStopOnErrors = 0; |
|
70 // Ignore all non fatal opcode evaluation errors. |
|
71 const uint32 kIgnoreErrors = 1; |
|
72 // Short-circuit evaluation: Only evaluate until opcode group that |
|
73 // evaluated to true has been found. |
|
74 const 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. |
|
77 const 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. |
|
108 class 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__ |