1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef SANDBOX_SRC_CROSSCALL_PARAMS_H__
6 #define SANDBOX_SRC_CROSSCALL_PARAMS_H__
13 #include "base/basictypes.h"
14 #include "sandbox/win/src/internal_types.h"
15 #include "sandbox/win/src/sandbox_types.h"
17 // Increases |value| until there is no need for padding given an int64
18 // alignment. Returns the increased value.
19 inline uint32
Align(uint32 value
) {
20 uint32 alignment
= sizeof(int64
);
21 return ((value
+ alignment
- 1) / alignment
) * alignment
;
24 // This header is part of CrossCall: the sandbox inter-process communication.
25 // This header defines the basic types used both in the client IPC and in the
26 // server IPC code. CrossCallParams and ActualCallParams model the input
27 // parameters of an IPC call and CrossCallReturn models the output params and
30 // An IPC call is defined by its 'tag' which is a (uint32) unique identifier
31 // that is used to route the IPC call to the proper server. Every tag implies
32 // a complete call signature including the order and type of each parameter.
34 // Like most IPC systems. CrossCall is designed to take as inputs 'simple'
35 // types such as integers and strings. Classes, generic arrays or pointers to
36 // them are not supported.
38 // Another limitation of CrossCall is that the return value and output
39 // parameters can only be uint32 integers. Returning complex structures or
40 // strings is not supported.
44 // max number of extended return parameters. See CrossCallReturn
45 const size_t kExtendedReturnCount
= 8;
47 // Union of multiple types to be used as extended results
48 // in the CrossCallReturn.
56 // Maximum number of IPC parameters currently supported.
57 // To increase this value, we have to:
58 // - Add another Callback typedef to Dispatcher.
59 // - Add another case to the switch on SharedMemIPCServer::InvokeCallback.
60 // - Add another case to the switch in GetActualAndMaxBufferSize
61 const int kMaxIpcParams
= 9;
63 // Contains the information about a parameter in the ipc buffer.
70 // Models the return value and the return parameters of an IPC call
71 // currently limited to one status code and eight generic return values
72 // which cannot be pointers to other data. For x64 ports this structure
73 // might have to use other integer types.
74 struct CrossCallReturn
{
75 // the IPC tag. It should match the original IPC tag.
77 // The result of the IPC operation itself.
78 ResultCode call_outcome
;
79 // the result of the IPC call as executed in the server. The interpretation
80 // of this value depends on the specific service.
85 // Number of extended return values.
86 uint32 extended_count
;
87 // for calls that should return a windows handle. It is found here.
89 // The array of extended values.
90 MultiType extended
[kExtendedReturnCount
];
93 // CrossCallParams base class that models the input params all packed in a
94 // single compact memory blob. The representation can vary but in general a
95 // given child of this class is meant to represent all input parameters
96 // necessary to make a IPC call.
98 // This class cannot have virtual members because its assumed the IPC
99 // parameters start from the 'this' pointer to the end, which is defined by
100 // one of the subclasses
102 // Objects of this class cannot be constructed directly. Only derived
103 // classes have the proper knowledge to construct it.
104 class CrossCallParams
{
106 // Returns the tag (ipc unique id) associated with this IPC.
107 uint32
GetTag() const {
111 // Returns the beggining of the buffer where the IPC params can be stored.
112 // prior to an IPC call
113 const void* GetBuffer() const {
117 // Returns how many parameter this IPC call should have.
118 const uint32
GetParamsCount() const {
119 return params_count_
;
122 // Returns a pointer to the CrossCallReturn structure.
123 CrossCallReturn
* GetCallReturn() {
127 // Returns TRUE if this call contains InOut parameters.
128 const bool IsInOut() const {
129 return (1 == is_in_out_
);
132 // Tells the CrossCall object if it contains InOut parameters.
133 void SetIsInOut(bool value
) {
141 // constructs the IPC call params. Called only from the derived classes
142 CrossCallParams(uint32 tag
, uint32 params_count
)
143 : tag_(tag
), is_in_out_(0), params_count_(params_count
) {}
148 CrossCallReturn call_return
;
149 const uint32 params_count_
;
150 DISALLOW_COPY_AND_ASSIGN(CrossCallParams
);
153 // ActualCallParams models an specific IPC call parameters with respect to the
154 // storage allocation that the packed parameters should need.
155 // NUMBER_PARAMS: the number of parameters, valid from 1 to N
156 // BLOCK_SIZE: the total storage that the NUMBER_PARAMS parameters can take,
157 // typically the block size is defined by the channel size of the underlying
159 // In practice this class is used to levergage C++ capacity to properly
160 // calculate sizes and displacements given the possibility of the packed params
161 // blob to be complex.
163 // As is, this class assumes that the layout of the blob is as follows. Assume
164 // that NUMBER_PARAMS = 2 and a 32-bit build:
167 // [ IsOnOut 4 bytes]
168 // [ call return 52 bytes]
169 // [ params count 4 bytes]
170 // [ parameter 0 type 4 bytes]
171 // [ parameter 0 offset 4 bytes] ---delta to ---\
172 // [ parameter 0 size 4 bytes] |
173 // [ parameter 1 type 4 bytes] |
174 // [ parameter 1 offset 4 bytes] ---------------|--\
175 // [ parameter 1 size 4 bytes] | |
176 // [ parameter 2 type 4 bytes] | |
177 // [ parameter 2 offset 4 bytes] ----------------------\
178 // [ parameter 2 size 4 bytes] | | |
179 // |---------------------------| | | |
180 // | value 0 (x bytes) | <--------------/ | |
181 // | value 1 (y bytes) | <-----------------/ |
183 // | end of buffer | <---------------------/
184 // |---------------------------|
186 // Note that the actual number of params is NUMBER_PARAMS + 1
187 // so that the size of each actual param can be computed from the difference
188 // between one parameter and the next down. The offset of the last param
189 // points to the end of the buffer and the type and size are undefined.
191 template <size_t NUMBER_PARAMS
, size_t BLOCK_SIZE
>
192 class ActualCallParams
: public CrossCallParams
{
194 // constructor. Pass the ipc unique tag as input
195 explicit ActualCallParams(uint32 tag
)
196 : CrossCallParams(tag
, NUMBER_PARAMS
) {
197 param_info_
[0].offset_
=
198 static_cast<uint32
>(parameters_
- reinterpret_cast<char*>(this));
201 // Testing-only constructor. Allows setting the |number_params| to a
203 ActualCallParams(uint32 tag
, uint32 number_params
)
204 : CrossCallParams(tag
, number_params
) {
205 param_info_
[0].offset_
=
206 static_cast<uint32
>(parameters_
- reinterpret_cast<char*>(this));
209 // Testing-only method. Allows setting the apparent size to a wrong value.
210 // returns the previous size.
211 uint32
OverrideSize(uint32 new_size
) {
212 uint32 previous_size
= param_info_
[NUMBER_PARAMS
].offset_
;
213 param_info_
[NUMBER_PARAMS
].offset_
= new_size
;
214 return previous_size
;
217 // Copies each paramter into the internal buffer. For each you must supply:
218 // index: 0 for the first param, 1 for the next an so on
219 bool CopyParamIn(uint32 index
, const void* parameter_address
, uint32 size
,
220 bool is_in_out
, ArgType type
) {
221 if (index
>= NUMBER_PARAMS
) {
225 if (kuint32max
== size
) {
226 // Memory error while getting the size.
230 if (size
&& !parameter_address
) {
234 if ((size
> sizeof(*this)) ||
235 (param_info_
[index
].offset_
> (sizeof(*this) - size
))) {
236 // It does not fit, abort copy.
240 char* dest
= reinterpret_cast<char*>(this) + param_info_
[index
].offset_
;
242 // We might be touching user memory, this has to be done from inside a try
245 memcpy(dest
, parameter_address
, size
);
247 __except(EXCEPTION_EXECUTE_HANDLER
) {
251 // Set the flag to tell the broker to update the buffer once the call is
256 param_info_
[index
+ 1].offset_
= Align(param_info_
[index
].offset_
+
258 param_info_
[index
].size_
= size
;
259 param_info_
[index
].type_
= type
;
263 // Returns a pointer to a parameter in the memory section.
264 void* GetParamPtr(size_t index
) {
265 return reinterpret_cast<char*>(this) + param_info_
[index
].offset_
;
268 // Returns the total size of the buffer. Only valid once all the paramters
269 // have been copied in with CopyParamIn.
270 uint32
GetSize() const {
271 return param_info_
[NUMBER_PARAMS
].offset_
;
275 ActualCallParams() : CrossCallParams(0, NUMBER_PARAMS
) { }
278 ParamInfo param_info_
[NUMBER_PARAMS
+ 1];
279 char parameters_
[BLOCK_SIZE
- sizeof(CrossCallParams
)
280 - sizeof(ParamInfo
) * (NUMBER_PARAMS
+ 1)];
281 DISALLOW_COPY_AND_ASSIGN(ActualCallParams
);
284 static_assert(sizeof(ActualCallParams
<1, 1024>) == 1024, "bad size buffer");
285 static_assert(sizeof(ActualCallParams
<2, 1024>) == 1024, "bad size buffer");
286 static_assert(sizeof(ActualCallParams
<3, 1024>) == 1024, "bad size buffer");
288 } // namespace sandbox
290 #endif // SANDBOX_SRC_CROSSCALL_PARAMS_H__