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