123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- // 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_WIN_SRC_POLICY_ENGINE_PROCESSOR_H_
- #define SANDBOX_WIN_SRC_POLICY_ENGINE_PROCESSOR_H_
- #include <stddef.h>
- #include <stdint.h>
- #include "base/memory/raw_ptr.h"
- #include "sandbox/win/src/policy_engine_opcodes.h"
- #include "sandbox/win/src/policy_engine_params.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 kStopOnErrors & kRankedEval.
- //
- // Stop evaluating as soon as an error is encountered.
- const uint32_t kStopOnErrors = 1;
- // Ignore all non fatal opcode evaluation errors.
- const uint32_t kIgnoreErrors = 2;
- // Short-circuit evaluation: Only evaluate until opcode group that
- // evaluated to true has been found.
- const uint32_t kShortEval = 4;
- // Discussed briefly at the policy design meeting. It will evaluate
- // all rules and then return the 'best' rule that evaluated true.
- const uint32_t kRankedEval = 8;
- // 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);
- }
- PolicyProcessor(const PolicyProcessor&) = delete;
- PolicyProcessor& operator=(const PolicyProcessor&) = delete;
- // 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_t 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);
- raw_ptr<PolicyBuffer> policy_;
- };
- } // namespace sandbox
- #endif // SANDBOX_WIN_SRC_POLICY_ENGINE_PROCESSOR_H_
|