Index: sandbox/win/src/policy_low_level.cc |
diff --git a/sandbox/win/src/policy_low_level.cc b/sandbox/win/src/policy_low_level.cc |
deleted file mode 100644 |
index 526b23d6b0136340e973d677964fef07d0604554..0000000000000000000000000000000000000000 |
--- a/sandbox/win/src/policy_low_level.cc |
+++ /dev/null |
@@ -1,360 +0,0 @@ |
-// 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. |
- |
-#include "sandbox/win/src/policy_low_level.h" |
- |
-#include <stddef.h> |
-#include <stdint.h> |
- |
-#include <map> |
-#include <string> |
- |
-namespace { |
- |
- // A single rule can use at most this amount of memory. |
- const size_t kRuleBufferSize = 1024*4; |
- |
- // The possible states of the string matching opcode generator. |
- enum { |
- PENDING_NONE, |
- PENDING_ASTERISK, // Have seen an '*' but have not generated an opcode. |
- PENDING_QMARK, // Have seen an '?' but have not generated an opcode. |
- }; |
- |
- // The category of the last character seen by the string matching opcode |
- // generator. |
- const uint32_t kLastCharIsNone = 0; |
- const uint32_t kLastCharIsAlpha = 1; |
- const uint32_t kLastCharIsWild = 2; |
- const uint32_t kLastCharIsAsterisk = kLastCharIsWild + 4; |
- const uint32_t kLastCharIsQuestionM = kLastCharIsWild + 8; |
-} |
- |
-namespace sandbox { |
- |
-LowLevelPolicy::LowLevelPolicy(PolicyGlobal* policy_store) |
- : policy_store_(policy_store) { |
-} |
- |
-// Adding a rule is nothing more than pushing it into an stl container. Done() |
-// is called for the rule in case the code that made the rule in the first |
-// place has not done it. |
-bool LowLevelPolicy::AddRule(int service, PolicyRule* rule) { |
- if (!rule->Done()) { |
- return false; |
- } |
- |
- PolicyRule* local_rule = new PolicyRule(*rule); |
- RuleNode node = {local_rule, service}; |
- rules_.push_back(node); |
- return true; |
-} |
- |
-LowLevelPolicy::~LowLevelPolicy() { |
- // Delete all the rules. |
- typedef std::list<RuleNode> RuleNodes; |
- for (RuleNodes::iterator it = rules_.begin(); it != rules_.end(); ++it) { |
- delete it->rule; |
- } |
-} |
- |
-// Here is where the heavy byte shuffling is done. We take all the rules and |
-// 'compile' them into a single memory region. Now, the rules are in random |
-// order so the first step is to reorganize them into a stl map that is keyed |
-// by the service id and as a value contains a list with all the rules that |
-// belong to that service. Then we enter the big for-loop where we carve a |
-// memory zone for the opcodes and the data and call RebindCopy on each rule |
-// so they all end up nicely packed in the policy_store_. |
-bool LowLevelPolicy::Done() { |
- typedef std::list<RuleNode> RuleNodes; |
- typedef std::list<const PolicyRule*> RuleList; |
- typedef std::map<uint32_t, RuleList> Mmap; |
- Mmap mmap; |
- |
- for (RuleNodes::iterator it = rules_.begin(); it != rules_.end(); ++it) { |
- mmap[it->service].push_back(it->rule); |
- } |
- |
- PolicyBuffer* current_buffer = &policy_store_->data[0]; |
- char* buffer_end = reinterpret_cast<char*>(current_buffer) + |
- policy_store_->data_size; |
- size_t avail_size = policy_store_->data_size; |
- |
- for (Mmap::iterator it = mmap.begin(); it != mmap.end(); ++it) { |
- uint32_t service = (*it).first; |
- if (service >= kMaxServiceCount) { |
- return false; |
- } |
- policy_store_->entry[service] = current_buffer; |
- |
- RuleList::iterator rules_it = (*it).second.begin(); |
- RuleList::iterator rules_it_end = (*it).second.end(); |
- |
- size_t svc_opcode_count = 0; |
- |
- for (; rules_it != rules_it_end; ++rules_it) { |
- const PolicyRule* rule = (*rules_it); |
- size_t op_count = rule->GetOpcodeCount(); |
- |
- size_t opcodes_size = op_count * sizeof(PolicyOpcode); |
- if (avail_size < opcodes_size) { |
- return false; |
- } |
- size_t data_size = avail_size - opcodes_size; |
- PolicyOpcode* opcodes_start = ¤t_buffer->opcodes[svc_opcode_count]; |
- if (!rule->RebindCopy(opcodes_start, opcodes_size, |
- buffer_end, &data_size)) { |
- return false; |
- } |
- size_t used = avail_size - data_size; |
- buffer_end -= used; |
- avail_size -= used; |
- svc_opcode_count += op_count; |
- } |
- |
- current_buffer->opcode_count += svc_opcode_count; |
- size_t policy_byte_count = (svc_opcode_count * sizeof(PolicyOpcode)) |
- / sizeof(current_buffer[0]); |
- current_buffer = ¤t_buffer[policy_byte_count + 1]; |
- } |
- |
- return true; |
-} |
- |
-PolicyRule::PolicyRule(EvalResult action) |
- : action_(action), done_(false) { |
- char* memory = new char[sizeof(PolicyBuffer) + kRuleBufferSize]; |
- buffer_ = reinterpret_cast<PolicyBuffer*>(memory); |
- buffer_->opcode_count = 0; |
- opcode_factory_ = new OpcodeFactory(buffer_, |
- kRuleBufferSize + sizeof(PolicyOpcode)); |
-} |
- |
-PolicyRule::PolicyRule(const PolicyRule& other) { |
- if (this == &other) |
- return; |
- action_ = other.action_; |
- done_ = other.done_; |
- size_t buffer_size = sizeof(PolicyBuffer) + kRuleBufferSize; |
- char* memory = new char[buffer_size]; |
- buffer_ = reinterpret_cast<PolicyBuffer*>(memory); |
- memcpy(buffer_, other.buffer_, buffer_size); |
- |
- char* opcode_buffer = reinterpret_cast<char*>(&buffer_->opcodes[0]); |
- char* next_opcode = &opcode_buffer[GetOpcodeCount() * sizeof(PolicyOpcode)]; |
- opcode_factory_ = |
- new OpcodeFactory(next_opcode, other.opcode_factory_->memory_size()); |
-} |
- |
-// This function get called from a simple state machine implemented in |
-// AddStringMatch() which passes the current state (in state) and it passes |
-// true in last_call if AddStringMatch() has finished processing the input |
-// pattern string and this would be the last call to generate any pending |
-// opcode. The skip_count is the currently accumulated number of '?' seen so |
-// far and once the associated opcode is generated this function sets it back |
-// to zero. |
-bool PolicyRule::GenStringOpcode(RuleType rule_type, |
- StringMatchOptions match_opts, |
- uint16_t parameter, |
- int state, |
- bool last_call, |
- int* skip_count, |
- base::string16* fragment) { |
- // The last opcode must: |
- // 1) Always clear the context. |
- // 2) Preserve the negation. |
- // 3) Remove the 'OR' mode flag. |
- uint32_t options = kPolNone; |
- if (last_call) { |
- if (IF_NOT == rule_type) { |
- options = kPolClearContext | kPolNegateEval; |
- } else { |
- options = kPolClearContext; |
- } |
- } else if (IF_NOT == rule_type) { |
- options = kPolUseOREval | kPolNegateEval; |
- } |
- |
- PolicyOpcode* op = NULL; |
- |
- // The fragment string contains the accumulated characters to match with, it |
- // never contains wildcards (unless they have been escaped) and while there |
- // is no fragment there is no new string match opcode to generate. |
- if (fragment->empty()) { |
- // There is no new opcode to generate but in the last call we have to fix |
- // the previous opcode because it was really the last but we did not know |
- // it at that time. |
- if (last_call && (buffer_->opcode_count > 0)) { |
- op = &buffer_->opcodes[buffer_->opcode_count - 1]; |
- op->SetOptions(options); |
- } |
- return true; |
- } |
- |
- if (PENDING_ASTERISK == state) { |
- if (last_call) { |
- op = opcode_factory_->MakeOpWStringMatch(parameter, fragment->c_str(), |
- kSeekToEnd, match_opts, |
- options); |
- } else { |
- op = opcode_factory_->MakeOpWStringMatch(parameter, fragment->c_str(), |
- kSeekForward, match_opts, |
- options); |
- } |
- |
- } else if (PENDING_QMARK == state) { |
- op = opcode_factory_->MakeOpWStringMatch(parameter, fragment->c_str(), |
- *skip_count, match_opts, options); |
- *skip_count = 0; |
- } else { |
- if (last_call) { |
- match_opts = static_cast<StringMatchOptions>(EXACT_LENGHT | match_opts); |
- } |
- op = opcode_factory_->MakeOpWStringMatch(parameter, fragment->c_str(), 0, |
- match_opts, options); |
- } |
- if (NULL == op) { |
- return false; |
- } |
- ++buffer_->opcode_count; |
- fragment->clear(); |
- return true; |
-} |
- |
-bool PolicyRule::AddStringMatch(RuleType rule_type, |
- int16_t parameter, |
- const wchar_t* string, |
- StringMatchOptions match_opts) { |
- if (done_) { |
- // Do not allow to add more rules after generating the action opcode. |
- return false; |
- } |
- |
- const wchar_t* current_char = string; |
- uint32_t last_char = kLastCharIsNone; |
- int state = PENDING_NONE; |
- int skip_count = 0; // counts how many '?' we have seen in a row. |
- base::string16 fragment; // accumulates the non-wildcard part. |
- |
- while (L'\0' != *current_char) { |
- switch (*current_char) { |
- case L'*': |
- if (kLastCharIsWild & last_char) { |
- // '**' and '&*' is an error. |
- return false; |
- } |
- if (!GenStringOpcode(rule_type, match_opts, parameter, |
- state, false, &skip_count, &fragment)) { |
- return false; |
- } |
- last_char = kLastCharIsAsterisk; |
- state = PENDING_ASTERISK; |
- break; |
- case L'?': |
- if (kLastCharIsAsterisk == last_char) { |
- // '*?' is an error. |
- return false; |
- } |
- if (!GenStringOpcode(rule_type, match_opts, parameter, |
- state, false, &skip_count, &fragment)) { |
- return false; |
- } |
- ++skip_count; |
- last_char = kLastCharIsQuestionM; |
- state = PENDING_QMARK; |
- break; |
- case L'/': |
- // Note: "/?" is an escaped '?'. Eat the slash and fall through. |
- if (L'?' == current_char[1]) { |
- ++current_char; |
- } |
- default: |
- fragment += *current_char; |
- last_char = kLastCharIsAlpha; |
- } |
- ++current_char; |
- } |
- |
- if (!GenStringOpcode(rule_type, match_opts, parameter, |
- state, true, &skip_count, &fragment)) { |
- return false; |
- } |
- return true; |
-} |
- |
-bool PolicyRule::AddNumberMatch(RuleType rule_type, |
- int16_t parameter, |
- uint32_t number, |
- RuleOp comparison_op) { |
- if (done_) { |
- // Do not allow to add more rules after generating the action opcode. |
- return false; |
- } |
- uint32_t opts = (rule_type == IF_NOT) ? kPolNegateEval : kPolNone; |
- |
- if (EQUAL == comparison_op) { |
- if (NULL == opcode_factory_->MakeOpNumberMatch(parameter, number, opts)) { |
- return false; |
- } |
- } else if (AND == comparison_op) { |
- if (NULL == opcode_factory_->MakeOpNumberAndMatch(parameter, number, |
- opts)) { |
- return false; |
- } |
- } |
- ++buffer_->opcode_count; |
- return true; |
-} |
- |
-bool PolicyRule::Done() { |
- if (done_) { |
- return true; |
- } |
- if (NULL == opcode_factory_->MakeOpAction(action_, kPolNone)) { |
- return false; |
- } |
- ++buffer_->opcode_count; |
- done_ = true; |
- return true; |
-} |
- |
-bool PolicyRule::RebindCopy(PolicyOpcode* opcode_start, size_t opcode_size, |
- char* data_start, size_t* data_size) const { |
- size_t count = buffer_->opcode_count; |
- for (size_t ix = 0; ix != count; ++ix) { |
- if (opcode_size < sizeof(PolicyOpcode)) { |
- return false; |
- } |
- PolicyOpcode& opcode = buffer_->opcodes[ix]; |
- *opcode_start = opcode; |
- if (OP_WSTRING_MATCH == opcode.GetID()) { |
- // For this opcode argument 0 is a delta to the string and argument 1 |
- // is the length (in chars) of the string. |
- const wchar_t* str = opcode.GetRelativeString(0); |
- size_t str_len; |
- opcode.GetArgument(1, &str_len); |
- str_len = str_len * sizeof(wchar_t); |
- if ((*data_size) < str_len) { |
- return false; |
- } |
- *data_size -= str_len; |
- data_start -= str_len; |
- memcpy(data_start, str, str_len); |
- // Recompute the string displacement |
- ptrdiff_t delta = data_start - reinterpret_cast<char*>(opcode_start); |
- opcode_start->SetArgument(0, delta); |
- } |
- ++opcode_start; |
- opcode_size -= sizeof(PolicyOpcode); |
- } |
- |
- return true; |
-} |
- |
-PolicyRule::~PolicyRule() { |
- delete [] reinterpret_cast<char*>(buffer_); |
- delete opcode_factory_; |
-} |
- |
-} // namespace sandbox |