blob: 3327e36d96f204ec81d632447eb4054b5470f6d0 [file] [log] [blame]
// 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.
#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 {
// 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)
// 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 {
// 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;
struct {
size_t current_index_;
EvalResult current_result_;
} state_;
// Sets the currently matching action result.
void SetInternalState(size_t index, EvalResult result);
PolicyBuffer* policy_;
} // namespace sandbox