15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/policy_engine_processor.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace sandbox {
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PolicyProcessor::SetInternalState(size_t index, EvalResult result) {
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state_.current_index_ = index;
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state_.current_result_ = result;
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EvalResult PolicyProcessor::GetAction() const {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return state_.current_result_;
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Decides if an opcode can be skipped (not evaluated) or not. The function
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// takes as inputs the opcode and the current evaluation context and returns
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// true if the opcode should be skipped or not and also can set keep_skipping
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to false to signal that the current instruction should be skipped but not
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the next after the current one.
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SkipOpcode(const PolicyOpcode& opcode, MatchContext* context,
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                bool* keep_skipping) {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (opcode.IsAction()) {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32 options = context->options;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    context->Clear();
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *keep_skipping = false;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return (kPolUseOREval != options);
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *keep_skipping = true;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PolicyResult PolicyProcessor::Evaluate(uint32 options,
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       ParameterSet* parameters,
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       size_t param_count) {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NULL == policy_) {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NO_POLICY_MATCH;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (0 == policy_->opcode_count) {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NO_POLICY_MATCH;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!(kShortEval & options)) {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return POLICY_ERROR;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MatchContext context;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool evaluation = false;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool skip_group = false;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetInternalState(0, EVAL_FALSE);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t count = policy_->opcode_count;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Loop over all the opcodes Evaluating in sequence. Since we only support
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // short circuit evaluation, we stop as soon as we find an 'action' opcode
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and the current evaluation is true.
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Skipping opcodes can happen when we are in AND mode (!kPolUseOREval) and
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // have got EVAL_FALSE or when we are in OR mode (kPolUseOREval) and got
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // EVAL_TRUE. Skipping will stop at the next action opcode or at the opcode
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // after the action depending on kPolUseOREval.
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t ix = 0; ix != count; ++ix) {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PolicyOpcode& opcode = policy_->opcodes[ix];
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Skipping block.
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (skip_group) {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (SkipOpcode(opcode, &context, &skip_group)) {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Evaluation block.
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EvalResult result = opcode.Evaluate(parameters, param_count, &context);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (result) {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case EVAL_FALSE:
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        evaluation = false;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (kPolUseOREval != context.options) {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          skip_group = true;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case EVAL_ERROR:
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (kStopOnErrors & options) {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return POLICY_ERROR;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case EVAL_TRUE:
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        evaluation = true;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (kPolUseOREval == context.options) {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          skip_group = true;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // We have evaluated an action.
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SetInternalState(ix, result);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return POLICY_MATCH;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (evaluation) {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Reaching the end of the policy with a positive evaluation is probably
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // an error: we did not find a final action opcode?
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return POLICY_ERROR;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NO_POLICY_MATCH;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace sandbox
108