OLD | NEW |
1 // Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <string> | 5 #include <string> |
6 #include <vector> | 6 #include <vector> |
7 | 7 |
8 #include "sandbox/src/crosscall_server.h" | 8 #include "sandbox/src/crosscall_server.h" |
9 #include "sandbox/src/crosscall_params.h" | 9 #include "sandbox/src/crosscall_params.h" |
10 #include "sandbox/src/crosscall_client.h" | 10 #include "sandbox/src/crosscall_client.h" |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
78 } | 78 } |
79 delete[] reinterpret_cast<char*>(raw_memory); | 79 delete[] reinterpret_cast<char*>(raw_memory); |
80 } | 80 } |
81 | 81 |
82 // This function uses a SEH try block so cannot use C++ objects that | 82 // This function uses a SEH try block so cannot use C++ objects that |
83 // have destructors or else you get Compiler Error C2712. So no DCHECKs | 83 // have destructors or else you get Compiler Error C2712. So no DCHECKs |
84 // inside this function. | 84 // inside this function. |
85 CrossCallParamsEx* CrossCallParamsEx::CreateFromBuffer(void* buffer_base, | 85 CrossCallParamsEx* CrossCallParamsEx::CreateFromBuffer(void* buffer_base, |
86 size_t buffer_size, | 86 size_t buffer_size, |
87 size_t* output_size) { | 87 size_t* output_size) { |
| 88 // IMPORTANT: Everything inside buffer_base and derived from it such |
| 89 // as param_count and declared_size is untrusted. |
88 if (NULL == buffer_base) { | 90 if (NULL == buffer_base) { |
89 return NULL; | 91 return NULL; |
90 } | 92 } |
91 if (buffer_size < sizeof(CrossCallParams)) { | 93 if (buffer_size < sizeof(CrossCallParams)) { |
92 return NULL; | 94 return NULL; |
93 } | 95 } |
94 if (buffer_size > kMaxBufferSize) { | 96 if (buffer_size > kMaxBufferSize) { |
95 return NULL; | 97 return NULL; |
96 } | 98 } |
| 99 |
97 char* backing_mem = NULL; | 100 char* backing_mem = NULL; |
98 size_t param_count = 0; | 101 size_t param_count = 0; |
| 102 size_t declared_size; |
| 103 size_t min_declared_size; |
99 CrossCallParamsEx* copied_params = NULL; | 104 CrossCallParamsEx* copied_params = NULL; |
100 size_t actual_size; | |
101 | 105 |
102 // Touching the untrusted buffer is done under a SEH try block. This | 106 // Touching the untrusted buffer is done under a SEH try block. This |
103 // will catch memory access violations so we don't crash. | 107 // will catch memory access violations so we don't crash. |
104 __try { | 108 __try { |
105 CrossCallParams* call_params = | 109 CrossCallParams* call_params = |
106 reinterpret_cast<CrossCallParams*>(buffer_base); | 110 reinterpret_cast<CrossCallParams*>(buffer_base); |
107 // Check against the minimum size given the number of stated params | 111 // Check against the minimum size given the number of stated params |
108 // if too small we bail out. | 112 // if too small we bail out. |
109 param_count = call_params->GetParamsCount(); | 113 param_count = call_params->GetParamsCount(); |
110 if ((buffer_size - sizeof(CrossCallParams)) < | 114 |
111 (sizeof(ptrdiff_t) * (param_count + 1))) { | 115 min_declared_size = |
112 // This test is subject to integer overflow but the next is not. | 116 sizeof(CrossCallParamsEx) + (param_count * sizeof(ParamInfo)); |
| 117 |
| 118 if ((buffer_size < min_declared_size) || |
| 119 (sizeof(CrossCallParamsEx) > min_declared_size)) { |
| 120 // Minimal computed size bigger than existing buffer or param_count |
| 121 // integer overflow. |
113 return NULL; | 122 return NULL; |
114 } | 123 } |
115 | 124 |
116 actual_size = GetActualBufferSize(param_count, buffer_base); | 125 // Retrieve the declared size which if it fails returns 0. |
117 if ((actual_size > buffer_size) || (0 == actual_size)) { | 126 declared_size = GetActualBufferSize(param_count, buffer_base); |
118 // It is too big or too many declared parameters. | 127 |
| 128 if ((declared_size > buffer_size) || |
| 129 (declared_size < min_declared_size)) { |
| 130 // Declared size is bigger than buffer or smaller than computed size |
| 131 // or param_count 0 or bigger than 9. |
119 return NULL; | 132 return NULL; |
120 } | 133 } |
121 | 134 |
122 // Now we copy the actual amount of the message. | 135 // Now we copy the actual amount of the message. |
123 actual_size += sizeof(ParamInfo); // To get the last offset. | 136 *output_size = declared_size; |
124 *output_size = actual_size; | 137 backing_mem = new char[declared_size]; |
125 backing_mem = new char[actual_size]; | 138 copied_params = reinterpret_cast<CrossCallParamsEx*>(backing_mem); |
126 memset(backing_mem, 0, actual_size); | 139 memcpy(backing_mem, call_params, declared_size); |
127 // Note that this is a placement new. | |
128 #pragma warning(push) | |
129 #pragma warning(disable: 4291) // No matching operator delete. | |
130 // TODO(cpu): Remove this warning. | |
131 copied_params = new(backing_mem)CrossCallParamsEx(); | |
132 #pragma warning(pop) | |
133 memcpy(backing_mem, call_params, actual_size); | |
134 | 140 |
135 } __except(EXCEPTION_EXECUTE_HANDLER) { | 141 } __except(EXCEPTION_EXECUTE_HANDLER) { |
136 // In case of a windows exception we know it occurred while touching the | 142 // In case of a windows exception we know it occurred while touching the |
137 // untrusted buffer so we bail out as is. | 143 // untrusted buffer so we bail out as is. |
| 144 delete [] backing_mem; |
138 return NULL; | 145 return NULL; |
139 } | 146 } |
140 | 147 |
141 char* last_byte = &backing_mem[actual_size - 1]; | 148 const char* last_byte = &backing_mem[declared_size]; |
| 149 const char* first_byte = &backing_mem[min_declared_size]; |
| 150 |
142 // Verify here that all and each parameters make sense. This is done in the | 151 // Verify here that all and each parameters make sense. This is done in the |
143 // local copy. | 152 // local copy. |
144 for (size_t ix =0; ix != param_count; ++ix) { | 153 for (size_t ix =0; ix != param_count; ++ix) { |
145 size_t size = 0; | 154 size_t size = 0; |
146 ArgType type; | 155 ArgType type; |
147 char* address = reinterpret_cast<char*>( | 156 char* address = reinterpret_cast<char*>( |
148 copied_params->GetRawParameter(ix, &size, &type)); | 157 copied_params->GetRawParameter(ix, &size, &type)); |
149 if ((NULL == address) || // No null params. | 158 if ((NULL == address) || // No null params. |
150 (INVALID_TYPE >= type) || (LAST_TYPE <= type) || // Unknown type. | 159 (INVALID_TYPE >= type) || (LAST_TYPE <= type) || // Unknown type. |
151 (address < backing_mem) || // Start cannot point before buffer. | 160 (address < backing_mem) || // Start cannot point before buffer. |
| 161 (address < first_byte) || // Start cannot point too low. |
152 (address > last_byte) || // Start cannot point past buffer. | 162 (address > last_byte) || // Start cannot point past buffer. |
153 ((address + size) < address) || // Invalid size. | 163 ((address + size) < address) || // Invalid size. |
154 ((address + size) > last_byte)) { // End cannot point past buffer. | 164 ((address + size) > last_byte)) { // End cannot point past buffer. |
155 // Malformed. | 165 // Malformed. |
156 delete[] backing_mem; | 166 delete[] backing_mem; |
157 return NULL; | 167 return NULL; |
158 } | 168 } |
159 } | 169 } |
160 // The parameter buffer looks good. | 170 // The parameter buffer looks good. |
161 return copied_params; | 171 return copied_params; |
162 } | 172 } |
163 | 173 |
164 // Accessors to the parameters in the raw buffer. | 174 // Accessors to the parameters in the raw buffer. |
165 void* CrossCallParamsEx::GetRawParameter(size_t index, size_t* size, | 175 void* CrossCallParamsEx::GetRawParameter(size_t index, size_t* size, |
166 ArgType* type) { | 176 ArgType* type) { |
167 if (index > GetParamsCount()) { | 177 if (index >= GetParamsCount()) { |
168 return NULL; | 178 return NULL; |
169 } | 179 } |
170 // The size is always computed from the parameter minus the next | 180 // The size is always computed from the parameter minus the next |
171 // parameter, this works because the message has an extra parameter slot | 181 // parameter, this works because the message has an extra parameter slot |
172 *size = param_info_[index].size_; | 182 *size = param_info_[index].size_; |
173 *type = param_info_[index].type_; | 183 *type = param_info_[index].type_; |
174 | 184 |
175 return param_info_[index].offset_ + reinterpret_cast<char*>(this); | 185 return param_info_[index].offset_ + reinterpret_cast<char*>(this); |
176 } | 186 } |
177 | 187 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
256 for (; it != ipc_calls_.end(); ++it) { | 266 for (; it != ipc_calls_.end(); ++it) { |
257 if (it->params.Matches(ipc)) { | 267 if (it->params.Matches(ipc)) { |
258 *callback = it->callback; | 268 *callback = it->callback; |
259 return this; | 269 return this; |
260 } | 270 } |
261 } | 271 } |
262 return NULL; | 272 return NULL; |
263 } | 273 } |
264 | 274 |
265 } // namespace sandbox | 275 } // namespace sandbox |
OLD | NEW |