15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2010 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SANDBOX_SRC_POLICY_ENGINE_PROCESSOR_H__
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SANDBOX_SRC_POLICY_ENGINE_PROCESSOR_H__
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/policy_engine_params.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/policy_engine_opcodes.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace sandbox {
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This header contains the core policy evaluator. In its simplest form
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// it evaluates a stream of opcodes assuming that they are laid out in
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// memory as opcode groups.
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// An opcode group has N comparison opcodes plus 1 action opcode. For
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// example here we have 3 opcode groups (A, B,C):
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// [comparison 1]  <-- group A start
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// [comparison 2]
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// [comparison 3]
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// [action A    ]
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// [comparison 1]  <-- group B start
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// [action B    ]
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// [comparison 1]  <-- group C start
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// [comparison 2]
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// [action C    ]
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The opcode evaluator proceeds from the top, evaluating each opcode in
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sequence. An opcode group is evaluated until the first comparison that
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// returns false. At that point the rest of the group is skipped and evaluation
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// resumes with the first comparison of the next group. When all the comparisons
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in a group have evaluated to true and the action is reached. The group is
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// considered a matching group.
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In the 'ShortEval' mode evaluation stops when it reaches the end or the first
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// matching group. The action opcode from this group is the resulting policy
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// action.
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In the 'RankedEval' mode evaluation stops only when it reaches the end of the
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the opcode stream. In the process all matching groups are saved and at the
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// end the 'best' group is selected (what makes the best is TBD) and the action
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// from this group is the resulting policy action.
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// As explained above, the policy evaluation of a group is a logical AND of
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the evaluation of each opcode. However an opcode can request kPolUseOREval
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// which makes the evaluation to use logical OR. Given that each opcode can
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// request its evaluation result to be negated with kPolNegateEval you can
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// achieve the negation of the total group evaluation. This means that if you
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// need to express:
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//             if (!(c1 && c2 && c3))
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// You can do it by:
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//             if ((!c1) || (!c2) || (!c3))
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Possible outcomes of policy evaluation.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum PolicyResult {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NO_POLICY_MATCH,
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  POLICY_MATCH,
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  POLICY_ERROR
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Policy evaluation flags
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(cpu): implement the options 0 & 4.
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Stop evaluating as soon as an error is encountered.
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const uint32 kStopOnErrors = 0;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Ignore all non fatal opcode evaluation errors.
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const uint32 kIgnoreErrors = 1;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Short-circuit evaluation: Only evaluate until opcode group that
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// evaluated to true has been found.
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const uint32 kShortEval = 2;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Discussed briefly at the policy design meeting. It will evaluate
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// all rules and then return the 'best' rule that evaluated true.
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const uint32 kRankedEval = 4;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class evaluates a policy-opcode stream given the memory where the
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// opcodes are and an input 'parameter set'.
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class is designed to be callable from interception points
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// as low as the NtXXXX service level (it is not currently safe, but
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// it is designed to be made safe).
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Its usage in an interception is:
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   POLPARAMS_BEGIN(eval_params)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     POLPARAM(param1)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     POLPARAM(param2)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     POLPARAM(param3)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     POLPARAM(param4)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     POLPARAM(param5)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   POLPARAMS_END;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   PolicyProcessor pol_evaluator(policy_memory);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   PolicyResult pr = pol_evaluator.Evaluate(ShortEval, eval_params,
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                                            _countof(eval_params));
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   if (NO_POLICY_MATCH == pr) {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     EvalResult policy_action =  pol_evaluator.GetAction();
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     // apply policy here...
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   }
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Where the POLPARAM() arguments are derived from the intercepted function
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// arguments, and represent all the 'interesting' policy inputs, and
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// policy_memory is a memory buffer containing the opcode stream that is the
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// relevant policy for this intercept.
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PolicyProcessor {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // policy_buffer contains opcodes made with OpcodeFactory. They are usually
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // created in the broker process and evaluated in the target process.
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This constructor is just a variant of the previous constructor.
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit PolicyProcessor(PolicyBuffer* policy)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : policy_(policy) {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetInternalState(0, EVAL_FALSE);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Evaluates a policy-opcode stream. See the comments at the top of this
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // class for more info. Returns POLICY_MATCH if a rule set was found that
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // matches an active policy.
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PolicyResult Evaluate(uint32 options,
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        ParameterSet* parameters,
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        size_t parameter_count);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the result of Evaluate() was POLICY_MATCH, calling this function returns
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the recommended policy action.
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EvalResult GetAction() const;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct {
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t current_index_;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EvalResult current_result_;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } state_;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Sets the currently matching action result.
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetInternalState(size_t index, EvalResult result);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PolicyBuffer* policy_;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(PolicyProcessor);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace sandbox
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // SANDBOX_SRC_POLICY_ENGINE_PROCESSOR_H__
146