15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 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)#include <string>
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/crosscall_server.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/crosscall_params.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/crosscall_client.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This code performs the ipc message validation. Potential security flaws
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// on the ipc are likelier to be found in this code than in the rest of
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the ipc code.
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The buffer for a message must match the max channel size.
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t kMaxBufferSize = sandbox::kIPCChannelSize;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace sandbox {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the actual size for the parameters in an IPC buffer. Returns
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// zero if the |param_count| is zero or too big.
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint32 GetActualBufferSize(uint32 param_count, void* buffer_base) {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The template types are used to calculate the maximum expected size.
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef ActualCallParams<1, kMaxBufferSize> ActualCP1;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef ActualCallParams<2, kMaxBufferSize> ActualCP2;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef ActualCallParams<3, kMaxBufferSize> ActualCP3;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef ActualCallParams<4, kMaxBufferSize> ActualCP4;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef ActualCallParams<5, kMaxBufferSize> ActualCP5;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef ActualCallParams<6, kMaxBufferSize> ActualCP6;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef ActualCallParams<7, kMaxBufferSize> ActualCP7;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef ActualCallParams<8, kMaxBufferSize> ActualCP8;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef ActualCallParams<9, kMaxBufferSize> ActualCP9;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Retrieve the actual size and the maximum size of the params buffer.
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (param_count) {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 0:
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return 0;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 1:
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return reinterpret_cast<ActualCP1*>(buffer_base)->GetSize();
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 2:
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return reinterpret_cast<ActualCP2*>(buffer_base)->GetSize();
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 3:
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return reinterpret_cast<ActualCP3*>(buffer_base)->GetSize();
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 4:
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return reinterpret_cast<ActualCP4*>(buffer_base)->GetSize();
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 5:
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return reinterpret_cast<ActualCP5*>(buffer_base)->GetSize();
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 6:
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return reinterpret_cast<ActualCP6*>(buffer_base)->GetSize();
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 7:
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return reinterpret_cast<ActualCP7*>(buffer_base)->GetSize();
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 8:
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return reinterpret_cast<ActualCP8*>(buffer_base)->GetSize();
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 9:
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return reinterpret_cast<ActualCP9*>(buffer_base)->GetSize();
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return 0;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Verifies that the declared sizes of an IPC buffer are within range.
68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool IsSizeWithinRange(uint32 buffer_size, uint32 min_declared_size,
69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                       uint32 declared_size) {
70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if ((buffer_size < min_declared_size) ||
71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      (sizeof(CrossCallParamsEx) > min_declared_size)) {
72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Minimal computed size bigger than existing buffer or param_count
73eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // integer overflow.
74eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return false;
75eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if ((declared_size > buffer_size) || (declared_size < min_declared_size)) {
78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Declared size is bigger than buffer or smaller than computed size
79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // or param_count is equal to 0 or bigger than 9.
80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return false;
81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return true;
84eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
85eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CrossCallParamsEx::CrossCallParamsEx()
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  :CrossCallParams(0, 0) {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We override the delete operator because the object's backing memory
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is hand allocated in CreateFromBuffer. We don't override the new operator
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// because the constructors are private so there is no way to mismatch
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// new & delete.
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CrossCallParamsEx::operator delete(void* raw_memory) throw() {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NULL == raw_memory) {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // C++ standard allows 'delete 0' behavior.
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete[] reinterpret_cast<char*>(raw_memory);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This function uses a SEH try block so cannot use C++ objects that
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// have destructors or else you get Compiler Error C2712. So no DCHECKs
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// inside this function.
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CrossCallParamsEx* CrossCallParamsEx::CreateFromBuffer(void* buffer_base,
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                       uint32 buffer_size,
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                       uint32* output_size) {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // IMPORTANT: Everything inside buffer_base and derived from it such
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // as param_count and declared_size is untrusted.
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NULL == buffer_base) {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (buffer_size < sizeof(CrossCallParams)) {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (buffer_size > kMaxBufferSize) {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* backing_mem = NULL;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 param_count = 0;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 declared_size;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 min_declared_size;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CrossCallParamsEx* copied_params = NULL;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Touching the untrusted buffer is done under a SEH try block. This
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // will catch memory access violations so we don't crash.
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  __try {
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CrossCallParams* call_params =
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reinterpret_cast<CrossCallParams*>(buffer_base);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Check against the minimum size given the number of stated params
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // if too small we bail out.
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    param_count = call_params->GetParamsCount();
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    min_declared_size = sizeof(CrossCallParams) +
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        ((param_count + 1) * sizeof(ParamInfo));
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Retrieve the declared size which if it fails returns 0.
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    declared_size = GetActualBufferSize(param_count, buffer_base);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (!IsSizeWithinRange(buffer_size, min_declared_size, declared_size))
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Now we copy the actual amount of the message.
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *output_size = declared_size;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    backing_mem = new char[declared_size];
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    copied_params = reinterpret_cast<CrossCallParamsEx*>(backing_mem);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(backing_mem, call_params, declared_size);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Avoid compiler optimizations across this point. Any value stored in
151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // memory should be stored for real, and values previously read from memory
152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // should be actually read.
153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    _ReadWriteBarrier();
154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    min_declared_size = sizeof(CrossCallParams) +
156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                        ((param_count + 1) * sizeof(ParamInfo));
157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Check that the copied buffer is still valid.
159eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (copied_params->GetParamsCount() != param_count ||
160eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        GetActualBufferSize(param_count, backing_mem) != declared_size ||
161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        !IsSizeWithinRange(buffer_size, min_declared_size, declared_size)) {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete [] backing_mem;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } __except(EXCEPTION_EXECUTE_HANDLER) {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // In case of a windows exception we know it occurred while touching the
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // untrusted buffer so we bail out as is.
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete [] backing_mem;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* last_byte = &backing_mem[declared_size];
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* first_byte = &backing_mem[min_declared_size];
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify here that all and each parameters make sense. This is done in the
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // local copy.
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (uint32 ix =0; ix != param_count; ++ix) {
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32 size = 0;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ArgType type;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char* address = reinterpret_cast<char*>(
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        copied_params->GetRawParameter(ix, &size, &type));
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((NULL == address) ||               // No null params.
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (INVALID_TYPE >= type) || (LAST_TYPE <= type) ||  // Unknown type.
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (address < backing_mem) ||         // Start cannot point before buffer.
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (address < first_byte) ||          // Start cannot point too low.
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (address > last_byte) ||           // Start cannot point past buffer.
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ((address + size) < address) ||    // Invalid size.
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ((address + size) > last_byte)) {  // End cannot point past buffer.
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Malformed.
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete[] backing_mem;
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The parameter buffer looks good.
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return copied_params;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Accessors to the parameters in the raw buffer.
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* CrossCallParamsEx::GetRawParameter(uint32 index, uint32* size,
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         ArgType* type) {
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (index >= GetParamsCount()) {
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The size is always computed from the parameter minus the next
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // parameter, this works because the message has an extra parameter slot
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *size = param_info_[index].size_;
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *type = param_info_[index].type_;
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return param_info_[index].offset_ + reinterpret_cast<char*>(this);
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Covers common case for 32 bit integers.
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CrossCallParamsEx::GetParameter32(uint32 index, uint32* param) {
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 size = 0;
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ArgType type;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* start = GetRawParameter(index, &size, &type);
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((NULL == start) || (4 != size) || (ULONG_TYPE != type)) {
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Copy the 4 bytes.
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *(reinterpret_cast<uint32*>(param)) = *(reinterpret_cast<uint32*>(start));
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CrossCallParamsEx::GetParameterVoidPtr(uint32 index, void** param) {
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 size = 0;
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ArgType type;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* start = GetRawParameter(index, &size, &type);
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((NULL == start) || (sizeof(void*) != size) || (VOIDPTR_TYPE != type)) {
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *param = *(reinterpret_cast<void**>(start));
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Covers the common case of reading a string. Note that the string is not
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// scanned for invalid characters.
2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool CrossCallParamsEx::GetParameterStr(uint32 index, base::string16* string) {
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 size = 0;
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ArgType type;
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* start = GetRawParameter(index, &size, &type);
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (WCHAR_TYPE != type) {
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check if this is an empty string.
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (size == 0) {
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *string = L"";
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((NULL == start) || ((size % sizeof(wchar_t)) != 0)) {
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string->append(reinterpret_cast<wchar_t*>(start), size/(sizeof(wchar_t)));
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CrossCallParamsEx::GetParameterPtr(uint32 index, uint32 expected_size,
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        void** pointer) {
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 size = 0;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ArgType type;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* start = GetRawParameter(index, &size, &type);
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((size != expected_size) || (INOUTPTR_TYPE != type)) {
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NULL == start) {
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *pointer = start;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SetCallError(ResultCode error, CrossCallReturn* call_return) {
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  call_return->call_outcome = error;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  call_return->extended_count = 0;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SetCallSuccess(CrossCallReturn* call_return) {
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  call_return->call_outcome = SBOX_ALL_OK;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Dispatcher* Dispatcher::OnMessageReady(IPCParams* ipc,
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      CallbackGeneric* callback) {
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(callback);
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<IPCCall>::iterator it = ipc_calls_.begin();
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (; it != ipc_calls_.end(); ++it) {
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (it->params.Matches(ipc)) {
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *callback = it->callback;
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return this;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace sandbox
301