michael@0: // Copyright (c) 2010 The Chromium Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: michael@0: #ifndef SANDBOX_SRC_POLICY_ENGINE_PROCESSOR_H__ michael@0: #define SANDBOX_SRC_POLICY_ENGINE_PROCESSOR_H__ michael@0: michael@0: #include "base/basictypes.h" michael@0: #include "sandbox/win/src/policy_engine_params.h" michael@0: #include "sandbox/win/src/policy_engine_opcodes.h" michael@0: michael@0: namespace sandbox { michael@0: michael@0: // This header contains the core policy evaluator. In its simplest form michael@0: // it evaluates a stream of opcodes assuming that they are laid out in michael@0: // memory as opcode groups. michael@0: // michael@0: // An opcode group has N comparison opcodes plus 1 action opcode. For michael@0: // example here we have 3 opcode groups (A, B,C): michael@0: // michael@0: // [comparison 1] <-- group A start michael@0: // [comparison 2] michael@0: // [comparison 3] michael@0: // [action A ] michael@0: // [comparison 1] <-- group B start michael@0: // [action B ] michael@0: // [comparison 1] <-- group C start michael@0: // [comparison 2] michael@0: // [action C ] michael@0: // michael@0: // The opcode evaluator proceeds from the top, evaluating each opcode in michael@0: // sequence. An opcode group is evaluated until the first comparison that michael@0: // returns false. At that point the rest of the group is skipped and evaluation michael@0: // resumes with the first comparison of the next group. When all the comparisons michael@0: // in a group have evaluated to true and the action is reached. The group is michael@0: // considered a matching group. michael@0: // michael@0: // In the 'ShortEval' mode evaluation stops when it reaches the end or the first michael@0: // matching group. The action opcode from this group is the resulting policy michael@0: // action. michael@0: // michael@0: // In the 'RankedEval' mode evaluation stops only when it reaches the end of the michael@0: // the opcode stream. In the process all matching groups are saved and at the michael@0: // end the 'best' group is selected (what makes the best is TBD) and the action michael@0: // from this group is the resulting policy action. michael@0: // michael@0: // As explained above, the policy evaluation of a group is a logical AND of michael@0: // the evaluation of each opcode. However an opcode can request kPolUseOREval michael@0: // which makes the evaluation to use logical OR. Given that each opcode can michael@0: // request its evaluation result to be negated with kPolNegateEval you can michael@0: // achieve the negation of the total group evaluation. This means that if you michael@0: // need to express: michael@0: // if (!(c1 && c2 && c3)) michael@0: // You can do it by: michael@0: // if ((!c1) || (!c2) || (!c3)) michael@0: // michael@0: michael@0: // Possible outcomes of policy evaluation. michael@0: enum PolicyResult { michael@0: NO_POLICY_MATCH, michael@0: POLICY_MATCH, michael@0: POLICY_ERROR michael@0: }; michael@0: michael@0: // Policy evaluation flags michael@0: // TODO(cpu): implement the options 0 & 4. michael@0: // michael@0: // Stop evaluating as soon as an error is encountered. michael@0: const uint32 kStopOnErrors = 0; michael@0: // Ignore all non fatal opcode evaluation errors. michael@0: const uint32 kIgnoreErrors = 1; michael@0: // Short-circuit evaluation: Only evaluate until opcode group that michael@0: // evaluated to true has been found. michael@0: const uint32 kShortEval = 2; michael@0: // Discussed briefly at the policy design meeting. It will evaluate michael@0: // all rules and then return the 'best' rule that evaluated true. michael@0: const uint32 kRankedEval = 4; michael@0: michael@0: // This class evaluates a policy-opcode stream given the memory where the michael@0: // opcodes are and an input 'parameter set'. michael@0: // michael@0: // This class is designed to be callable from interception points michael@0: // as low as the NtXXXX service level (it is not currently safe, but michael@0: // it is designed to be made safe). michael@0: // michael@0: // Its usage in an interception is: michael@0: // michael@0: // POLPARAMS_BEGIN(eval_params) michael@0: // POLPARAM(param1) michael@0: // POLPARAM(param2) michael@0: // POLPARAM(param3) michael@0: // POLPARAM(param4) michael@0: // POLPARAM(param5) michael@0: // POLPARAMS_END; michael@0: // michael@0: // PolicyProcessor pol_evaluator(policy_memory); michael@0: // PolicyResult pr = pol_evaluator.Evaluate(ShortEval, eval_params, michael@0: // _countof(eval_params)); michael@0: // if (NO_POLICY_MATCH == pr) { michael@0: // EvalResult policy_action = pol_evaluator.GetAction(); michael@0: // // apply policy here... michael@0: // } michael@0: // michael@0: // Where the POLPARAM() arguments are derived from the intercepted function michael@0: // arguments, and represent all the 'interesting' policy inputs, and michael@0: // policy_memory is a memory buffer containing the opcode stream that is the michael@0: // relevant policy for this intercept. michael@0: class PolicyProcessor { michael@0: public: michael@0: // policy_buffer contains opcodes made with OpcodeFactory. They are usually michael@0: // created in the broker process and evaluated in the target process. michael@0: michael@0: // This constructor is just a variant of the previous constructor. michael@0: explicit PolicyProcessor(PolicyBuffer* policy) michael@0: : policy_(policy) { michael@0: SetInternalState(0, EVAL_FALSE); michael@0: } michael@0: michael@0: // Evaluates a policy-opcode stream. See the comments at the top of this michael@0: // class for more info. Returns POLICY_MATCH if a rule set was found that michael@0: // matches an active policy. michael@0: PolicyResult Evaluate(uint32 options, michael@0: ParameterSet* parameters, michael@0: size_t parameter_count); michael@0: michael@0: // If the result of Evaluate() was POLICY_MATCH, calling this function returns michael@0: // the recommended policy action. michael@0: EvalResult GetAction() const; michael@0: michael@0: private: michael@0: struct { michael@0: size_t current_index_; michael@0: EvalResult current_result_; michael@0: } state_; michael@0: michael@0: // Sets the currently matching action result. michael@0: void SetInternalState(size_t index, EvalResult result); michael@0: michael@0: PolicyBuffer* policy_; michael@0: DISALLOW_COPY_AND_ASSIGN(PolicyProcessor); michael@0: }; michael@0: michael@0: } // namespace sandbox michael@0: michael@0: #endif // SANDBOX_SRC_POLICY_ENGINE_PROCESSOR_H__