| Index: sandbox/win/src/crosscall_server.cc
|
| diff --git a/sandbox/win/src/crosscall_server.cc b/sandbox/win/src/crosscall_server.cc
|
| deleted file mode 100644
|
| index 9f71f333f02d5d1a02f6c5b9724be039dbc7a32f..0000000000000000000000000000000000000000
|
| --- a/sandbox/win/src/crosscall_server.cc
|
| +++ /dev/null
|
| @@ -1,314 +0,0 @@
|
| -// Copyright (c) 2012 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/crosscall_server.h"
|
| -
|
| -#include <stddef.h>
|
| -#include <stdint.h>
|
| -
|
| -#include <string>
|
| -#include <vector>
|
| -
|
| -#include "base/logging.h"
|
| -#include "sandbox/win/src/crosscall_client.h"
|
| -#include "sandbox/win/src/crosscall_params.h"
|
| -
|
| -// This code performs the ipc message validation. Potential security flaws
|
| -// on the ipc are likelier to be found in this code than in the rest of
|
| -// the ipc code.
|
| -
|
| -namespace {
|
| -
|
| -// The buffer for a message must match the max channel size.
|
| -const size_t kMaxBufferSize = sandbox::kIPCChannelSize;
|
| -
|
| -}
|
| -
|
| -namespace sandbox {
|
| -
|
| -// Returns the actual size for the parameters in an IPC buffer. Returns
|
| -// zero if the |param_count| is zero or too big.
|
| -uint32_t GetActualBufferSize(uint32_t param_count, void* buffer_base) {
|
| - // The template types are used to calculate the maximum expected size.
|
| - typedef ActualCallParams<1, kMaxBufferSize> ActualCP1;
|
| - typedef ActualCallParams<2, kMaxBufferSize> ActualCP2;
|
| - typedef ActualCallParams<3, kMaxBufferSize> ActualCP3;
|
| - typedef ActualCallParams<4, kMaxBufferSize> ActualCP4;
|
| - typedef ActualCallParams<5, kMaxBufferSize> ActualCP5;
|
| - typedef ActualCallParams<6, kMaxBufferSize> ActualCP6;
|
| - typedef ActualCallParams<7, kMaxBufferSize> ActualCP7;
|
| - typedef ActualCallParams<8, kMaxBufferSize> ActualCP8;
|
| - typedef ActualCallParams<9, kMaxBufferSize> ActualCP9;
|
| -
|
| - // Retrieve the actual size and the maximum size of the params buffer.
|
| - switch (param_count) {
|
| - case 0:
|
| - return 0;
|
| - case 1:
|
| - return reinterpret_cast<ActualCP1*>(buffer_base)->GetSize();
|
| - case 2:
|
| - return reinterpret_cast<ActualCP2*>(buffer_base)->GetSize();
|
| - case 3:
|
| - return reinterpret_cast<ActualCP3*>(buffer_base)->GetSize();
|
| - case 4:
|
| - return reinterpret_cast<ActualCP4*>(buffer_base)->GetSize();
|
| - case 5:
|
| - return reinterpret_cast<ActualCP5*>(buffer_base)->GetSize();
|
| - case 6:
|
| - return reinterpret_cast<ActualCP6*>(buffer_base)->GetSize();
|
| - case 7:
|
| - return reinterpret_cast<ActualCP7*>(buffer_base)->GetSize();
|
| - case 8:
|
| - return reinterpret_cast<ActualCP8*>(buffer_base)->GetSize();
|
| - case 9:
|
| - return reinterpret_cast<ActualCP9*>(buffer_base)->GetSize();
|
| - default:
|
| - return 0;
|
| - }
|
| -}
|
| -
|
| -// Verifies that the declared sizes of an IPC buffer are within range.
|
| -bool IsSizeWithinRange(uint32_t buffer_size,
|
| - uint32_t min_declared_size,
|
| - uint32_t declared_size) {
|
| - if ((buffer_size < min_declared_size) ||
|
| - (sizeof(CrossCallParamsEx) > min_declared_size)) {
|
| - // Minimal computed size bigger than existing buffer or param_count
|
| - // integer overflow.
|
| - return false;
|
| - }
|
| -
|
| - if ((declared_size > buffer_size) || (declared_size < min_declared_size)) {
|
| - // Declared size is bigger than buffer or smaller than computed size
|
| - // or param_count is equal to 0 or bigger than 9.
|
| - return false;
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -CrossCallParamsEx::CrossCallParamsEx()
|
| - :CrossCallParams(0, 0) {
|
| -}
|
| -
|
| -// We override the delete operator because the object's backing memory
|
| -// is hand allocated in CreateFromBuffer. We don't override the new operator
|
| -// because the constructors are private so there is no way to mismatch
|
| -// new & delete.
|
| -void CrossCallParamsEx::operator delete(void* raw_memory) throw() {
|
| - if (NULL == raw_memory) {
|
| - // C++ standard allows 'delete 0' behavior.
|
| - return;
|
| - }
|
| - delete[] reinterpret_cast<char*>(raw_memory);
|
| -}
|
| -
|
| -// This function uses a SEH try block so cannot use C++ objects that
|
| -// have destructors or else you get Compiler Error C2712. So no DCHECKs
|
| -// inside this function.
|
| -CrossCallParamsEx* CrossCallParamsEx::CreateFromBuffer(void* buffer_base,
|
| - uint32_t buffer_size,
|
| - uint32_t* output_size) {
|
| - // IMPORTANT: Everything inside buffer_base and derived from it such
|
| - // as param_count and declared_size is untrusted.
|
| - if (NULL == buffer_base) {
|
| - return NULL;
|
| - }
|
| - if (buffer_size < sizeof(CrossCallParams)) {
|
| - return NULL;
|
| - }
|
| - if (buffer_size > kMaxBufferSize) {
|
| - return NULL;
|
| - }
|
| -
|
| - char* backing_mem = NULL;
|
| - uint32_t param_count = 0;
|
| - uint32_t declared_size;
|
| - uint32_t min_declared_size;
|
| - CrossCallParamsEx* copied_params = NULL;
|
| -
|
| - // Touching the untrusted buffer is done under a SEH try block. This
|
| - // will catch memory access violations so we don't crash.
|
| - __try {
|
| - CrossCallParams* call_params =
|
| - reinterpret_cast<CrossCallParams*>(buffer_base);
|
| -
|
| - // Check against the minimum size given the number of stated params
|
| - // if too small we bail out.
|
| - param_count = call_params->GetParamsCount();
|
| - min_declared_size = sizeof(CrossCallParams) +
|
| - ((param_count + 1) * sizeof(ParamInfo));
|
| -
|
| - // Retrieve the declared size which if it fails returns 0.
|
| - declared_size = GetActualBufferSize(param_count, buffer_base);
|
| -
|
| - if (!IsSizeWithinRange(buffer_size, min_declared_size, declared_size))
|
| - return NULL;
|
| -
|
| - // Now we copy the actual amount of the message.
|
| - *output_size = declared_size;
|
| - backing_mem = new char[declared_size];
|
| - copied_params = reinterpret_cast<CrossCallParamsEx*>(backing_mem);
|
| - memcpy(backing_mem, call_params, declared_size);
|
| -
|
| - // Avoid compiler optimizations across this point. Any value stored in
|
| - // memory should be stored for real, and values previously read from memory
|
| - // should be actually read.
|
| - _ReadWriteBarrier();
|
| -
|
| - min_declared_size = sizeof(CrossCallParams) +
|
| - ((param_count + 1) * sizeof(ParamInfo));
|
| -
|
| - // Check that the copied buffer is still valid.
|
| - if (copied_params->GetParamsCount() != param_count ||
|
| - GetActualBufferSize(param_count, backing_mem) != declared_size ||
|
| - !IsSizeWithinRange(buffer_size, min_declared_size, declared_size)) {
|
| - delete [] backing_mem;
|
| - return NULL;
|
| - }
|
| -
|
| - } __except(EXCEPTION_EXECUTE_HANDLER) {
|
| - // In case of a windows exception we know it occurred while touching the
|
| - // untrusted buffer so we bail out as is.
|
| - delete [] backing_mem;
|
| - return NULL;
|
| - }
|
| -
|
| - const char* last_byte = &backing_mem[declared_size];
|
| - const char* first_byte = &backing_mem[min_declared_size];
|
| -
|
| - // Verify here that all and each parameters make sense. This is done in the
|
| - // local copy.
|
| - for (uint32_t ix = 0; ix != param_count; ++ix) {
|
| - uint32_t size = 0;
|
| - ArgType type;
|
| - char* address = reinterpret_cast<char*>(
|
| - copied_params->GetRawParameter(ix, &size, &type));
|
| - if ((NULL == address) || // No null params.
|
| - (INVALID_TYPE >= type) || (LAST_TYPE <= type) || // Unknown type.
|
| - (address < backing_mem) || // Start cannot point before buffer.
|
| - (address < first_byte) || // Start cannot point too low.
|
| - (address > last_byte) || // Start cannot point past buffer.
|
| - ((address + size) < address) || // Invalid size.
|
| - ((address + size) > last_byte)) { // End cannot point past buffer.
|
| - // Malformed.
|
| - delete[] backing_mem;
|
| - return NULL;
|
| - }
|
| - }
|
| - // The parameter buffer looks good.
|
| - return copied_params;
|
| -}
|
| -
|
| -// Accessors to the parameters in the raw buffer.
|
| -void* CrossCallParamsEx::GetRawParameter(uint32_t index,
|
| - uint32_t* size,
|
| - ArgType* type) {
|
| - if (index >= GetParamsCount()) {
|
| - return NULL;
|
| - }
|
| - // The size is always computed from the parameter minus the next
|
| - // parameter, this works because the message has an extra parameter slot
|
| - *size = param_info_[index].size_;
|
| - *type = param_info_[index].type_;
|
| -
|
| - return param_info_[index].offset_ + reinterpret_cast<char*>(this);
|
| -}
|
| -
|
| -// Covers common case for 32 bit integers.
|
| -bool CrossCallParamsEx::GetParameter32(uint32_t index, uint32_t* param) {
|
| - uint32_t size = 0;
|
| - ArgType type;
|
| - void* start = GetRawParameter(index, &size, &type);
|
| - if ((NULL == start) || (4 != size) || (UINT32_TYPE != type)) {
|
| - return false;
|
| - }
|
| - // Copy the 4 bytes.
|
| - *(reinterpret_cast<uint32_t*>(param)) = *(reinterpret_cast<uint32_t*>(start));
|
| - return true;
|
| -}
|
| -
|
| -bool CrossCallParamsEx::GetParameterVoidPtr(uint32_t index, void** param) {
|
| - uint32_t size = 0;
|
| - ArgType type;
|
| - void* start = GetRawParameter(index, &size, &type);
|
| - if ((NULL == start) || (sizeof(void*) != size) || (VOIDPTR_TYPE != type)) {
|
| - return false;
|
| - }
|
| - *param = *(reinterpret_cast<void**>(start));
|
| - return true;
|
| -}
|
| -
|
| -// Covers the common case of reading a string. Note that the string is not
|
| -// scanned for invalid characters.
|
| -bool CrossCallParamsEx::GetParameterStr(uint32_t index,
|
| - base::string16* string) {
|
| - uint32_t size = 0;
|
| - ArgType type;
|
| - void* start = GetRawParameter(index, &size, &type);
|
| - if (WCHAR_TYPE != type) {
|
| - return false;
|
| - }
|
| -
|
| - // Check if this is an empty string.
|
| - if (size == 0) {
|
| - *string = L"";
|
| - return true;
|
| - }
|
| -
|
| - if ((NULL == start) || ((size % sizeof(wchar_t)) != 0)) {
|
| - return false;
|
| - }
|
| - string->append(reinterpret_cast<wchar_t*>(start), size/(sizeof(wchar_t)));
|
| - return true;
|
| -}
|
| -
|
| -bool CrossCallParamsEx::GetParameterPtr(uint32_t index,
|
| - uint32_t expected_size,
|
| - void** pointer) {
|
| - uint32_t size = 0;
|
| - ArgType type;
|
| - void* start = GetRawParameter(index, &size, &type);
|
| -
|
| - if ((size != expected_size) || (INOUTPTR_TYPE != type)) {
|
| - return false;
|
| - }
|
| -
|
| - if (NULL == start) {
|
| - return false;
|
| - }
|
| -
|
| - *pointer = start;
|
| - return true;
|
| -}
|
| -
|
| -void SetCallError(ResultCode error, CrossCallReturn* call_return) {
|
| - call_return->call_outcome = error;
|
| - call_return->extended_count = 0;
|
| -}
|
| -
|
| -void SetCallSuccess(CrossCallReturn* call_return) {
|
| - call_return->call_outcome = SBOX_ALL_OK;
|
| -}
|
| -
|
| -Dispatcher* Dispatcher::OnMessageReady(IPCParams* ipc,
|
| - CallbackGeneric* callback) {
|
| - DCHECK(callback);
|
| - std::vector<IPCCall>::iterator it = ipc_calls_.begin();
|
| - for (; it != ipc_calls_.end(); ++it) {
|
| - if (it->params.Matches(ipc)) {
|
| - *callback = it->callback;
|
| - return this;
|
| - }
|
| - }
|
| - return NULL;
|
| -}
|
| -
|
| -Dispatcher::Dispatcher() {
|
| -}
|
| -
|
| -Dispatcher::~Dispatcher() {
|
| -}
|
| -
|
| -} // namespace sandbox
|
|
|