Home | History | Annotate | Download | only in src
      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__
    146