summaryrefslogtreecommitdiffstats
path: root/sandbox
diff options
context:
space:
mode:
authorcpu@chromium.org <cpu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-22 23:38:14 +0000
committercpu@chromium.org <cpu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-22 23:38:14 +0000
commite9b676190a37d4f1f57cc6b9f2f3bad634449101 (patch)
tree814cdb0287b1fece49be866bbc8a221f0106ed0b /sandbox
parentda17b37430e97d518b7d640b98831c8e338b478c (diff)
downloadchromium_src-e9b676190a37d4f1f57cc6b9f2f3bad634449101.zip
chromium_src-e9b676190a37d4f1f57cc6b9f2f3bad634449101.tar.gz
chromium_src-e9b676190a37d4f1f57cc6b9f2f3bad634449101.tar.bz2
Fix integer overflow in sbox
BUG=32915 TEST= unit test included Review URL: http://codereview.chromium.org/553061 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@36923 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'sandbox')
-rw-r--r--sandbox/src/crosscall_params.h7
-rw-r--r--sandbox/src/crosscall_server.cc50
-rw-r--r--sandbox/src/ipc_unittest.cc39
3 files changed, 67 insertions, 29 deletions
diff --git a/sandbox/src/crosscall_params.h b/sandbox/src/crosscall_params.h
index 5e562cc..f6de823 100644
--- a/sandbox/src/crosscall_params.h
+++ b/sandbox/src/crosscall_params.h
@@ -202,6 +202,13 @@ class ActualCallParams : public CrossCallParams {
param_info_[0].offset_ = parameters_ - reinterpret_cast<char*>(this);
}
+ // Testing-only constructor. Allows setting the |number_params| to a
+ // wrong value.
+ ActualCallParams(uint32 tag, uint32 number_params)
+ : 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,
diff --git a/sandbox/src/crosscall_server.cc b/sandbox/src/crosscall_server.cc
index aff1ff4..35e80f4 100644
--- a/sandbox/src/crosscall_server.cc
+++ b/sandbox/src/crosscall_server.cc
@@ -21,9 +21,9 @@ namespace {
namespace sandbox {
-// Returns the actual size for the parameters in an IPC buffer.
-void GetActualBufferSize(size_t param_count, void* buffer_base,
- size_t* actual_size) {
+// Returns the actual size for the parameters in an IPC buffer. Returns
+// zero if the |param_count| is zero or too big.
+size_t GetActualBufferSize(size_t 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;
@@ -37,36 +37,29 @@ void GetActualBufferSize(size_t param_count, void* buffer_base,
// Retrieve the actual size and the maximum size of the params buffer.
switch (param_count) {
+ case 0:
+ return 0;
case 1:
- *actual_size = reinterpret_cast<ActualCP1*>(buffer_base)->GetSize();
- break;
+ return reinterpret_cast<ActualCP1*>(buffer_base)->GetSize();
case 2:
- *actual_size = reinterpret_cast<ActualCP2*>(buffer_base)->GetSize();
- break;
+ return reinterpret_cast<ActualCP2*>(buffer_base)->GetSize();
case 3:
- *actual_size = reinterpret_cast<ActualCP3*>(buffer_base)->GetSize();
- break;
+ return reinterpret_cast<ActualCP3*>(buffer_base)->GetSize();
case 4:
- *actual_size = reinterpret_cast<ActualCP4*>(buffer_base)->GetSize();
- break;
+ return reinterpret_cast<ActualCP4*>(buffer_base)->GetSize();
case 5:
- *actual_size = reinterpret_cast<ActualCP5*>(buffer_base)->GetSize();
- break;
+ return reinterpret_cast<ActualCP5*>(buffer_base)->GetSize();
case 6:
- *actual_size = reinterpret_cast<ActualCP6*>(buffer_base)->GetSize();
- break;
+ return reinterpret_cast<ActualCP6*>(buffer_base)->GetSize();
case 7:
- *actual_size = reinterpret_cast<ActualCP7*>(buffer_base)->GetSize();
- break;
+ return reinterpret_cast<ActualCP7*>(buffer_base)->GetSize();
case 8:
- *actual_size = reinterpret_cast<ActualCP8*>(buffer_base)->GetSize();
- break;
+ return reinterpret_cast<ActualCP8*>(buffer_base)->GetSize();
case 9:
- *actual_size = reinterpret_cast<ActualCP9*>(buffer_base)->GetSize();
- break;
+ return reinterpret_cast<ActualCP9*>(buffer_base)->GetSize();
default:
NOTREACHED();
- *actual_size = 0;
+ return 0;
}
}
@@ -104,8 +97,7 @@ CrossCallParamsEx* CrossCallParamsEx::CreateFromBuffer(void* buffer_base,
char* backing_mem = NULL;
size_t param_count = 0;
CrossCallParamsEx* copied_params = NULL;
-
- size_t actual_size = 0;
+ size_t actual_size;
// Touching the untrusted buffer is done under a SEH try block. This
// will catch memory access violations so we don't crash.
@@ -117,16 +109,16 @@ CrossCallParamsEx* CrossCallParamsEx::CreateFromBuffer(void* buffer_base,
param_count = call_params->GetParamsCount();
if ((buffer_size - sizeof(CrossCallParams)) <
(sizeof(ptrdiff_t) * (param_count + 1))) {
- // Too small.
+ // This test is subject to integer overflow but the next is not.
return NULL;
}
- GetActualBufferSize(param_count, buffer_base, &actual_size);
-
- if (actual_size > buffer_size) {
- // It is too big.
+ actual_size = GetActualBufferSize(param_count, buffer_base);
+ if ((actual_size > buffer_size) || (0 == actual_size)) {
+ // It is too big or too many declared parameters.
return NULL;
}
+
// Now we copy the actual amount of the message.
actual_size += sizeof(ParamInfo); // To get the last offset.
*output_size = actual_size;
diff --git a/sandbox/src/ipc_unittest.cc b/sandbox/src/ipc_unittest.cc
index 60f326c..cb9e81c 100644
--- a/sandbox/src/ipc_unittest.cc
+++ b/sandbox/src/ipc_unittest.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/basictypes.h"
#include "sandbox/src/crosscall_client.h"
#include "sandbox/src/crosscall_server.h"
#include "sandbox/src/sharedmem_ipc_client.h"
@@ -214,6 +215,44 @@ TEST(IPCTest, CrossCallStrPacking) {
delete [] reinterpret_cast<char*>(client_control);
}
+TEST(IPCTest, CrossCallValidation) {
+ // First a sanity test with a well formed parameter object.
+ unsigned long value = 124816;
+ const uint32 kTag = 33;
+ ActualCallParams<1, 128> params_1(kTag);
+ params_1.CopyParamIn(0, &value, sizeof(value), false, ULONG_TYPE);
+ void* buffer = const_cast<void*>(params_1.GetBuffer());
+
+ size_t out_size = 0;
+ CrossCallParamsEx* ccp = 0;
+ ccp = CrossCallParamsEx::CreateFromBuffer(buffer, params_1.GetSize(),
+ &out_size);
+ ASSERT_TRUE(NULL != ccp);
+ EXPECT_TRUE(ccp->GetBuffer() != buffer);
+ EXPECT_EQ(kTag, ccp->GetTag());
+ EXPECT_EQ(1, ccp->GetParamsCount());
+ delete[] (reinterpret_cast<char*>(ccp));
+
+#if defined(NDEBUG)
+ // Test hat we handle integer overflow on the number of params
+ // correctly. We use a test-only ctor for ActualCallParams that
+ // allows to create malformed cross-call buffers.
+ const int32 kPtrDiffSz = sizeof(ptrdiff_t);
+ for (int32 ix = -1; ix != 3; ++ix) {
+ uint32 fake_num_params = (kuint32max / kPtrDiffSz) + ix;
+ ActualCallParams<1, 128> params_2(kTag, fake_num_params);
+ params_2.CopyParamIn(0, &value, sizeof(value), false, ULONG_TYPE);
+ buffer = const_cast<void*>(params_2.GetBuffer());
+
+ EXPECT_TRUE(NULL != buffer);
+ ccp = CrossCallParamsEx::CreateFromBuffer(buffer, params_2.GetSize(),
+ &out_size);
+ // If the buffer is malformed the return is NULL.
+ EXPECT_TRUE(NULL == ccp);
+ }
+#endif // defined(NDEBUG)
+}
+
// This structure is passed to the mock server threads to simulate
// the server side IPC so it has the required kernel objects.
struct ServerEvents {