Home | History | Annotate | Download | only in src
      1 // Copyright (c) 2006-2008 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_LOW_LEVEL_H__
      6 #define SANDBOX_SRC_POLICY_LOW_LEVEL_H__
      7 
      8 #include <list>
      9 
     10 #include "base/basictypes.h"
     11 #include "sandbox/win/src/ipc_tags.h"
     12 #include "sandbox/win/src/policy_engine_params.h"
     13 #include "sandbox/win/src/policy_engine_opcodes.h"
     14 
     15 // Low level policy classes.
     16 // Built on top of the PolicyOpcode and OpcodeFatory, the low level policy
     17 // provides a way to define rules on strings and numbers but it is unaware
     18 // of Windows specific details or how the Interceptions must be set up.
     19 // To use these classes you construct one or more rules and add them to the
     20 // LowLevelPolicy object like this:
     21 //
     22 //   PolicyRule rule1(ASK_BROKER);
     23 //   rule1.AddStringMatch(IF, 0, L"\\\\/?/?\\c:\\*Microsoft*\\*.exe", true);
     24 //   rule1.AddNumberMatch(IF_NOT, 1, CREATE_ALWAYS, EQUAL);
     25 //   rule1.AddNumberMatch(IF, 2, FILE_ATTRIBUTE_NORMAL, EQUAL);
     26 //
     27 //   PolicyRule rule2(FAKE_SUCCESS);
     28 //   rule2.AddStringMatch(IF, 0, L"\\\\/?/?\\Pipe\\Chrome.*", false));
     29 //   rule2.AddNumberMatch(IF, 1, OPEN_EXISTING, EQUAL));
     30 //
     31 //   LowLevelPolicy policyGen(*policy_memory);
     32 //   policyGen.AddRule(kNtCreateFileSvc, &rule1);
     33 //   policyGen.AddRule(kNtCreateFileSvc, &rule2);
     34 //   policyGen.Done();
     35 //
     36 // At this point (error checking omitted) the policy_memory can be copied
     37 // to the target process where it can be evaluated.
     38 
     39 namespace sandbox {
     40 
     41 // TODO(cpu): Move this constant to crosscall_client.h.
     42 const size_t kMaxServiceCount = 32;
     43 COMPILE_ASSERT(IPC_LAST_TAG <= kMaxServiceCount, kMaxServiceCount_is_too_low);
     44 
     45 // Defines the memory layout of the policy. This memory is filled by
     46 // LowLevelPolicy object.
     47 // For example:
     48 //
     49 //  [Service 0] --points to---\
     50 //  [Service 1] --------------|-----\
     51 //   ......                   |     |
     52 //  [Service N]               |     |
     53 //  [data_size]               |     |
     54 //  [Policy Buffer 0] <-------/     |
     55 //  [opcodes of]                    |
     56 //  .......                         |
     57 //  [Policy Buffer 1] <-------------/
     58 //  [opcodes]
     59 //  .......
     60 //  .......
     61 //  [Policy Buffer N]
     62 //  [opcodes]
     63 //  .......
     64 //   <possibly unused space here>
     65 //  .......
     66 //  [opcode string ]
     67 //  [opcode string ]
     68 //  .......
     69 //  [opcode string ]
     70 struct PolicyGlobal {
     71   PolicyBuffer* entry[kMaxServiceCount];
     72   size_t data_size;
     73   PolicyBuffer data[1];
     74 };
     75 
     76 class PolicyRule;
     77 
     78 // Provides the means to collect rules into a policy store (memory)
     79 class LowLevelPolicy {
     80  public:
     81   // policy_store: must contain allocated memory and the internal
     82   // size fields set to correct values.
     83   explicit LowLevelPolicy(PolicyGlobal* policy_store)
     84       : policy_store_(policy_store) {
     85   }
     86 
     87   // Destroys all the policy rules.
     88   ~LowLevelPolicy();
     89 
     90   // Adds a rule to be generated when Done() is called.
     91   // service: The id of the service that this rule is associated with,
     92   // for example the 'Open Thread' service or the "Create File" service.
     93   // returns false on error.
     94   bool AddRule(int service, PolicyRule* rule);
     95 
     96   // Generates all the rules added with AddRule() into the memory area
     97   // passed on the constructor. Returns false on error.
     98   bool Done();
     99 
    100  private:
    101   struct RuleNode {
    102     const PolicyRule* rule;
    103     int service;
    104   };
    105   std::list<RuleNode> rules_;
    106   PolicyGlobal* policy_store_;
    107   DISALLOW_IMPLICIT_CONSTRUCTORS(LowLevelPolicy);
    108 };
    109 
    110 // There are 'if' rules and 'if not' comparisons
    111 enum RuleType {
    112   IF = 0,
    113   IF_NOT = 1,
    114 };
    115 
    116 // Possible comparisons for numbers
    117 enum RuleOp {
    118   EQUAL,
    119   AND,
    120   RANGE   // TODO(cpu): Implement this option.
    121 };
    122 
    123 // Provides the means to collect a set of comparisons into a single
    124 // rule and its associated action.
    125 class PolicyRule {
    126   friend class LowLevelPolicy;
    127 
    128  public:
    129   explicit PolicyRule(EvalResult action);
    130   PolicyRule(const PolicyRule& other);
    131   ~PolicyRule();
    132 
    133   // Adds a string comparison to the rule.
    134   // rule_type: possible values are IF and IF_NOT.
    135   // parameter: the expected index of the argument for this rule. For example
    136   // in a 'create file' service the file name argument can be at index 0.
    137   // string: is the desired matching pattern.
    138   // match_opts: if the pattern matching is case sensitive or not.
    139   bool AddStringMatch(RuleType rule_type, int16 parameter,
    140                       const wchar_t* string, StringMatchOptions match_opts);
    141 
    142   // Adds a number match comparison to the rule.
    143   // rule_type: possible values are IF and IF_NOT.
    144   // parameter: the expected index of the argument for this rule.
    145   // number: the value to compare the input to.
    146   // comparison_op: the comparison kind (equal, logical and, etc).
    147   bool AddNumberMatch(RuleType rule_type, int16 parameter,
    148                       unsigned long number, RuleOp comparison_op);
    149 
    150   // Returns the number of opcodes generated so far.
    151   size_t GetOpcodeCount() const {
    152     return buffer_->opcode_count;
    153   }
    154 
    155   // Called when there is no more comparisons to add. Internally it generates
    156   // the last opcode (the action opcode). Returns false if this operation fails.
    157   bool Done();
    158 
    159  private:
    160   void operator=(const PolicyRule&);
    161   // Called in a loop from AddStringMatch to generate the required string
    162   // match opcodes. rule_type, match_opts and parameter are the same as
    163   // in AddStringMatch.
    164   bool GenStringOpcode(RuleType rule_type, StringMatchOptions match_opts,
    165                        uint16 parameter, int state, bool last_call,
    166                        int* skip_count, std::wstring* fragment);
    167 
    168   // Loop over all generated opcodes and copy them to increasing memory
    169   // addresses from opcode_start and copy the extra data (strings usually) into
    170   // decreasing addresses from data_start. Extra data is only present in the
    171   // string evaluation opcodes.
    172   bool RebindCopy(PolicyOpcode* opcode_start, size_t opcode_size,
    173                   char* data_start, size_t* data_size) const;
    174   PolicyBuffer* buffer_;
    175   OpcodeFactory* opcode_factory_;
    176   EvalResult action_;
    177   bool done_;
    178 };
    179 
    180 }  // namespace sandbox
    181 
    182 #endif  // SANDBOX_SRC_POLICY_LOW_LEVEL_H__
    183