blob: 5bf6a464002a7c4e73472911fd503ce7b5d2d489 [file] [log] [blame]
// Copyright (c) 2006-2008 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_SRC_POLICY_LOW_LEVEL_H__
#define SANDBOX_SRC_POLICY_LOW_LEVEL_H__
#include <list>
#include "base/basictypes.h"
#include "sandbox/src/ipc_tags.h"
#include "sandbox/src/policy_engine_params.h"
#include "sandbox/src/policy_engine_opcodes.h"
// Low level policy classes.
// Built on top of the PolicyOpcode and OpcodeFatory, the low level policy
// provides a way to define rules on strings and numbers but it is unaware
// of Windows specific details or how the Interceptions must be set up.
// To use these classes you construct one or more rules and add them to the
// LowLevelPolicy object like this:
//
// PolicyRule rule1(ASK_BROKER);
// rule1.AddStringMatch(IF, 0, L"\\\\/?/?\\c:\\*Microsoft*\\*.exe", true);
// rule1.AddNumberMatch(IF_NOT, 1, CREATE_ALWAYS, EQUAL);
// rule1.AddNumberMatch(IF, 2, FILE_ATTRIBUTE_NORMAL, EQUAL);
//
// PolicyRule rule2(FAKE_SUCCESS);
// rule2.AddStringMatch(IF, 0, L"\\\\/?/?\\Pipe\\Chrome.*", false));
// rule2.AddNumberMatch(IF, 1, OPEN_EXISTING, EQUAL));
//
// LowLevelPolicy policyGen(*policy_memory);
// policyGen.AddRule(kNtCreateFileSvc, &rule1);
// policyGen.AddRule(kNtCreateFileSvc, &rule2);
// policyGen.Done();
//
// At this point (error checking omitted) the policy_memory can be copied
// to the target process where it can be evaluated.
namespace sandbox {
// TODO(cpu): Move this constant to crosscall_client.h.
const size_t kMaxServiceCount = 32;
COMPILE_ASSERT(IPC_LAST_TAG <= kMaxServiceCount, kMaxServiceCount_is_too_low);
// Defines the memory layout of the policy. This memory is filled by
// LowLevelPolicy object.
// For example:
//
// [Service 0] --points to---\
// [Service 1] --------------|-----\
// ...... | |
// [Service N] | |
// [data_size] | |
// [Policy Buffer 0] <-------/ |
// [opcodes of] |
// ....... |
// [Policy Buffer 1] <-------------/
// [opcodes]
// .......
// .......
// [Policy Buffer N]
// [opcodes]
// .......
// <possibly unused space here>
// .......
// [opcode string ]
// [opcode string ]
// .......
// [opcode string ]
struct PolicyGlobal {
PolicyBuffer* entry[kMaxServiceCount];
size_t data_size;
PolicyBuffer data[1];
};
class PolicyRule;
// Provides the means to collect rules into a policy store (memory)
class LowLevelPolicy {
public:
// policy_store: must contain allocated memory and the internal
// size fields set to correct values.
explicit LowLevelPolicy(PolicyGlobal* policy_store)
: policy_store_(policy_store) {
}
// Destroys all the policy rules.
~LowLevelPolicy();
// Adds a rule to be generated when Done() is called.
// service: The id of the service that this rule is associated with,
// for example the 'Open Thread' service or the "Create File" service.
// returns false on error.
bool AddRule(int service, PolicyRule* rule);
// Generates all the rules added with AddRule() into the memory area
// passed on the constructor. Returns false on error.
bool Done();
private:
struct RuleNode {
const PolicyRule* rule;
int service;
};
std::list<RuleNode> rules_;
PolicyGlobal* policy_store_;
DISALLOW_IMPLICIT_CONSTRUCTORS(LowLevelPolicy);
};
// There are 'if' rules and 'if not' comparisons
enum RuleType {
IF = 0,
IF_NOT = 1,
};
// Possible comparisons for numbers
enum RuleOp {
EQUAL,
AND,
RANGE // TODO(cpu): Implement this option.
};
// Provides the means to collect a set of comparisons into a single
// rule and its associated action.
class PolicyRule {
friend class LowLevelPolicy;
public:
explicit PolicyRule(EvalResult action);
PolicyRule(const PolicyRule& other);
~PolicyRule();
// Adds a string comparison to the rule.
// rule_type: possible values are IF and IF_NOT.
// parameter: the expected index of the argument for this rule. For example
// in a 'create file' service the file name argument can be at index 0.
// string: is the desired matching pattern.
// match_opts: if the pattern matching is case sensitive or not.
bool AddStringMatch(RuleType rule_type, int16 parameter,
const wchar_t* string, StringMatchOptions match_opts);
// Adds a number match comparison to the rule.
// rule_type: possible values are IF and IF_NOT.
// parameter: the expected index of the argument for this rule.
// number: the value to compare the input to.
// comparison_op: the comparison kind (equal, logical and, etc).
bool AddNumberMatch(RuleType rule_type, int16 parameter,
unsigned long number, RuleOp comparison_op);
// Returns the number of opcodes generated so far.
size_t GetOpcodeCount() const {
return buffer_->opcode_count;
}
// Called when there is no more comparisons to add. Internally it generates
// the last opcode (the action opcode). Returns false if this operation fails.
bool Done();
private:
void operator=(const PolicyRule&);
// Called in a loop from AddStringMatch to generate the required string
// match opcodes. rule_type, match_opts and parameter are the same as
// in AddStringMatch.
bool GenStringOpcode(RuleType rule_type, StringMatchOptions match_opts,
uint16 parameter, int state, bool last_call,
int* skip_count, std::wstring* fragment);
// Loop over all generated opcodes and copy them to increasing memory
// addresses from opcode_start and copy the extra data (strings usually) into
// decreasing addresses from data_start. Extra data is only present in the
// string evaluation opcodes.
bool RebindCopy(PolicyOpcode* opcode_start, size_t opcode_size,
char* data_start, size_t* data_size) const;
PolicyBuffer* buffer_;
OpcodeFactory* opcode_factory_;
EvalResult action_;
bool done_;
};
} // namespace sandbox
#endif // SANDBOX_SRC_POLICY_LOW_LEVEL_H__