15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2010 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)#ifndef SANDBOX_SRC_POLICY_ENGINE_PROCESSOR_H__ 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SANDBOX_SRC_POLICY_ENGINE_PROCESSOR_H__ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/policy_engine_params.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/policy_engine_opcodes.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace sandbox { 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This header contains the core policy evaluator. In its simplest form 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// it evaluates a stream of opcodes assuming that they are laid out in 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// memory as opcode groups. 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// An opcode group has N comparison opcodes plus 1 action opcode. For 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// example here we have 3 opcode groups (A, B,C): 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// [comparison 1] <-- group A start 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// [comparison 2] 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// [comparison 3] 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// [action A ] 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// [comparison 1] <-- group B start 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// [action B ] 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// [comparison 1] <-- group C start 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// [comparison 2] 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// [action C ] 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The opcode evaluator proceeds from the top, evaluating each opcode in 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sequence. An opcode group is evaluated until the first comparison that 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// returns false. At that point the rest of the group is skipped and evaluation 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// resumes with the first comparison of the next group. When all the comparisons 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in a group have evaluated to true and the action is reached. The group is 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// considered a matching group. 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In the 'ShortEval' mode evaluation stops when it reaches the end or the first 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// matching group. The action opcode from this group is the resulting policy 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// action. 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In the 'RankedEval' mode evaluation stops only when it reaches the end of the 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the opcode stream. In the process all matching groups are saved and at the 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// end the 'best' group is selected (what makes the best is TBD) and the action 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// from this group is the resulting policy action. 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// As explained above, the policy evaluation of a group is a logical AND of 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the evaluation of each opcode. However an opcode can request kPolUseOREval 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// which makes the evaluation to use logical OR. Given that each opcode can 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// request its evaluation result to be negated with kPolNegateEval you can 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// achieve the negation of the total group evaluation. This means that if you 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// need to express: 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// if (!(c1 && c2 && c3)) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// You can do it by: 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// if ((!c1) || (!c2) || (!c3)) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Possible outcomes of policy evaluation. 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum PolicyResult { 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NO_POLICY_MATCH, 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) POLICY_MATCH, 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) POLICY_ERROR 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Policy evaluation flags 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(cpu): implement the options 0 & 4. 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Stop evaluating as soon as an error is encountered. 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const uint32 kStopOnErrors = 0; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Ignore all non fatal opcode evaluation errors. 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const uint32 kIgnoreErrors = 1; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Short-circuit evaluation: Only evaluate until opcode group that 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// evaluated to true has been found. 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const uint32 kShortEval = 2; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Discussed briefly at the policy design meeting. It will evaluate 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// all rules and then return the 'best' rule that evaluated true. 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const uint32 kRankedEval = 4; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class evaluates a policy-opcode stream given the memory where the 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// opcodes are and an input 'parameter set'. 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class is designed to be callable from interception points 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// as low as the NtXXXX service level (it is not currently safe, but 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// it is designed to be made safe). 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Its usage in an interception is: 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// POLPARAMS_BEGIN(eval_params) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// POLPARAM(param1) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// POLPARAM(param2) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// POLPARAM(param3) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// POLPARAM(param4) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// POLPARAM(param5) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// POLPARAMS_END; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// PolicyProcessor pol_evaluator(policy_memory); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// PolicyResult pr = pol_evaluator.Evaluate(ShortEval, eval_params, 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// _countof(eval_params)); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// if (NO_POLICY_MATCH == pr) { 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// EvalResult policy_action = pol_evaluator.GetAction(); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// // apply policy here... 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// } 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Where the POLPARAM() arguments are derived from the intercepted function 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// arguments, and represent all the 'interesting' policy inputs, and 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// policy_memory is a memory buffer containing the opcode stream that is the 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// relevant policy for this intercept. 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PolicyProcessor { 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // policy_buffer contains opcodes made with OpcodeFactory. They are usually 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // created in the broker process and evaluated in the target process. 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This constructor is just a variant of the previous constructor. 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit PolicyProcessor(PolicyBuffer* policy) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : policy_(policy) { 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetInternalState(0, EVAL_FALSE); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Evaluates a policy-opcode stream. See the comments at the top of this 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // class for more info. Returns POLICY_MATCH if a rule set was found that 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // matches an active policy. 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PolicyResult Evaluate(uint32 options, 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ParameterSet* parameters, 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t parameter_count); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the result of Evaluate() was POLICY_MATCH, calling this function returns 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the recommended policy action. 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EvalResult GetAction() const; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct { 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t current_index_; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EvalResult current_result_; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } state_; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sets the currently matching action result. 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void SetInternalState(size_t index, EvalResult result); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PolicyBuffer* policy_; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(PolicyProcessor); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace sandbox 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // SANDBOX_SRC_POLICY_ENGINE_PROCESSOR_H__ 146