diff options
author | cpu@chromium.org <cpu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-12 20:59:39 +0000 |
---|---|---|
committer | cpu@chromium.org <cpu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-12 20:59:39 +0000 |
commit | a37a999f87eed77b08e7e1b6bdb86d406f31ea9b (patch) | |
tree | 070577d8aebd6b62788e64bb4c94e1106abc34aa /sandbox/src | |
parent | 836f9d7211bb84b2d6ff5c8cc33630599ddeee51 (diff) | |
download | chromium_src-a37a999f87eed77b08e7e1b6bdb86d406f31ea9b.zip chromium_src-a37a999f87eed77b08e7e1b6bdb86d406f31ea9b.tar.gz chromium_src-a37a999f87eed77b08e7e1b6bdb86d406f31ea9b.tar.bz2 |
Secound round of sbox changes for 64 bit port
- Handling pointer sized items
- Beefing up unit tests
- Beefing up integration tests
- Enabling Process, Thread and Token IPCs
- Making validation tests compile again
BUG=27218
TEST= unit tests included
Review URL: http://codereview.chromium.org/757001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@41481 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'sandbox/src')
-rw-r--r-- | sandbox/src/crosscall_client.h | 44 | ||||
-rw-r--r-- | sandbox/src/crosscall_server.cc | 15 | ||||
-rw-r--r-- | sandbox/src/crosscall_server.h | 9 | ||||
-rw-r--r-- | sandbox/src/interceptors_64.cc | 6 | ||||
-rw-r--r-- | sandbox/src/ipc_unittest.cc | 282 | ||||
-rw-r--r-- | sandbox/src/policy_broker.cc | 5 | ||||
-rw-r--r-- | sandbox/src/policy_target_test.cc | 12 | ||||
-rw-r--r-- | sandbox/src/process_thread_dispatcher.cc | 8 | ||||
-rw-r--r-- | sandbox/src/process_thread_dispatcher.h | 12 | ||||
-rw-r--r-- | sandbox/src/process_thread_policy.cc | 21 | ||||
-rw-r--r-- | sandbox/src/process_thread_policy.h | 20 | ||||
-rw-r--r-- | sandbox/src/sandbox_policy_base.cc | 17 | ||||
-rw-r--r-- | sandbox/src/sharedmem_ipc_server.cc | 11 | ||||
-rw-r--r-- | sandbox/src/sharedmem_ipc_server.h | 11 |
14 files changed, 330 insertions, 143 deletions
diff --git a/sandbox/src/crosscall_client.h b/sandbox/src/crosscall_client.h index c2d3045..e58388c9 100644 --- a/sandbox/src/crosscall_client.h +++ b/sandbox/src/crosscall_client.h @@ -1,9 +1,9 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef SANDBOX_SRC_CROSSCALL_CLIENT_H__ -#define SANDBOX_SRC_CROSSCALL_CLIENT_H__ +#ifndef SANDBOX_SRC_CROSSCALL_CLIENT_H_ +#define SANDBOX_SRC_CROSSCALL_CLIENT_H_ #include "sandbox/src/crosscall_params.h" #include "sandbox/src/sandbox.h" @@ -86,6 +86,44 @@ class CopyHelper { const T& t_; }; +// This copy helper template specialization if for the void pointer +// case both 32 and 64 bit. +template<> +class CopyHelper<void*> { + public: + CopyHelper(void* t) : t_(t) {} + + // Returns the pointer to the start of the input. + const void* GetStart() const { + return &t_; + } + + // Update the stored value with the value in the buffer. This is not + // supported for this type. + bool Update(void* buffer) { + // Not supported; + return true; + } + + // Returns the size of the input in bytes. + size_t GetSize() const { + return sizeof(t_); + } + + // Returns true if the current type is used as an In or InOut parameter. + bool IsInOut() { + return false; + } + + // Returns this object's type. + ArgType GetType() { + return VOIDPTR_TYPE; + } + + private: + const void* t_; +}; + // This copy helper template specialization catches the cases where the // parameter is a pointer to a string. template<> diff --git a/sandbox/src/crosscall_server.cc b/sandbox/src/crosscall_server.cc index 35e80f4..da43c69 100644 --- a/sandbox/src/crosscall_server.cc +++ b/sandbox/src/crosscall_server.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -176,7 +176,7 @@ void* CrossCallParamsEx::GetRawParameter(size_t index, size_t* size, } // Covers common case for 32 bit integers. -bool CrossCallParamsEx::GetParameter32(size_t index, void* param) { +bool CrossCallParamsEx::GetParameter32(size_t index, uint32* param) { size_t size = 0; ArgType type; void* start = GetRawParameter(index, &size, &type); @@ -188,6 +188,17 @@ bool CrossCallParamsEx::GetParameter32(size_t index, void* param) { return true; } +bool CrossCallParamsEx::GetParameterVoidPtr(size_t index, void** param) { + size_t size = 0; + ArgType type; + void* start = GetRawParameter(index, &size, &type); + if ((NULL == start) || (sizeof(void*) != size) || (VOIDPTR_TYPE != type)) { + return false; + } + *param = *(reinterpret_cast<void**>(start)); + return true; +} + // Covers the common case of reading a string. Note that the string is not // scanned for invalid characters. bool CrossCallParamsEx::GetParameterStr(size_t index, std::wstring* string) { diff --git a/sandbox/src/crosscall_server.h b/sandbox/src/crosscall_server.h index fd0cd4c..06c0e02 100644 --- a/sandbox/src/crosscall_server.h +++ b/sandbox/src/crosscall_server.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -7,6 +7,7 @@ #include <string> #include <vector> +#include "base/basictypes.h" #include "base/callback.h" #include "sandbox/src/crosscall_params.h" @@ -103,7 +104,11 @@ class CrossCallParamsEx : public CrossCallParams { // Gets a parameter that is four bytes in size. // Returns false if the parameter does not exist or is not 32 bits wide. - bool GetParameter32(size_t index, void* param); + bool GetParameter32(size_t index, uint32* param); + + // Gets a parameter that is void pointer in size. + // Returns false if the parameter does not exist or is not void pointer sized. + bool GetParameterVoidPtr(size_t index, void** param); // Gets a parameter that is a string. Returns false if the parameter does not // exist. diff --git a/sandbox/src/interceptors_64.cc b/sandbox/src/interceptors_64.cc index a63ec33..49018a0 100644 --- a/sandbox/src/interceptors_64.cc +++ b/sandbox/src/interceptors_64.cc @@ -141,9 +141,6 @@ SANDBOX_INTERCEPT HANDLE WINAPI TargetCreateNamedPipeW64( // ----------------------------------------------------------------------- -#if 0 -// Bug 27218: We don't have IPC yet. - SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenThread64( PHANDLE thread, ACCESS_MASK desired_access, POBJECT_ATTRIBUTES object_attributes, PCLIENT_ID client_id) { @@ -209,7 +206,8 @@ SANDBOX_INTERCEPT BOOL WINAPI TargetCreateProcessA64( } // ----------------------------------------------------------------------- - +#if 0 +// Bug 27218: We don't have IPC yet. SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtCreateKey64( PHANDLE key, ACCESS_MASK desired_access, POBJECT_ATTRIBUTES object_attributes, ULONG title_index, diff --git a/sandbox/src/ipc_unittest.cc b/sandbox/src/ipc_unittest.cc index 1ba24ab..909f144 100644 --- a/sandbox/src/ipc_unittest.cc +++ b/sandbox/src/ipc_unittest.cc @@ -6,9 +6,9 @@ #include "sandbox/src/crosscall_client.h" #include "sandbox/src/crosscall_server.h" #include "sandbox/src/sharedmem_ipc_client.h" +#include "sandbox/src/sharedmem_ipc_server.h" #include "testing/gtest/include/gtest/gtest.h" - namespace sandbox { // Helper function to make the fake shared memory with some @@ -18,30 +18,54 @@ IPCControl* MakeChannels(size_t channel_size, size_t total_shared_size, // Allocate memory char* mem = new char[total_shared_size]; memset(mem, 0, total_shared_size); - // Calculate how many channels we can fit in the shared memory. total_shared_size -= offsetof(IPCControl, channels); size_t channel_count = total_shared_size / (sizeof(ChannelControl) + channel_size); - // Calculate the start of the first channel. *base_start = (sizeof(ChannelControl)* channel_count) + offsetof(IPCControl, channels); - // Setup client structure. IPCControl* client_control = reinterpret_cast<IPCControl*>(mem); client_control->channels_count = channel_count; - return client_control; } -TEST(IPCTest, ChannelMaker) { - size_t channel_start = 0; - IPCControl* client_control = MakeChannels(12*64, 4096, &channel_start); +enum TestFixMode { + FIX_NO_EVENTS, + FIX_PONG_READY, + FIX_PONG_NOT_READY +}; +void FixChannels(IPCControl* client_control, size_t base_start, + size_t channel_size, TestFixMode mode) { + for (size_t ix = 0; ix != client_control->channels_count; ++ix) { + ChannelControl& channel = client_control->channels[ix]; + channel.channel_base = base_start; + channel.state = kFreeChannel; + if (mode != FIX_NO_EVENTS) { + BOOL signaled = (FIX_PONG_READY == mode)? TRUE : FALSE; + channel.ping_event = ::CreateEventW(NULL, FALSE, FALSE, NULL); + channel.pong_event = ::CreateEventW(NULL, FALSE, signaled, NULL); + } + base_start += channel_size; + } +} + +void CloseChannelEvents(IPCControl* client_control) { + for (size_t ix = 0; ix != client_control->channels_count; ++ix) { + ChannelControl& channel = client_control->channels[ix]; + ::CloseHandle(channel.ping_event); + ::CloseHandle(channel.pong_event); + } +} + +TEST(IPCTest, ChannelMaker) { // Test that our testing rig is computing offsets properly. We should have // 5 channnels and the offset to the first channel is 108 bytes in 32 bits // and 216 in 64 bits. + size_t channel_start = 0; + IPCControl* client_control = MakeChannels(12 * 64, 4096, &channel_start); ASSERT_TRUE(NULL != client_control); EXPECT_EQ(5, client_control->channels_count); #if defined(_WIN64) @@ -49,23 +73,16 @@ TEST(IPCTest, ChannelMaker) { #else EXPECT_EQ(108, channel_start); #endif - - delete [] reinterpret_cast<char*>(client_control); + delete[] reinterpret_cast<char*>(client_control); } TEST(IPCTest, ClientLockUnlock) { // Make 7 channels of kIPCChannelSize (1kb) each. Test that we lock and // unlock channels properly. - const size_t channel_size = kIPCChannelSize; size_t base_start = 0; - IPCControl* client_control = MakeChannels(channel_size, 4096*2, &base_start); - - for (size_t ix = 0; ix != client_control->channels_count; ++ix) { - ChannelControl& channel = client_control->channels[ix]; - channel.channel_base = base_start; - channel.state = kFreeChannel; - base_start += channel_size; - } + IPCControl* client_control = + MakeChannels(kIPCChannelSize, 4096 * 2, &base_start); + FixChannels(client_control, base_start, kIPCChannelSize, FIX_NO_EVENTS); char* mem = reinterpret_cast<char*>(client_control); SharedMemIPCClient client(mem); @@ -124,26 +141,18 @@ TEST(IPCTest, ClientLockUnlock) { EXPECT_EQ(kFreeChannel, client_control->channels[4].state); EXPECT_EQ(kFreeChannel, client_control->channels[5].state); - delete [] reinterpret_cast<char*>(client_control); + delete[] reinterpret_cast<char*>(client_control); } TEST(IPCTest, CrossCallStrPacking) { // This test tries the CrossCall object with null and non-null string - // combination of parameters and verifies that the unpacker can read them - // properly. - const size_t channel_size = kIPCChannelSize; + // combination of parameters, integer types and verifies that the unpacker + // can read them properly. size_t base_start = 0; - IPCControl* client_control = MakeChannels(channel_size, 4096*2, &base_start); + IPCControl* client_control = + MakeChannels(kIPCChannelSize, 4096 * 4, &base_start); client_control->server_alive = HANDLE(1); - - for (size_t ix = 0; ix != client_control->channels_count; ++ix) { - ChannelControl& channel = client_control->channels[ix]; - channel.channel_base = base_start; - channel.state = kFreeChannel; - channel.ping_event = ::CreateEventW(NULL, FALSE, FALSE, NULL); - channel.pong_event = ::CreateEventW(NULL, FALSE, TRUE, NULL); - base_start += channel_size; - } + FixChannels(client_control, base_start, kIPCChannelSize, FIX_PONG_READY); char* mem = reinterpret_cast<char*>(client_control); SharedMemIPCClient client(mem); @@ -212,12 +221,79 @@ TEST(IPCTest, CrossCallStrPacking) { EXPECT_EQ(0, param_size); EXPECT_EQ(WCHAR_TYPE, type); - for (size_t ix = 0; ix != client_control->channels_count; ++ix) { - ChannelControl& channel = client_control->channels[ix]; - ::CloseHandle(channel.ping_event); - ::CloseHandle(channel.pong_event); - } - delete [] reinterpret_cast<char*>(client_control); + CloseChannelEvents(client_control); + delete[] reinterpret_cast<char*>(client_control); +} + +TEST(IPCTest, CrossCallIntPacking) { + // Check handling for regular 32 bit integers used in Windows. + size_t base_start = 0; + IPCControl* client_control = + MakeChannels(kIPCChannelSize, 4096 * 4, &base_start); + client_control->server_alive = HANDLE(1); + FixChannels(client_control, base_start, kIPCChannelSize, FIX_PONG_READY); + + uint32 tag1 = 999; + uint32 tag2 = 111; + const wchar_t text[] = L"godzilla"; + CrossCallParamsEx* actual_params; + + char* mem = reinterpret_cast<char*>(client_control); + SharedMemIPCClient client(mem); + + CrossCallReturn answer; + DWORD dw = 0xE6578; + CrossCall(client, tag2, dw, &answer); + actual_params = reinterpret_cast<CrossCallParamsEx*>(client.GetBuffer()); + EXPECT_EQ(1, actual_params->GetParamsCount()); + EXPECT_EQ(tag2, actual_params->GetTag()); + ArgType type = INVALID_TYPE; + size_t param_size = 1; + void* param_addr = actual_params->GetRawParameter(0, ¶m_size, &type); + ASSERT_EQ(sizeof(dw), param_size); + EXPECT_EQ(ULONG_TYPE, type); + ASSERT_TRUE(NULL != param_addr); + EXPECT_EQ(0, memcmp(&dw, param_addr, param_size)); + + // Check handling for windows HANDLES. + HANDLE h = HANDLE(0x70000500); + CrossCall(client, tag1, text, h, &answer); + actual_params = reinterpret_cast<CrossCallParamsEx*>(client.GetBuffer()); + EXPECT_EQ(2, actual_params->GetParamsCount()); + EXPECT_EQ(tag1, actual_params->GetTag()); + type = INVALID_TYPE; + param_addr = actual_params->GetRawParameter(1, ¶m_size, &type); + ASSERT_EQ(sizeof(h), param_size); + EXPECT_EQ(VOIDPTR_TYPE, type); + ASSERT_TRUE(NULL != param_addr); + EXPECT_EQ(0, memcmp(&h, param_addr, param_size)); + + // Check combination of 32 and 64 bits. + CrossCall(client, tag2, h, dw, h, &answer); + actual_params = reinterpret_cast<CrossCallParamsEx*>(client.GetBuffer()); + EXPECT_EQ(3, actual_params->GetParamsCount()); + EXPECT_EQ(tag2, actual_params->GetTag()); + type = INVALID_TYPE; + param_addr = actual_params->GetRawParameter(0, ¶m_size, &type); + ASSERT_EQ(sizeof(h), param_size); + EXPECT_EQ(VOIDPTR_TYPE, type); + ASSERT_TRUE(NULL != param_addr); + EXPECT_EQ(0, memcmp(&h, param_addr, param_size)); + type = INVALID_TYPE; + param_addr = actual_params->GetRawParameter(1, ¶m_size, &type); + ASSERT_EQ(sizeof(dw), param_size); + EXPECT_EQ(ULONG_TYPE, type); + ASSERT_TRUE(NULL != param_addr); + EXPECT_EQ(0, memcmp(&dw, param_addr, param_size)); + type = INVALID_TYPE; + param_addr = actual_params->GetRawParameter(2, ¶m_size, &type); + ASSERT_EQ(sizeof(h), param_size); + EXPECT_EQ(VOIDPTR_TYPE, type); + ASSERT_TRUE(NULL != param_addr); + EXPECT_EQ(0, memcmp(&h, param_addr, param_size)); + + CloseChannelEvents(client_control); + delete[] reinterpret_cast<char*>(client_control); } TEST(IPCTest, CrossCallValidation) { @@ -297,17 +373,9 @@ void FakeOkAnswerInChannel(void* channel) { TEST(IPCTest, ClientFastServer) { const size_t channel_size = kIPCChannelSize; size_t base_start = 0; - IPCControl* client_control = MakeChannels(channel_size, 4096*2, &base_start); - - for (size_t ix = 0; ix != client_control->channels_count; ++ix) { - ChannelControl& channel = client_control->channels[ix]; - channel.channel_base = base_start; - channel.state = kFreeChannel; - channel.ping_event = ::CreateEventW(NULL, FALSE, FALSE, NULL); - channel.pong_event = ::CreateEventW(NULL, FALSE, FALSE, NULL); - base_start += channel_size; - } - + IPCControl* client_control = + MakeChannels(channel_size, 4096 * 2, &base_start); + FixChannels(client_control, base_start, kIPCChannelSize, FIX_PONG_NOT_READY); client_control->server_alive = ::CreateMutex(NULL, FALSE, NULL); char* mem = reinterpret_cast<char*>(client_control); @@ -374,14 +442,10 @@ TEST(IPCTest, ClientFastServer) { EXPECT_EQ(kFreeChannel, client_control->channels[1].state); EXPECT_EQ(kFreeChannel, client_control->channels[2].state); - for (size_t ix = 0; ix != client_control->channels_count; ++ix) { - ChannelControl& channel = client_control->channels[ix]; - ::CloseHandle(channel.ping_event); - ::CloseHandle(channel.pong_event); - } - + CloseChannelEvents(client_control); ::CloseHandle(client_control->server_alive); - delete [] reinterpret_cast<char*>(client_control); + + delete[] reinterpret_cast<char*>(client_control); } // This is the server thread that very slowly answers an IPC and exits. Note @@ -410,19 +474,10 @@ DWORD WINAPI MainServerThread(PVOID param) { // to hold locked the server_alive mutex: this signals the client that the // server is not dead and it retries the wait. TEST(IPCTest, ClientSlowServer) { - const size_t channel_size = kIPCChannelSize; size_t base_start = 0; - IPCControl* client_control = MakeChannels(channel_size, 4096*2, &base_start); - - for (size_t ix = 0; ix != client_control->channels_count; ++ix) { - ChannelControl& channel = client_control->channels[ix]; - channel.channel_base = base_start; - channel.state = kFreeChannel; - channel.ping_event = ::CreateEventW(NULL, FALSE, FALSE, NULL); - channel.pong_event = ::CreateEventW(NULL, FALSE, FALSE, NULL); - base_start += channel_size; - } - + IPCControl* client_control = + MakeChannels(kIPCChannelSize, 4096*2, &base_start); + FixChannels(client_control, base_start, kIPCChannelSize, FIX_PONG_NOT_READY); client_control->server_alive = ::CreateMutex(NULL, FALSE, NULL); char* mem = reinterpret_cast<char*>(client_control); @@ -461,13 +516,90 @@ TEST(IPCTest, ClientSlowServer) { EXPECT_EQ(tag, client_control->channels[0].ipc_tag); EXPECT_EQ(kFreeChannel, client_control->channels[0].state); - for (size_t ix = 0; ix != client_control->channels_count; ++ix) { - ChannelControl& channel = client_control->channels[ix]; - ::CloseHandle(channel.ping_event); - ::CloseHandle(channel.pong_event); - } + CloseChannelEvents(client_control); ::CloseHandle(client_control->server_alive); - delete [] reinterpret_cast<char*>(client_control); + delete[] reinterpret_cast<char*>(client_control); +} + +// This test-only IPC dispatcher has two handlers with the same signature +// but only CallOneHandler should be used. +class UnitTestIPCDispatcher : public Dispatcher { + public: + enum { + CALL_ONE_TAG = 78, + CALL_TWO_TAG = 87 + }; + + UnitTestIPCDispatcher(); + ~UnitTestIPCDispatcher() {}; + + virtual bool SetupService(InterceptionManager* manager, int service) { + return true; + } + + private: + bool CallOneHandler(IPCInfo* ipc, HANDLE p1, DWORD p2) { + ipc->return_info.extended[0].handle = p1; + ipc->return_info.extended[1].unsigned_int = p2; + return true; + } + + bool CallTwoHandler(IPCInfo* ipc, HANDLE p1, DWORD p2) { + return true; + } +}; + +UnitTestIPCDispatcher::UnitTestIPCDispatcher() { + static const IPCCall call_one = { + {CALL_ONE_TAG, VOIDPTR_TYPE, ULONG_TYPE}, + reinterpret_cast<CallbackGeneric>( + &UnitTestIPCDispatcher::CallOneHandler) + }; + static const IPCCall call_two = { + {CALL_TWO_TAG, VOIDPTR_TYPE, ULONG_TYPE}, + reinterpret_cast<CallbackGeneric>( + &UnitTestIPCDispatcher::CallTwoHandler) + }; + ipc_calls_.push_back(call_one); + ipc_calls_.push_back(call_two); +} + +// This test does most of the shared memory IPC client-server roundtrip +// and tests the packing, unpacking and call dispatching. +TEST(IPCTest, SharedMemServerTests) { + size_t base_start = 0; + IPCControl* client_control = + MakeChannels(kIPCChannelSize, 4096, &base_start); + client_control->server_alive = HANDLE(1); + FixChannels(client_control, base_start, kIPCChannelSize, FIX_PONG_READY); + + char* mem = reinterpret_cast<char*>(client_control); + SharedMemIPCClient client(mem); + + CrossCallReturn answer; + HANDLE bar = HANDLE(191919); + DWORD foo = 6767676; + CrossCall(client, UnitTestIPCDispatcher::CALL_ONE_TAG, bar, foo, &answer); + void* buff = client.GetBuffer(); + ASSERT_TRUE(NULL != buff); + + UnitTestIPCDispatcher dispatcher; + // Since we are directly calling InvokeCallback, most of this structure + // can be set to NULL. + sandbox::SharedMemIPCServer::ServerControl srv_control = { + NULL, NULL, kIPCChannelSize, NULL, + reinterpret_cast<char*>(client_control), + NULL, &dispatcher, {0} }; + + sandbox::CrossCallReturn call_return = {0}; + EXPECT_TRUE(SharedMemIPCServer::InvokeCallback(&srv_control, buff, + &call_return)); + EXPECT_EQ(SBOX_ALL_OK, call_return.call_outcome); + EXPECT_TRUE(bar == call_return.extended[0].handle); + EXPECT_EQ(foo, call_return.extended[1].unsigned_int); + + CloseChannelEvents(client_control); + delete[] reinterpret_cast<char*>(client_control); } } // namespace sandbox diff --git a/sandbox/src/policy_broker.cc b/sandbox/src/policy_broker.cc index 82701ed..f2316b0 100644 --- a/sandbox/src/policy_broker.cc +++ b/sandbox/src/policy_broker.cc @@ -88,14 +88,11 @@ bool SetupNtdllImports(TargetProcess *child) { #undef INIT_GLOBAL_RTL bool SetupBasicInterceptions(InterceptionManager* manager) { -#if !defined(_WIN64) - // Bug 27218: We don't have dispatch for some x64 syscalls. // Interceptions provided by process_thread_policy, without actual policy. if (!INTERCEPT_NT(manager, NtOpenThread, OPEN_TREAD_ID, 20) || !INTERCEPT_NT(manager, NtOpenProcess, OPEN_PROCESS_ID, 20) || !INTERCEPT_NT(manager, NtOpenProcessToken, OPEN_PROCESS_TOKEN_ID, 16)) return false; -#endif // Interceptions with neither policy nor IPC. if (!INTERCEPT_NT(manager, NtSetInformationThread, SET_INFORMATION_THREAD_ID, @@ -104,13 +101,11 @@ bool SetupBasicInterceptions(InterceptionManager* manager) { return false; if (win_util::GetWinVersion() >= win_util::WINVERSION_XP) { -#if !defined(_WIN64) // Bug 27218: We don't have dispatch for some x64 syscalls. // This one is also provided by process_thread_policy. if (!INTERCEPT_NT(manager, NtOpenProcessTokenEx, OPEN_PROCESS_TOKEN_EX_ID, 20)) return false; -#endif return INTERCEPT_NT(manager, NtOpenThreadTokenEx, OPEN_THREAD_TOKEN_EX_ID, 24); diff --git a/sandbox/src/policy_target_test.cc b/sandbox/src/policy_target_test.cc index 6a7aebb..d4ffb40 100644 --- a/sandbox/src/policy_target_test.cc +++ b/sandbox/src/policy_target_test.cc @@ -150,10 +150,10 @@ SBOX_TESTS_COMMAND int PolicyTargetTest_process(int argc, wchar_t **argv) { STARTUPINFO startup_info = {0}; startup_info.cb = sizeof(startup_info); PROCESS_INFORMATION process_info; - ::CreateProcess(L"foo.exe", L"foo.exe", NULL, NULL, FALSE, 0, NULL, NULL, - &startup_info, &process_info); - - return SBOX_TEST_SUCCEEDED; + if (!::CreateProcessW(L"foo.exe", L"foo.exe", NULL, NULL, FALSE, 0, + NULL, NULL, &startup_info, &process_info)) + return SBOX_TEST_SUCCEEDED; + return SBOX_TEST_FAILED; } TEST(PolicyTargetTest, SetInformationThread) { @@ -194,8 +194,6 @@ TEST(PolicyTargetTest, OpenThreadTokenEx) { EXPECT_EQ(ERROR_NO_TOKEN, runner.RunTest(L"PolicyTargetTest_token3")); } -#if !defined(_WIN64) -// Bug 27218: We don't have dispatch for some x64 syscalls. TEST(PolicyTargetTest, OpenThread) { TestRunner runner; EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"PolicyTargetTest_thread")) << @@ -211,6 +209,8 @@ TEST(PolicyTargetTest, OpenProcess) { "Opens a process"; } +#if !defined(_WIN64) + // Launches the app in the sandbox and ask it to wait in an // infinite loop. Waits for 2 seconds and then check if the // desktop associated with the app thread is not the same as the diff --git a/sandbox/src/process_thread_dispatcher.cc b/sandbox/src/process_thread_dispatcher.cc index bbc1e57..f3badb4 100644 --- a/sandbox/src/process_thread_dispatcher.cc +++ b/sandbox/src/process_thread_dispatcher.cc @@ -110,13 +110,13 @@ ThreadProcessDispatcher::ThreadProcessDispatcher(PolicyBase* policy_base) }; static const IPCCall process_token = { - {IPC_NTOPENPROCESSTOKEN_TAG, ULONG_TYPE, ULONG_TYPE}, + {IPC_NTOPENPROCESSTOKEN_TAG, VOIDPTR_TYPE, ULONG_TYPE}, reinterpret_cast<CallbackGeneric>( &ThreadProcessDispatcher::NtOpenProcessToken) }; static const IPCCall process_tokenex = { - {IPC_NTOPENPROCESSTOKENEX_TAG, ULONG_TYPE, ULONG_TYPE, ULONG_TYPE}, + {IPC_NTOPENPROCESSTOKENEX_TAG, VOIDPTR_TYPE, ULONG_TYPE, ULONG_TYPE}, reinterpret_cast<CallbackGeneric>( &ThreadProcessDispatcher::NtOpenProcessTokenEx) }; @@ -178,7 +178,7 @@ bool ThreadProcessDispatcher::NtOpenProcess(IPCInfo* ipc, DWORD desired_access, return true; } -bool ThreadProcessDispatcher::NtOpenProcessToken(IPCInfo* ipc, DWORD process, +bool ThreadProcessDispatcher::NtOpenProcessToken(IPCInfo* ipc, HANDLE process, DWORD desired_access) { HANDLE handle; NTSTATUS ret = ProcessPolicy::OpenProcessTokenAction(*ipc->client_info, @@ -189,7 +189,7 @@ bool ThreadProcessDispatcher::NtOpenProcessToken(IPCInfo* ipc, DWORD process, return true; } -bool ThreadProcessDispatcher::NtOpenProcessTokenEx(IPCInfo* ipc, DWORD process, +bool ThreadProcessDispatcher::NtOpenProcessTokenEx(IPCInfo* ipc, HANDLE process, DWORD desired_access, DWORD attributes) { HANDLE handle; diff --git a/sandbox/src/process_thread_dispatcher.h b/sandbox/src/process_thread_dispatcher.h index dfd58c0..0403c50 100644 --- a/sandbox/src/process_thread_dispatcher.h +++ b/sandbox/src/process_thread_dispatcher.h @@ -1,9 +1,9 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef SANDBOX_SRC_PROCESS_THREAD_DISPATCHER_H__ -#define SANDBOX_SRC_PROCESS_THREAD_DISPATCHER_H__ +#ifndef SANDBOX_SRC_PROCESS_THREAD_DISPATCHER_H_ +#define SANDBOX_SRC_PROCESS_THREAD_DISPATCHER_H_ #include "base/basictypes.h" #include "sandbox/src/crosscall_server.h" @@ -28,10 +28,10 @@ class ThreadProcessDispatcher : public Dispatcher { bool NtOpenProcess(IPCInfo* ipc, DWORD desired_access, DWORD process_id); // Processes IPC requests from calls to NtOpenProcessToken() in the target. - bool NtOpenProcessToken(IPCInfo* ipc, DWORD process, DWORD desired_access); + bool NtOpenProcessToken(IPCInfo* ipc, HANDLE process, DWORD desired_access); // Processes IPC requests from calls to NtOpenProcessTokenEx() in the target. - bool NtOpenProcessTokenEx(IPCInfo* ipc, DWORD process, DWORD desired_access, + bool NtOpenProcessTokenEx(IPCInfo* ipc, HANDLE process, DWORD desired_access, DWORD attributes); // Processes IPC requests coming from calls to CreateProcessW() in the target. @@ -44,4 +44,4 @@ class ThreadProcessDispatcher : public Dispatcher { } // namespace sandbox -#endif // SANDBOX_SRC_PROCESS_THREAD_DISPATCHER_H__ +#endif // SANDBOX_SRC_PROCESS_THREAD_DISPATCHER_H_ diff --git a/sandbox/src/process_thread_policy.cc b/sandbox/src/process_thread_policy.cc index 3abd043..7e4effb 100644 --- a/sandbox/src/process_thread_policy.cc +++ b/sandbox/src/process_thread_policy.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -103,7 +103,7 @@ bool ProcessPolicy::GenerateRules(const wchar_t* name, NTSTATUS ProcessPolicy::OpenThreadAction(const ClientInfo& client_info, uint32 desired_access, uint32 thread_id, - HANDLE *handle) { + HANDLE* handle) { *handle = NULL; NtOpenThreadFunction NtOpenThread = NULL; @@ -135,7 +135,7 @@ NTSTATUS ProcessPolicy::OpenThreadAction(const ClientInfo& client_info, NTSTATUS ProcessPolicy::OpenProcessAction(const ClientInfo& client_info, uint32 desired_access, uint32 process_id, - HANDLE *handle) { + HANDLE* handle) { *handle = NULL; NtOpenProcessFunction NtOpenProcess = NULL; @@ -165,16 +165,13 @@ NTSTATUS ProcessPolicy::OpenProcessAction(const ClientInfo& client_info, } NTSTATUS ProcessPolicy::OpenProcessTokenAction(const ClientInfo& client_info, - uint32 process_requested, + HANDLE process, uint32 desired_access, - HANDLE *handle) { + HANDLE* handle) { *handle = NULL; - NtOpenProcessTokenFunction NtOpenProcessToken = NULL; ResolveNTFunctionPtr("NtOpenProcessToken", &NtOpenProcessToken); - HANDLE process = reinterpret_cast<HANDLE>( - static_cast<ULONG_PTR>(process_requested)); if (CURRENT_PROCESS != process) return STATUS_ACCESS_DENIED; @@ -189,21 +186,18 @@ NTSTATUS ProcessPolicy::OpenProcessTokenAction(const ClientInfo& client_info, return STATUS_ACCESS_DENIED; } } - return status; } NTSTATUS ProcessPolicy::OpenProcessTokenExAction(const ClientInfo& client_info, - uint32 process_requested, + HANDLE process, uint32 desired_access, uint32 attributes, - HANDLE *handle) { + HANDLE* handle) { *handle = NULL; NtOpenProcessTokenExFunction NtOpenProcessTokenEx = NULL; ResolveNTFunctionPtr("NtOpenProcessTokenEx", &NtOpenProcessTokenEx); - HANDLE process = reinterpret_cast<HANDLE>( - static_cast<ULONG_PTR>(process_requested)); if (CURRENT_PROCESS != process) return STATUS_ACCESS_DENIED; @@ -218,7 +212,6 @@ NTSTATUS ProcessPolicy::OpenProcessTokenExAction(const ClientInfo& client_info, return STATUS_ACCESS_DENIED; } } - return status; } diff --git a/sandbox/src/process_thread_policy.h b/sandbox/src/process_thread_policy.h index 29ea91d..78323cc 100644 --- a/sandbox/src/process_thread_policy.h +++ b/sandbox/src/process_thread_policy.h @@ -1,9 +1,9 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef SANDBOX_SRC_PROCESS_THREAD_POLICY_H__ -#define SANDBOX_SRC_PROCESS_THREAD_POLICY_H__ +#ifndef SANDBOX_SRC_PROCESS_THREAD_POLICY_H_ +#define SANDBOX_SRC_PROCESS_THREAD_POLICY_H_ #include <string> @@ -37,7 +37,7 @@ class ProcessPolicy { static NTSTATUS OpenThreadAction(const ClientInfo& client_info, uint32 desired_access, uint32 thread_id, - HANDLE *handle); + HANDLE* handle); // Opens the process id passed in and returns the duplicated handle to // the child. We only allow the child processes to open themselves. Any other @@ -45,24 +45,24 @@ class ProcessPolicy { static NTSTATUS OpenProcessAction(const ClientInfo& client_info, uint32 desired_access, uint32 process_id, - HANDLE *handle); + HANDLE* handle); // Opens the token associated with the process and returns the duplicated // handle to the child. We only allow the child processes to open his own // token (using ::GetCurrentProcess()). static NTSTATUS OpenProcessTokenAction(const ClientInfo& client_info, - uint32 process, + HANDLE process, uint32 desired_access, - HANDLE *handle); + HANDLE* handle); // Opens the token associated with the process and returns the duplicated // handle to the child. We only allow the child processes to open his own // token (using ::GetCurrentProcess()). static NTSTATUS OpenProcessTokenExAction(const ClientInfo& client_info, - uint32 process, + HANDLE process, uint32 desired_access, uint32 attributes, - HANDLE *handle); + HANDLE* handle); // Processes a 'CreateProcessW()' request from the target. // 'client_info' : the target process that is making the request. @@ -79,4 +79,4 @@ class ProcessPolicy { } // namespace sandbox -#endif // SANDBOX_SRC_PROCESS_THREAD_POLICY_H__ +#endif // SANDBOX_SRC_PROCESS_THREAD_POLICY_H_ diff --git a/sandbox/src/sandbox_policy_base.cc b/sandbox/src/sandbox_policy_base.cc index d47d5921..4dbfc2d 100644 --- a/sandbox/src/sandbox_policy_base.cc +++ b/sandbox/src/sandbox_policy_base.cc @@ -71,6 +71,12 @@ PolicyBase::PolicyBase() // Initialize the IPC dispatcher array. memset(&ipc_targets_, NULL, sizeof(ipc_targets_)); Dispatcher* dispatcher = NULL; + dispatcher = new ThreadProcessDispatcher(this); + ipc_targets_[IPC_NTOPENTHREAD_TAG] = dispatcher; + ipc_targets_[IPC_NTOPENPROCESS_TAG] = dispatcher; + ipc_targets_[IPC_CREATEPROCESSW_TAG] = dispatcher; + ipc_targets_[IPC_NTOPENPROCESSTOKEN_TAG] = dispatcher; + ipc_targets_[IPC_NTOPENPROCESSTOKENEX_TAG] = dispatcher; #if !defined(_WIN64) // Bug 27218: We don't have dispatch for some x64 syscalls. dispatcher = new FilesystemDispatcher(this); @@ -79,17 +85,14 @@ PolicyBase::PolicyBase() ipc_targets_[IPC_NTSETINFO_RENAME_TAG] = dispatcher; ipc_targets_[IPC_NTQUERYATTRIBUTESFILE_TAG] = dispatcher; ipc_targets_[IPC_NTQUERYFULLATTRIBUTESFILE_TAG] = dispatcher; - dispatcher = new ThreadProcessDispatcher(this); - ipc_targets_[IPC_NTOPENTHREAD_TAG] = dispatcher; - ipc_targets_[IPC_NTOPENPROCESS_TAG] = dispatcher; - ipc_targets_[IPC_CREATEPROCESSW_TAG] = dispatcher; - ipc_targets_[IPC_NTOPENPROCESSTOKEN_TAG] = dispatcher; - ipc_targets_[IPC_NTOPENPROCESSTOKENEX_TAG] = dispatcher; + dispatcher = new NamedPipeDispatcher(this); ipc_targets_[IPC_CREATENAMEDPIPEW_TAG] = dispatcher; + dispatcher = new SyncDispatcher(this); ipc_targets_[IPC_CREATEEVENT_TAG] = dispatcher; ipc_targets_[IPC_OPENEVENT_TAG] = dispatcher; + dispatcher = new RegistryDispatcher(this); ipc_targets_[IPC_NTCREATEKEY_TAG] = dispatcher; ipc_targets_[IPC_NTOPENKEY_TAG] = dispatcher; @@ -102,10 +105,10 @@ PolicyBase::~PolicyBase() { TargetProcess* target = (*it); delete target; } + delete ipc_targets_[IPC_NTOPENTHREAD_TAG]; #if !defined(_WIN64) // Bug 27218: We don't have dispatch for some x64 syscalls. delete ipc_targets_[IPC_NTCREATEFILE_TAG]; - delete ipc_targets_[IPC_NTOPENTHREAD_TAG]; delete ipc_targets_[IPC_CREATENAMEDPIPEW_TAG]; delete ipc_targets_[IPC_CREATEEVENT_TAG]; delete ipc_targets_[IPC_NTCREATEKEY_TAG]; diff --git a/sandbox/src/sharedmem_ipc_server.cc b/sandbox/src/sharedmem_ipc_server.cc index d835033..b287d21 100644 --- a/sandbox/src/sharedmem_ipc_server.cc +++ b/sandbox/src/sharedmem_ipc_server.cc @@ -171,7 +171,7 @@ bool GetArgs(CrossCallParamsEx* params, IPCParams* ipc_params, break; } case ULONG_TYPE: { - ULONG data; + uint32 data; if (!params->GetParameter32(i, &data)) { ReleaseArgs(ipc_params, args); return false; @@ -180,6 +180,15 @@ bool GetArgs(CrossCallParamsEx* params, IPCParams* ipc_params, args[i] = ipc_int.AsVoidPtr(); break; } + case VOIDPTR_TYPE : { + void* data; + if (!params->GetParameterVoidPtr(i, &data)) { + ReleaseArgs(ipc_params, args); + return false; + } + args[i] = data; + break; + } case INOUTPTR_TYPE: { if (!args[i]) { ReleaseArgs(ipc_params, args); diff --git a/sandbox/src/sharedmem_ipc_server.h b/sandbox/src/sharedmem_ipc_server.h index 337a221..1041245 100644 --- a/sandbox/src/sharedmem_ipc_server.h +++ b/sandbox/src/sharedmem_ipc_server.h @@ -1,9 +1,9 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef SANDBOX_SRC_SHAREDMEM_IPC_SERVER_H__ -#define SANDBOX_SRC_SHAREDMEM_IPC_SERVER_H__ +#ifndef SANDBOX_SRC_SHAREDMEM_IPC_SERVER_H_ +#define SANDBOX_SRC_SHAREDMEM_IPC_SERVER_H_ #include <list> @@ -12,6 +12,8 @@ #include "sandbox/src/crosscall_server.h" #include "sandbox/src/sharedmem_ipc_client.h" +#include "testing/gtest/include/gtest/gtest_prod.h" + // IPC transport implementation that uses shared memory. // This is the server side // @@ -51,6 +53,7 @@ class SharedMemIPCServer { bool Init(void* shared_mem, size_t shared_size, size_t channel_size); private: + FRIEND_TEST(IPCTest, SharedMemServerTests); // When an event fires (IPC request). A thread from the ThreadProvider // will call this function. The context parameter should be the same as // provided when ThreadProvider::RegisterWait was called. @@ -120,4 +123,4 @@ class SharedMemIPCServer { } // namespace sandbox -#endif // SANDBOX_SRC_SHAREDMEM_IPC_SERVER_H__ +#endif // SANDBOX_SRC_SHAREDMEM_IPC_SERVER_H_ |