diff options
Diffstat (limited to 'sandbox/win/src/crosscall_server.cc')
-rw-r--r-- | sandbox/win/src/crosscall_server.cc | 307 |
1 files changed, 0 insertions, 307 deletions
diff --git a/sandbox/win/src/crosscall_server.cc b/sandbox/win/src/crosscall_server.cc deleted file mode 100644 index 6f8bd744f2..0000000000 --- a/sandbox/win/src/crosscall_server.cc +++ /dev/null @@ -1,307 +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 <string> -#include <vector> - -#include "sandbox/win/src/crosscall_params.h" -#include "sandbox/win/src/crosscall_client.h" -#include "base/logging.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 GetActualBufferSize(uint32 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 buffer_size, uint32 min_declared_size, - uint32 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 buffer_size, - uint32* 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 param_count = 0; - uint32 declared_size; - uint32 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 ix =0; ix != param_count; ++ix) { - uint32 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 index, uint32* 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 index, uint32* param) { - uint32 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*>(param)) = *(reinterpret_cast<uint32*>(start)); - return true; -} - -bool CrossCallParamsEx::GetParameterVoidPtr(uint32 index, void** param) { - uint32 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 index, base::string16* string) { - uint32 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 index, uint32 expected_size, - void** pointer) { - uint32 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 |