diff options
author | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-26 22:41:28 +0000 |
---|---|---|
committer | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-26 22:41:28 +0000 |
commit | a814a8d55429605fe6d7045045cd25b6bf624580 (patch) | |
tree | 58fcd994d4ce41ef021f6406a6fac32d9ca2d265 /sandbox/src/crosscall_params.h | |
parent | e6c9e14e0dfec2bb156a1f7a107cda3ebee8d392 (diff) | |
download | chromium_src-a814a8d55429605fe6d7045045cd25b6bf624580.zip chromium_src-a814a8d55429605fe6d7045045cd25b6bf624580.tar.gz chromium_src-a814a8d55429605fe6d7045045cd25b6bf624580.tar.bz2 |
Add sandbox to the repository.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@13 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'sandbox/src/crosscall_params.h')
-rw-r--r-- | sandbox/src/crosscall_params.h | 302 |
1 files changed, 302 insertions, 0 deletions
diff --git a/sandbox/src/crosscall_params.h b/sandbox/src/crosscall_params.h new file mode 100644 index 0000000..d6ad2ae --- /dev/null +++ b/sandbox/src/crosscall_params.h @@ -0,0 +1,302 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef SANDBOX_SRC_CROSSCALL_PARAMS_H__ +#define SANDBOX_SRC_CROSSCALL_PARAMS_H__ + +#include <windows.h> +#include <lmaccess.h> + +#include <memory> + +#include "base/basictypes.h" +#include "sandbox/src/internal_types.h" +#include "sandbox/src/sandbox_types.h" + +namespace { + +// Increases |value| until there is no need for padding given the 2*pointer +// alignment on the platform. Returns the increased value. +// NOTE: This might not be good enough for some buffer. The OS might want the +// structure inside the buffer to be aligned also. +size_t Align(size_t value) { + size_t alignment = sizeof(ULONG_PTR) * 2; + return ((value + alignment - 1) / alignment) * alignment; +} + +} +// This header is part of CrossCall: the sandbox inter-process communication. +// This header defines the basic types used both in the client IPC and in the +// server IPC code. CrossCallParams and ActualCallParams model the input +// parameters of an IPC call and CrossCallReturn models the output params and +// the return value. +// +// An IPC call is defined by its 'tag' which is a (uint32) unique identifier +// that is used to route the IPC call to the proper server. Every tag implies +// a complete call signature including the order and type of each parameter. +// +// Like most IPC systems. CrossCall is designed to take as inputs 'simple' +// types such as integers and strings. Classes, generic arrays or pointers to +// them are not supported. +// +// Another limitation of CrossCall is that the return value and output +// parameters can only be uint32 integers. Returning complex structures or +// strings is not supported. + +namespace sandbox { + +// max number of extended return parameters. See CrossCallReturn +const size_t kExtendedReturnCount = 8; + +// Union of multiple types to be used as extended results +// in the CrossCallReturn. +union MultiType { + uint32 unsigned_int; + void* pointer; + HANDLE handle; + ULONG_PTR ulong_ptr; +}; + +// Maximum number of IPC parameters currently supported. +// To increase this value, we have to: +// - Add another Callback typedef to Dispatcher. +// - Add another case to the switch on SharedMemIPCServer::InvokeCallback. +// - Add another case to the switch in GetActualAndMaxBufferSize +const int kMaxIpcParams = 9; + +// Contains the information about a parameter in the ipc buffer. +struct ParamInfo { + ArgType type_; + ptrdiff_t offset_; + size_t size_; +}; + +// Models the return value and the return parameters of an IPC call +// currently limited to one status code and eight generic return values +// which cannot be pointers to other data. For x64 ports this structure +// might have to use other integer types. +struct CrossCallReturn { + // the IPC tag. It should match the original IPC tag. + uint32 tag; + // The result of the IPC operation itself. + ResultCode call_outcome; + // the result of the IPC call as executed in the server. The interpretation + // of this value depends on the specific service. + union { + NTSTATUS nt_status; + DWORD win32_result; + }; + // for calls that should return a windows handle. It is found here. + HANDLE handle; + // Number of extended return values. + uint32 extended_count; + // The array of extended values. + MultiType extended[kExtendedReturnCount]; +}; + +// CrossCallParams base class that models the input params all packed in a +// single compact memory blob. The representation can vary but in general a +// given child of this class is meant to represent all input parameters +// necessary to make a IPC call. +// +// This class cannot have virtual members because its assumed the IPC +// parameters start from the 'this' pointer to the end, which is defined by +// one of the subclasses +// +// Objects of this class cannot be constructed directly. Only derived +// classes have the proper knowledge to construct it. +class CrossCallParams { + public: + // Returns the tag (ipc unique id) associated with this IPC. + uint32 GetTag() const { + return tag_; + } + + // Returns the beggining of the buffer where the IPC params can be stored. + // prior to an IPC call + const void* GetBuffer() const { + return this; + } + + // Returns how many parameter this IPC call should have. + const size_t GetParamsCount() const { + return params_count_; + } + + // Returns a pointer to the CrossCallReturn structure. + CrossCallReturn* GetCallReturn() { + return &call_return; + } + + // Returns TRUE if this call contains InOut parameters. + const bool IsInOut() const { + return (1 == is_in_out_); + } + + // Tells the CrossCall object if it contains InOut parameters. + void SetIsInOut(bool value) { + if (value) + is_in_out_ = 1; + else + is_in_out_ = 0; + } + + protected: + // constructs the IPC call params. Called only from the derived classes + explicit CrossCallParams(uint32 tag, size_t params_count) + : tag_(tag), + params_count_(params_count), + is_in_out_(0) { + } + + private: + uint32 tag_; + uint32 is_in_out_; + CrossCallReturn call_return; + const size_t params_count_; + DISALLOW_EVIL_CONSTRUCTORS(CrossCallParams); +}; + +// ActualCallParams models an specific IPC call parameters with respect to the +// storage allocation that the packed parameters should need. +// NUMBER_PARAMS: the number of parameters, valid from 1 to N +// BLOCK_SIZE: the total storage that the NUMBER_PARAMS parameters can take, +// typically the block size is defined by the channel size of the underlying +// ipc mechanism. +// In practice this class is used to levergage C++ capacity to properly +// calculate sizes and displacements given the possibility of the packed params +// blob to be complex. +// +// As is, this class assumes that the layout of the blob is as follows. Assume +// that NUMBER_PARAMS = 2: +// +// [ tag 4 bytes] +// [ IsOnOut 4 bytes] +// [ call return 52 bytes] +// [ params count 4 bytes] +// [ parameter 0 type 4 bytes] +// [ parameter 0 /\ 4 bytes] ---delta to ---\ +// [ parameter 0 size 4 bytes] | +// [ parameter 1 type 4 bytes] | +// [ parameter 1 /\ 4 bytes] | +// [ parameter 1 size 4 bytes] | +// [ parameter 2 type 4 bytes] | +// [ parameter 2 /\ 4 bytes] ----------------------\ +// [ parameter 2 size 4 bytes] | | +// |-------------------------| | | +// | | <--------------/ | +// | | | +// | | <---------------------/ +// |-------------------------| +// +// Note that the actual number of params is NUMBER_PARAMS + 1 +// so that the size of each actual param can be computed from the difference +// between one parameter and the next down +template <size_t NUMBER_PARAMS, size_t BLOCK_SIZE> +class ActualCallParams : public CrossCallParams { + public: + // constructor. Pass the ipc unique tag as input + explicit ActualCallParams(uint32 tag) + : CrossCallParams(tag, NUMBER_PARAMS) { + param_info_[0].offset_ = parameters_ - reinterpret_cast<char*>(this); + } + + // Copies each paramter into the internal buffer. For each you must supply: + // index: 0 for the first param, 1 for the next an so on + bool CopyParamIn(size_t index, const void* parameter_address, size_t size, + bool is_in_out, ArgType type) { + if (index >= NUMBER_PARAMS) { + return false; + } + + if (kuint32max == size) { + // Memory error while getting the size. + return false; + } + + if (size && !parameter_address) { + return false; + } + + if (param_info_[index].offset_ > sizeof(*this)) { + // it does not fit, abort copy + return false; + } + + char* dest = reinterpret_cast<char*>(this) + param_info_[index].offset_; + + // We might be touching user memory, this has to be done from inside a try + // except. + __try { + memcpy(dest, parameter_address, size); + } + __except(EXCEPTION_EXECUTE_HANDLER) { + return false; + } + + // Set the flag to tell the broker to update the buffer once the call is + // made. + if (is_in_out) + SetIsInOut(true); + + param_info_[index + 1].offset_ = Align(param_info_[index].offset_ + + size); + param_info_[index].size_ = size; + param_info_[index].type_ = type; + return true; + } + + // Returns a pointer to a parameter in the memory section. + void* GetParamPtr(size_t index) { + return reinterpret_cast<char*>(this) + param_info_[index].offset_; + } + + // returns the total size of the buffer. Only valid once all the paramters + // have been copied in with CopyParamIn + size_t GetSize() const { + return param_info_[NUMBER_PARAMS].offset_; + } + + protected: + ActualCallParams() : CrossCallParams(0, NUMBER_PARAMS) { } + + private: + ParamInfo param_info_[NUMBER_PARAMS + 1]; + char parameters_[BLOCK_SIZE - sizeof(CrossCallParams) + - sizeof(ParamInfo) * (NUMBER_PARAMS + 1)]; + DISALLOW_EVIL_CONSTRUCTORS(ActualCallParams); +}; + +COMPILE_ASSERT(sizeof(ActualCallParams<1, 1024>) == 1024, bad_size_buffer); +COMPILE_ASSERT(sizeof(ActualCallParams<2, 1024>) == 1024, bad_size_buffer); +COMPILE_ASSERT(sizeof(ActualCallParams<3, 1024>) == 1024, bad_size_buffer); + +} // namespace sandbox + +#endif // SANDBOX_SRC_CROSSCALL_PARAMS_H__ |