| Index: sandbox/win/src/policy_engine_opcodes.h
|
| diff --git a/sandbox/win/src/policy_engine_opcodes.h b/sandbox/win/src/policy_engine_opcodes.h
|
| deleted file mode 100644
|
| index 11a9c813ed9d53a398f632be21c17676eb2e911e..0000000000000000000000000000000000000000
|
| --- a/sandbox/win/src/policy_engine_opcodes.h
|
| +++ /dev/null
|
| @@ -1,388 +0,0 @@
|
| -// 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_OPCODES_H_
|
| -#define SANDBOX_WIN_SRC_POLICY_ENGINE_OPCODES_H_
|
| -
|
| -#include <stddef.h>
|
| -#include <stdint.h>
|
| -
|
| -#include "base/macros.h"
|
| -#include "base/numerics/safe_conversions.h"
|
| -#include "sandbox/win/src/policy_engine_params.h"
|
| -
|
| -// The low-level policy is implemented using the concept of policy 'opcodes'.
|
| -// An opcode is a structure that contains enough information to perform one
|
| -// comparison against one single input parameter. For example, an opcode can
|
| -// encode just one of the following comparison:
|
| -//
|
| -// - Is input parameter 3 not equal to NULL?
|
| -// - Does input parameter 2 start with L"c:\\"?
|
| -// - Is input parameter 5, bit 3 is equal 1?
|
| -//
|
| -// Each opcode is in fact equivalent to a function invocation where all
|
| -// the parameters are known by the opcode except one. So say you have a
|
| -// function of this form:
|
| -// bool fn(a, b, c, d) with 4 arguments
|
| -//
|
| -// Then an opcode is:
|
| -// op(fn, b, c, d)
|
| -// Which stores the function to call and its 3 last arguments
|
| -//
|
| -// Then and opcode evaluation is:
|
| -// op.eval(a) ------------------------> fn(a,b,c,d)
|
| -// internally calls
|
| -//
|
| -// The idea is that complex policy rules can be split into streams of
|
| -// opcodes which are evaluated in sequence. The evaluation is done in
|
| -// groups of opcodes that have N comparison opcodes plus 1 action opcode:
|
| -//
|
| -// [comparison 1][comparison 2]...[comparison N][action][comparison 1]...
|
| -// ----- evaluation order----------->
|
| -//
|
| -// Each opcode group encodes one high-level policy rule. The rule applies
|
| -// only if all the conditions on the group evaluate to true. The action
|
| -// opcode contains the policy outcome for that particular rule.
|
| -//
|
| -// Note that this header contains the main building blocks of low-level policy
|
| -// but not the low level policy class.
|
| -namespace sandbox {
|
| -
|
| -// These are the possible policy outcomes. Note that some of them might
|
| -// not apply and can be removed. Also note that The following values only
|
| -// specify what to do, not how to do it and it is acceptable given specific
|
| -// cases to ignore the policy outcome.
|
| -enum EvalResult {
|
| - // Comparison opcode values:
|
| - EVAL_TRUE, // Opcode condition evaluated true.
|
| - EVAL_FALSE, // Opcode condition evaluated false.
|
| - EVAL_ERROR, // Opcode condition generated an error while evaluating.
|
| - // Action opcode values:
|
| - ASK_BROKER, // The target must generate an IPC to the broker. On the broker
|
| - // side, this means grant access to the resource.
|
| - DENY_ACCESS, // No access granted to the resource.
|
| - GIVE_READONLY, // Give readonly access to the resource.
|
| - GIVE_ALLACCESS, // Give full access to the resource.
|
| - GIVE_CACHED, // IPC is not required. Target can return a cached handle.
|
| - GIVE_FIRST, // TODO(cpu)
|
| - SIGNAL_ALARM, // Unusual activity. Generate an alarm.
|
| - FAKE_SUCCESS, // Do not call original function. Just return 'success'.
|
| - FAKE_ACCESS_DENIED, // Do not call original function. Just return 'denied'
|
| - // and do not do IPC.
|
| - TERMINATE_PROCESS, // Destroy target process. Do IPC as well.
|
| -};
|
| -
|
| -// The following are the implemented opcodes.
|
| -enum OpcodeID {
|
| - OP_ALWAYS_FALSE, // Evaluates to false (EVAL_FALSE).
|
| - OP_ALWAYS_TRUE, // Evaluates to true (EVAL_TRUE).
|
| - OP_NUMBER_MATCH, // Match a 32-bit integer as n == a.
|
| - OP_NUMBER_MATCH_RANGE, // Match a 32-bit integer as a <= n <= b.
|
| - OP_NUMBER_AND_MATCH, // Match using bitwise AND; as in: n & a != 0.
|
| - OP_WSTRING_MATCH, // Match a string for equality.
|
| - OP_ACTION // Evaluates to an action opcode.
|
| -};
|
| -
|
| -// Options that apply to every opcode. They are specified when creating
|
| -// each opcode using OpcodeFactory::MakeOpXXXXX() family of functions
|
| -// Do nothing special.
|
| -const uint32_t kPolNone = 0;
|
| -
|
| -// Convert EVAL_TRUE into EVAL_FALSE and vice-versa. This allows to express
|
| -// negated conditions such as if ( a && !b).
|
| -const uint32_t kPolNegateEval = 1;
|
| -
|
| -// Zero the MatchContext context structure. This happens after the opcode
|
| -// is evaluated.
|
| -const uint32_t kPolClearContext = 2;
|
| -
|
| -// Use OR when evaluating this set of opcodes. The policy evaluator by default
|
| -// uses AND when evaluating. Very helpful when
|
| -// used with kPolNegateEval. For example if you have a condition best expressed
|
| -// as if(! (a && b && c)), the use of this flags allows it to be expressed as
|
| -// if ((!a) || (!b) || (!c)).
|
| -const uint32_t kPolUseOREval = 4;
|
| -
|
| -// Keeps the evaluation state between opcode evaluations. This is used
|
| -// for string matching where the next opcode needs to continue matching
|
| -// from the last character position from the current opcode. The match
|
| -// context is preserved across opcode evaluation unless an opcode specifies
|
| -// as an option kPolClearContext.
|
| -struct MatchContext {
|
| - size_t position;
|
| - uint32_t options;
|
| -
|
| - MatchContext() {
|
| - Clear();
|
| - }
|
| -
|
| - void Clear() {
|
| - position = 0;
|
| - options = 0;
|
| - }
|
| -};
|
| -
|
| -// Models a policy opcode; that is a condition evaluation were all the
|
| -// arguments but one are stored in objects of this class. Use OpcodeFactory
|
| -// to create objects of this type.
|
| -// This class is just an implementation artifact and not exposed to the
|
| -// API clients or visible in the intercepted service. Internally, an
|
| -// opcode is just:
|
| -// - An integer that identifies the actual opcode.
|
| -// - An index to indicate which one is the input argument
|
| -// - An array of arguments.
|
| -// While an OO hierarchy of objects would have been a natural choice, the fact
|
| -// that 1) this code can execute before the CRT is loaded, presents serious
|
| -// problems in terms of guarantees about the actual state of the vtables and
|
| -// 2) because the opcode objects are generated in the broker process, we need to
|
| -// use plain objects. To preserve some minimal type safety templates are used
|
| -// when possible.
|
| -class PolicyOpcode {
|
| - friend class OpcodeFactory;
|
| - public:
|
| - // Evaluates the opcode. For a typical comparison opcode the return value
|
| - // is EVAL_TRUE or EVAL_FALSE. If there was an error in the evaluation the
|
| - // the return is EVAL_ERROR. If the opcode is an action opcode then the
|
| - // return can take other values such as ASK_BROKER.
|
| - // parameters: An array of all input parameters. This argument is normally
|
| - // created by the macros POLPARAMS_BEGIN() POLPARAMS_END.
|
| - // count: The number of parameters passed as first argument.
|
| - // match: The match context that is persisted across the opcode evaluation
|
| - // sequence.
|
| - EvalResult Evaluate(const ParameterSet* parameters, size_t count,
|
| - MatchContext* match);
|
| -
|
| - // Retrieves a stored argument by index. Valid index values are
|
| - // from 0 to < kArgumentCount.
|
| - template <typename T>
|
| - void GetArgument(size_t index, T* argument) const {
|
| - static_assert(sizeof(T) <= sizeof(arguments_[0]), "invalid size");
|
| - *argument = *reinterpret_cast<const T*>(&arguments_[index].mem);
|
| - }
|
| -
|
| - // Sets a stored argument by index. Valid index values are
|
| - // from 0 to < kArgumentCount.
|
| - template <typename T>
|
| - void SetArgument(size_t index, const T& argument) {
|
| - static_assert(sizeof(T) <= sizeof(arguments_[0]), "invalid size");
|
| - *reinterpret_cast<T*>(&arguments_[index].mem) = argument;
|
| - }
|
| -
|
| - // Retrieves the actual address of an string argument. When using
|
| - // GetArgument() to retrieve an index that contains a string, the returned
|
| - // value is just an offset to the actual string.
|
| - // index: the stored string index. Valid values are from 0
|
| - // to < kArgumentCount.
|
| - const wchar_t* GetRelativeString(size_t index) const {
|
| - ptrdiff_t str_delta = 0;
|
| - GetArgument(index, &str_delta);
|
| - const char* delta = reinterpret_cast<const char*>(this) + str_delta;
|
| - return reinterpret_cast<const wchar_t*>(delta);
|
| - }
|
| -
|
| - // Returns true if this opcode is an action opcode without actually
|
| - // evaluating it. Used to do a quick scan forward to the next opcode group.
|
| - bool IsAction() const {
|
| - return (OP_ACTION == opcode_id_);
|
| - };
|
| -
|
| - // Returns the opcode type.
|
| - OpcodeID GetID() const {
|
| - return opcode_id_;
|
| - }
|
| -
|
| - // Returns the stored options such as kPolNegateEval and others.
|
| - uint32_t GetOptions() const { return options_; }
|
| -
|
| - // Sets the stored options such as kPolNegateEval.
|
| - void SetOptions(uint32_t options) {
|
| - options_ = base::checked_cast<uint16_t>(options);
|
| - }
|
| -
|
| - private:
|
| -
|
| - static const size_t kArgumentCount = 4; // The number of supported argument.
|
| -
|
| - struct OpcodeArgument {
|
| - UINT_PTR mem;
|
| - };
|
| -
|
| - // Better define placement new in the class instead of relying on the
|
| - // global definition which seems to be fubared.
|
| - void* operator new(size_t, void* location) {
|
| - return location;
|
| - }
|
| -
|
| - // Helper function to evaluate the opcode. The parameters have the same
|
| - // meaning that in Evaluate().
|
| - EvalResult EvaluateHelper(const ParameterSet* parameters,
|
| - MatchContext* match);
|
| - OpcodeID opcode_id_;
|
| - int16_t parameter_;
|
| - // TODO(cpu): Making |options_| a uint32_t would avoid casting, but causes
|
| - // test failures. Somewhere code is relying on the size of this struct.
|
| - // http://crbug.com/420296
|
| - uint16_t options_;
|
| - OpcodeArgument arguments_[PolicyOpcode::kArgumentCount];
|
| -};
|
| -
|
| -enum StringMatchOptions {
|
| - CASE_SENSITIVE = 0, // Pay or Not attention to the case as defined by
|
| - CASE_INSENSITIVE = 1, // RtlCompareUnicodeString windows API.
|
| - EXACT_LENGHT = 2 // Don't do substring match. Do full string match.
|
| -};
|
| -
|
| -// Opcodes that do string comparisons take a parameter that is the starting
|
| -// position to perform the comparison so we can do substring matching. There
|
| -// are two special values:
|
| -//
|
| -// Start from the current position and compare strings advancing forward until
|
| -// a match is found if any. Similar to CRT strstr().
|
| -const int kSeekForward = -1;
|
| -// Perform a match with the end of the string. It only does a single comparison.
|
| -const int kSeekToEnd = 0xfffff;
|
| -
|
| -
|
| -// A PolicyBuffer is a variable size structure that contains all the opcodes
|
| -// that are to be created or evaluated in sequence.
|
| -struct PolicyBuffer {
|
| - size_t opcode_count;
|
| - PolicyOpcode opcodes[1];
|
| -};
|
| -
|
| -// Helper class to create any opcode sequence. This class is normally invoked
|
| -// only by the high level policy module or when you need to handcraft a special
|
| -// policy.
|
| -// The factory works by creating the opcodes using a chunk of memory given
|
| -// in the constructor. The opcodes themselves are allocated from the beginning
|
| -// (top) of the memory, while any string that an opcode needs is allocated from
|
| -// the end (bottom) of the memory.
|
| -//
|
| -// In essence:
|
| -//
|
| -// low address ---> [opcode 1]
|
| -// [opcode 2]
|
| -// [opcode 3]
|
| -// | | <--- memory_top_
|
| -// | free |
|
| -// | |
|
| -// | | <--- memory_bottom_
|
| -// [string 1]
|
| -// high address --> [string 2]
|
| -//
|
| -// Note that this class does not keep track of the number of opcodes made and
|
| -// it is designed to be a building block for low-level policy.
|
| -//
|
| -// Note that any of the MakeOpXXXXX member functions below can return NULL on
|
| -// failure. When that happens opcode sequence creation must be aborted.
|
| -class OpcodeFactory {
|
| - public:
|
| - // memory: base pointer to a chunk of memory where the opcodes are created.
|
| - // memory_size: the size in bytes of the memory chunk.
|
| - OpcodeFactory(char* memory, size_t memory_size)
|
| - : memory_top_(memory) {
|
| - memory_bottom_ = &memory_top_[memory_size];
|
| - }
|
| -
|
| - // policy: contains the raw memory where the opcodes are created.
|
| - // memory_size: contains the actual size of the policy argument.
|
| - OpcodeFactory(PolicyBuffer* policy, size_t memory_size) {
|
| - memory_top_ = reinterpret_cast<char*>(&policy->opcodes[0]);
|
| - memory_bottom_ = &memory_top_[memory_size];
|
| - }
|
| -
|
| - // Returns the available memory to make opcodes.
|
| - size_t memory_size() const {
|
| - return memory_bottom_ - memory_top_;
|
| - }
|
| -
|
| - // Creates an OpAlwaysFalse opcode.
|
| - PolicyOpcode* MakeOpAlwaysFalse(uint32_t options);
|
| -
|
| - // Creates an OpAlwaysFalse opcode.
|
| - PolicyOpcode* MakeOpAlwaysTrue(uint32_t options);
|
| -
|
| - // Creates an OpAction opcode.
|
| - // action: The action to return when Evaluate() is called.
|
| - PolicyOpcode* MakeOpAction(EvalResult action, uint32_t options);
|
| -
|
| - // Creates an OpNumberMatch opcode.
|
| - // selected_param: index of the input argument. It must be a uint32_t or the
|
| - // evaluation result will generate a EVAL_ERROR.
|
| - // match: the number to compare against the selected_param.
|
| - PolicyOpcode* MakeOpNumberMatch(int16_t selected_param,
|
| - uint32_t match,
|
| - uint32_t options);
|
| -
|
| - // Creates an OpNumberMatch opcode (void pointers are cast to numbers).
|
| - // selected_param: index of the input argument. It must be an void* or the
|
| - // evaluation result will generate a EVAL_ERROR.
|
| - // match: the pointer numeric value to compare against selected_param.
|
| - PolicyOpcode* MakeOpVoidPtrMatch(int16_t selected_param,
|
| - const void* match,
|
| - uint32_t options);
|
| -
|
| - // Creates an OpNumberMatchRange opcode using the memory passed in the ctor.
|
| - // selected_param: index of the input argument. It must be a uint32_t or the
|
| - // evaluation result will generate a EVAL_ERROR.
|
| - // lower_bound, upper_bound: the range to compare against selected_param.
|
| - PolicyOpcode* MakeOpNumberMatchRange(int16_t selected_param,
|
| - uint32_t lower_bound,
|
| - uint32_t upper_bound,
|
| - uint32_t options);
|
| -
|
| - // Creates an OpWStringMatch opcode using the raw memory passed in the ctor.
|
| - // selected_param: index of the input argument. It must be a wide string
|
| - // pointer or the evaluation result will generate a EVAL_ERROR.
|
| - // match_str: string to compare against selected_param.
|
| - // start_position: when its value is from 0 to < 0x7fff it indicates an
|
| - // offset from the selected_param string where to perform the comparison. If
|
| - // the value is SeekForward then a substring search is performed. If the
|
| - // value is SeekToEnd the comparison is performed against the last part of
|
| - // the selected_param string.
|
| - // Note that the range in the position (0 to 0x7fff) is dictated by the
|
| - // current implementation.
|
| - // match_opts: Indicates additional matching flags. Currently CaseInsensitive
|
| - // is supported.
|
| - PolicyOpcode* MakeOpWStringMatch(int16_t selected_param,
|
| - const wchar_t* match_str,
|
| - int start_position,
|
| - StringMatchOptions match_opts,
|
| - uint32_t options);
|
| -
|
| - // Creates an OpNumberAndMatch opcode using the raw memory passed in the ctor.
|
| - // selected_param: index of the input argument. It must be uint32_t or the
|
| - // evaluation result will generate a EVAL_ERROR.
|
| - // match: the value to bitwise AND against selected_param.
|
| - PolicyOpcode* MakeOpNumberAndMatch(int16_t selected_param,
|
| - uint32_t match,
|
| - uint32_t options);
|
| -
|
| - private:
|
| - // Constructs the common part of every opcode. selected_param is the index
|
| - // of the input param to use when evaluating the opcode. Pass -1 in
|
| - // selected_param to indicate that no input parameter is required.
|
| - PolicyOpcode* MakeBase(OpcodeID opcode_id,
|
| - uint32_t options,
|
| - int16_t selected_param);
|
| -
|
| - // Allocates (and copies) a string (of size length) inside the buffer and
|
| - // returns the displacement with respect to start.
|
| - ptrdiff_t AllocRelative(void* start, const wchar_t* str, size_t lenght);
|
| -
|
| - // Points to the lowest currently available address of the memory
|
| - // used to make the opcodes. This pointer increments as opcodes are made.
|
| - char* memory_top_;
|
| -
|
| - // Points to the highest currently available address of the memory
|
| - // used to make the opcodes. This pointer decrements as opcode strings are
|
| - // allocated.
|
| - char* memory_bottom_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(OpcodeFactory);
|
| -};
|
| -
|
| -} // namespace sandbox
|
| -
|
| -#endif // SANDBOX_WIN_SRC_POLICY_ENGINE_OPCODES_H_
|
|
|