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 #include "sandbox/win/src/policy_engine_processor.h"
      6 
      7 namespace sandbox {
      8 
      9 void PolicyProcessor::SetInternalState(size_t index, EvalResult result) {
     10   state_.current_index_ = index;
     11   state_.current_result_ = result;
     12 }
     13 
     14 EvalResult PolicyProcessor::GetAction() const {
     15   return state_.current_result_;
     16 }
     17 
     18 // Decides if an opcode can be skipped (not evaluated) or not. The function
     19 // takes as inputs the opcode and the current evaluation context and returns
     20 // true if the opcode should be skipped or not and also can set keep_skipping
     21 // to false to signal that the current instruction should be skipped but not
     22 // the next after the current one.
     23 bool SkipOpcode(const PolicyOpcode& opcode, MatchContext* context,
     24                 bool* keep_skipping) {
     25   if (opcode.IsAction()) {
     26     uint32 options = context->options;
     27     context->Clear();
     28     *keep_skipping = false;
     29     return (kPolUseOREval != options);
     30   }
     31   *keep_skipping = true;
     32   return true;
     33 }
     34 
     35 PolicyResult PolicyProcessor::Evaluate(uint32 options,
     36                                        ParameterSet* parameters,
     37                                        size_t param_count) {
     38   if (NULL == policy_) {
     39     return NO_POLICY_MATCH;
     40   }
     41   if (0 == policy_->opcode_count) {
     42     return NO_POLICY_MATCH;
     43   }
     44   if (!(kShortEval & options)) {
     45     return POLICY_ERROR;
     46   }
     47 
     48   MatchContext context;
     49   bool evaluation = false;
     50   bool skip_group = false;
     51   SetInternalState(0, EVAL_FALSE);
     52   size_t count = policy_->opcode_count;
     53 
     54   // Loop over all the opcodes Evaluating in sequence. Since we only support
     55   // short circuit evaluation, we stop as soon as we find an 'action' opcode
     56   // and the current evaluation is true.
     57   //
     58   // Skipping opcodes can happen when we are in AND mode (!kPolUseOREval) and
     59   // have got EVAL_FALSE or when we are in OR mode (kPolUseOREval) and got
     60   // EVAL_TRUE. Skipping will stop at the next action opcode or at the opcode
     61   // after the action depending on kPolUseOREval.
     62 
     63   for (size_t ix = 0; ix != count; ++ix) {
     64     PolicyOpcode& opcode = policy_->opcodes[ix];
     65     // Skipping block.
     66     if (skip_group) {
     67       if (SkipOpcode(opcode, &context, &skip_group)) {
     68         continue;
     69       }
     70     }
     71     // Evaluation block.
     72     EvalResult result = opcode.Evaluate(parameters, param_count, &context);
     73     switch (result) {
     74       case EVAL_FALSE:
     75         evaluation = false;
     76         if (kPolUseOREval != context.options) {
     77           skip_group = true;
     78         }
     79         break;
     80       case EVAL_ERROR:
     81         if (kStopOnErrors & options) {
     82           return POLICY_ERROR;
     83         }
     84         break;
     85       case EVAL_TRUE:
     86         evaluation = true;
     87         if (kPolUseOREval == context.options) {
     88           skip_group = true;
     89         }
     90         break;
     91       default:
     92         // We have evaluated an action.
     93         SetInternalState(ix, result);
     94         return POLICY_MATCH;
     95     }
     96   }
     97 
     98   if (evaluation) {
     99     // Reaching the end of the policy with a positive evaluation is probably
    100     // an error: we did not find a final action opcode?
    101     return POLICY_ERROR;
    102   }
    103   return NO_POLICY_MATCH;
    104 }
    105 
    106 
    107 }  // namespace sandbox
    108