diff options
author | jschuh@chromium.org <jschuh@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-24 17:20:34 +0000 |
---|---|---|
committer | jschuh@chromium.org <jschuh@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-24 17:20:34 +0000 |
commit | 4a675af846624bccd583b8ae6b518391018ee6a6 (patch) | |
tree | f931ebaf34d7e451a10f9870f476919b8b611d55 /sandbox/src | |
parent | 65533ad0606a04de3746da2bc785702ba3da17b5 (diff) | |
download | chromium_src-4a675af846624bccd583b8ae6b518391018ee6a6.zip chromium_src-4a675af846624bccd583b8ae6b518391018ee6a6.tar.gz chromium_src-4a675af846624bccd583b8ae6b518391018ee6a6.tar.bz2 |
Close all open ALPC client ports at lockdown.
Close out the CSRSS and LSASS ALPC client ports that are opened during initialization.
BUG=58069
TEST=sbox_integration_tests --gtest_filter=HandleCloserTests.RunThreadPool
Review URL: http://codereview.chromium.org/7490002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@93827 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'sandbox/src')
-rw-r--r-- | sandbox/src/handle_closer.cc | 17 | ||||
-rw-r--r-- | sandbox/src/handle_closer.h | 4 | ||||
-rw-r--r-- | sandbox/src/handle_closer_test.cc | 49 | ||||
-rw-r--r-- | sandbox/src/interceptors.h | 4 | ||||
-rw-r--r-- | sandbox/src/interceptors_64.cc | 12 | ||||
-rw-r--r-- | sandbox/src/interceptors_64.h | 8 | ||||
-rw-r--r-- | sandbox/src/nt_internals.h | 14 | ||||
-rw-r--r-- | sandbox/src/policy_broker.cc | 1 | ||||
-rw-r--r-- | sandbox/src/process_thread_interception.cc | 30 | ||||
-rw-r--r-- | sandbox/src/process_thread_interception.h | 17 | ||||
-rw-r--r-- | sandbox/src/sandbox_nt_types.h | 1 | ||||
-rw-r--r-- | sandbox/src/sandbox_policy_base.cc | 3 |
12 files changed, 154 insertions, 6 deletions
diff --git a/sandbox/src/handle_closer.cc b/sandbox/src/handle_closer.cc index 4a08d2f..3ac802e 100644 --- a/sandbox/src/handle_closer.cc +++ b/sandbox/src/handle_closer.cc @@ -6,7 +6,11 @@ #include "base/logging.h" #include "base/memory/scoped_ptr.h" +#include "base/win/windows_version.h" +#include "sandbox/src/interceptors.h" +#include "sandbox/src/internal_types.h" #include "sandbox/src/nt_internals.h" +#include "sandbox/src/process_thread_interception.h" #include "sandbox/src/win_utils.h" namespace { @@ -149,6 +153,19 @@ bool HandleCloser::SetupHandleList(void* buffer, size_t buffer_bytes) { return output <= end; } +bool HandleCloser::SetupHandleInterceptions(InterceptionManager* manager) { + // We need to intercept CreateThread if we're closing ALPC port clients. + HandleMap::iterator names = handles_to_close_.find(L"ALPC Port"); + if (base::win::GetVersion() >= base::win::VERSION_VISTA && + names != handles_to_close_.end() && + (names->second.empty() || names->second.size() == 0)) { + return INTERCEPT_EAT(manager, kKerneldllName, CreateThread, + CREATE_THREAD_ID, 28); + } + + return true; +} + bool GetHandleName(HANDLE handle, string16* handle_name) { static NtQueryObject QueryObject = NULL; if (!QueryObject) diff --git a/sandbox/src/handle_closer.h b/sandbox/src/handle_closer.h index 7252968..76b1a51 100644 --- a/sandbox/src/handle_closer.h +++ b/sandbox/src/handle_closer.h @@ -10,6 +10,7 @@ #include "base/basictypes.h" #include "base/string16.h" +#include "sandbox/src/interception.h" #include "sandbox/src/sandbox_types.h" #include "sandbox/src/target_process.h" @@ -51,6 +52,9 @@ class HandleCloser { // Serializes and copies the closer table into the target process. bool InitializeTargetHandles(TargetProcess* target); + // Adds any interceptions that may be required due to closed system handles. + bool SetupHandleInterceptions(InterceptionManager* manager); + private: // Calculates the memory needed to copy the serialized handles list (rounded // to the nearest machine-word size). diff --git a/sandbox/src/handle_closer_test.cc b/sandbox/src/handle_closer_test.cc index b4d02d8..81b6db2 100644 --- a/sandbox/src/handle_closer_test.cc +++ b/sandbox/src/handle_closer_test.cc @@ -42,6 +42,10 @@ HANDLE GetMarkerFile(const wchar_t *extension) { NULL, OPEN_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL); } +// Used by the thread pool tests. +HANDLE finish_event; +const int kWaitCount = 20; + } // namespace namespace sandbox { @@ -142,4 +146,49 @@ TEST(HandleCloserTest, CloseMarkerFiles) { "Failed: " << command; } +void WINAPI ThreadPoolTask(void* event, BOOLEAN timeout) { + static volatile LONG waiters_remaining = kWaitCount; + CHECK(!timeout); + CHECK(::CloseHandle(event)); + if (::InterlockedDecrement(&waiters_remaining) == 0) + CHECK(::SetEvent(finish_event)); +} + +// Run a thread pool inside a sandbox without a CSRSS connection. +SBOX_TESTS_COMMAND int RunThreadPool(int argc, wchar_t **argv) { + HANDLE wait_list[20]; + CHECK(finish_event = ::CreateEvent(NULL, TRUE, FALSE, NULL)); + + // Set up a bunch of waiters. + HANDLE pool = NULL; + for (int i = 0; i < kWaitCount; ++i) { + HANDLE event = ::CreateEvent(NULL, TRUE, FALSE, NULL); + CHECK(event); + CHECK(::RegisterWaitForSingleObject(&pool, event, ThreadPoolTask, event, + INFINITE, WT_EXECUTEONLYONCE)); + wait_list[i] = event; + } + + // Signal all the waiters. + for (int i = 0; i < kWaitCount; ++i) + CHECK(::SetEvent(wait_list[i])); + + CHECK_EQ(::WaitForSingleObject(finish_event, INFINITE), WAIT_OBJECT_0); + CHECK(::CloseHandle(finish_event)); + + return SBOX_TEST_SUCCEEDED; +} + +TEST(HandleCloserTest, RunThreadPool) { + TestRunner runner; + runner.SetTimeout(2000); + runner.SetTestState(AFTER_REVERT); + sandbox::TargetPolicy* policy = runner.GetPolicy(); + + // Sever the CSRSS connection by closing ALPC ports inside the sandbox. + CHECK_EQ(policy->AddKernelObjectToClose(L"ALPC Port", NULL), SBOX_ALL_OK); + + EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(L"RunThreadPool")); +} + } // namespace sandbox diff --git a/sandbox/src/interceptors.h b/sandbox/src/interceptors.h index 2b033b6..3f690ae 100644 --- a/sandbox/src/interceptors.h +++ b/sandbox/src/interceptors.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -41,6 +41,8 @@ enum InterceptorId { // Sync dispatcher: CREATE_EVENT_ID, OPEN_EVENT_ID, + // CSRSS bypass for HandleCloser: + CREATE_THREAD_ID, INTERCEPTOR_MAX_ID }; diff --git a/sandbox/src/interceptors_64.cc b/sandbox/src/interceptors_64.cc index 29d59143..d1b9718 100644 --- a/sandbox/src/interceptors_64.cc +++ b/sandbox/src/interceptors_64.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -68,6 +68,16 @@ NTSTATUS WINAPI TargetNtOpenThreadTokenEx64( open_as_self, handle_attributes, token); } +HANDLE WINAPI TargetCreateThread64(LPSECURITY_ATTRIBUTES thread_attributes, + SIZE_T stack_size, LPTHREAD_START_ROUTINE start_address, + PVOID parameter, DWORD creation_flags, LPDWORD thread_id) { + CreateThreadFunction orig_fn = reinterpret_cast< + CreateThreadFunction>(g_originals[CREATE_THREAD_ID]); + return TargetCreateThread(orig_fn, thread_attributes, stack_size, + start_address, parameter, creation_flags, + thread_id); +} + // ----------------------------------------------------------------------- SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtCreateFile64( diff --git a/sandbox/src/interceptors_64.h b/sandbox/src/interceptors_64.h index 10dff4f..5fc0a4b 100644 --- a/sandbox/src/interceptors_64.h +++ b/sandbox/src/interceptors_64.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -44,6 +44,12 @@ SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenThreadTokenEx64( HANDLE thread, ACCESS_MASK desired_access, BOOLEAN open_as_self, ULONG handle_attributes, PHANDLE token); +// Interception of CreateThread on the child process. +SANDBOX_INTERCEPT HANDLE WINAPI TargetCreateThread64( + LPSECURITY_ATTRIBUTES thread_attributes, SIZE_T stack_size, + LPTHREAD_START_ROUTINE start_address, PVOID parameter, + DWORD creation_flags, LPDWORD thread_id); + // ----------------------------------------------------------------------- // Interceptors handled by the file system dispatcher. diff --git a/sandbox/src/nt_internals.h b/sandbox/src/nt_internals.h index 08bf1a1..e0bc6e3 100644 --- a/sandbox/src/nt_internals.h +++ b/sandbox/src/nt_internals.h @@ -338,6 +338,18 @@ typedef NTSTATUS (WINAPI *NtOpenProcessTokenExFunction) ( IN ULONG HandleAttributes, OUT PHANDLE TokenHandle); +typedef NTSTATUS (WINAPI * RtlCreateUserThreadFunction)( + IN HANDLE Process, + IN PSECURITY_DESCRIPTOR ThreadSecurityDescriptor, + IN BOOLEAN CreateSuspended, + IN ULONG ZeroBits, + IN SIZE_T MaximumStackSize, + IN SIZE_T CommittedStackSize, + IN LPTHREAD_START_ROUTINE StartAddress, + IN PVOID Parameter, + OUT PHANDLE Thread, + OUT PCLIENT_ID ClientId); + // ----------------------------------------------------------------------- // Registry @@ -454,7 +466,7 @@ typedef struct _PUBLIC_OBJECT_BASIC_INFORMATION { ULONG HandleCount; ULONG PointerCount; ULONG Reserved[10]; // reserved for internal use - } PUBLIC_OBJECT_BASIC_INFORMATION, *PPUBLIC_OBJECT_BASIC_INFORMATION; +} PUBLIC_OBJECT_BASIC_INFORMATION, *PPUBLIC_OBJECT_BASIC_INFORMATION; typedef struct __PUBLIC_OBJECT_TYPE_INFORMATION { UNICODE_STRING TypeName; diff --git a/sandbox/src/policy_broker.cc b/sandbox/src/policy_broker.cc index 0a63750..9882f38 100644 --- a/sandbox/src/policy_broker.cc +++ b/sandbox/src/policy_broker.cc @@ -68,6 +68,7 @@ bool SetupNtdllImports(TargetProcess *child) { INIT_GLOBAL_RTL(RtlAnsiStringToUnicodeString); INIT_GLOBAL_RTL(RtlCompareUnicodeString); INIT_GLOBAL_RTL(RtlCreateHeap); + INIT_GLOBAL_RTL(RtlCreateUserThread); INIT_GLOBAL_RTL(RtlDestroyHeap); INIT_GLOBAL_RTL(RtlFreeHeap); INIT_GLOBAL_RTL(_strnicmp); diff --git a/sandbox/src/process_thread_interception.cc b/sandbox/src/process_thread_interception.cc index fdb5644..5a3119f 100644 --- a/sandbox/src/process_thread_interception.cc +++ b/sandbox/src/process_thread_interception.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2006-2011 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. @@ -15,6 +15,8 @@ namespace sandbox { +SANDBOX_INTERCEPT NtExports g_nt; + // Hooks NtOpenThread and proxy the call to the broker if it's trying to // open a thread in the same process. NTSTATUS WINAPI TargetNtOpenThread(NtOpenThreadFunction orig_OpenThread, @@ -396,4 +398,30 @@ BOOL WINAPI TargetCreateProcessA(CreateProcessAFunction orig_CreateProcessA, return FALSE; } +// Creates a thread without registering with CSRSS. This is required if we +// closed the CSRSS ALPC port after lockdown. +HANDLE WINAPI TargetCreateThread(CreateThreadFunction orig_CreateThread, + LPSECURITY_ATTRIBUTES thread_attributes, + SIZE_T stack_size, + LPTHREAD_START_ROUTINE start_address, + PVOID parameter, + DWORD creation_flags, + LPDWORD thread_id) { + HANDLE thread; + PSECURITY_DESCRIPTOR sd = + thread_attributes ? thread_attributes->lpSecurityDescriptor : NULL; + CLIENT_ID client_id; + + NTSTATUS result = g_nt.RtlCreateUserThread(NtCurrentProcess, sd, + creation_flags & CREATE_SUSPENDED, + 0, stack_size, 0, start_address, + parameter, &thread, &client_id); + if (!NT_SUCCESS(result)) + return 0; + + if (thread_id) + *thread_id = HandleToUlong(client_id.UniqueThread); + return thread; +} + } // namespace sandbox diff --git a/sandbox/src/process_thread_interception.h b/sandbox/src/process_thread_interception.h index 6fa3349..e73689d 100644 --- a/sandbox/src/process_thread_interception.h +++ b/sandbox/src/process_thread_interception.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2006-2011 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. @@ -36,6 +36,14 @@ typedef BOOL (WINAPI *CreateProcessAFunction)( LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation); +typedef HANDLE (WINAPI *CreateThreadFunction)( + LPSECURITY_ATTRIBUTES lpThreadAttributes, + SIZE_T dwStackSize, + LPTHREAD_START_ROUTINE lpStartAddress, + PVOID lpParameter, + DWORD dwCreationFlags, + LPDWORD lpThreadId); + // Interception of NtOpenThread on the child process. SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtOpenThread( NtOpenThreadFunction orig_OpenThread, PHANDLE thread, @@ -73,6 +81,13 @@ SANDBOX_INTERCEPT BOOL WINAPI TargetCreateProcessA( LPVOID environment, LPCSTR current_directory, LPSTARTUPINFOA startup_info, LPPROCESS_INFORMATION process_information); +// Interception of CreateThread in kernel32.dll. +SANDBOX_INTERCEPT HANDLE WINAPI TargetCreateThread( + CreateThreadFunction orig_CreateThread, + LPSECURITY_ATTRIBUTES thread_attributes, SIZE_T stack_size, + LPTHREAD_START_ROUTINE start_address, PVOID parameter, + DWORD creation_flags, LPDWORD thread_id); + } // extern "C" } // namespace sandbox diff --git a/sandbox/src/sandbox_nt_types.h b/sandbox/src/sandbox_nt_types.h index 144dbd1..d0d24f8 100644 --- a/sandbox/src/sandbox_nt_types.h +++ b/sandbox/src/sandbox_nt_types.h @@ -25,6 +25,7 @@ struct NtExports { RtlAnsiStringToUnicodeStringFunction RtlAnsiStringToUnicodeString; RtlCompareUnicodeStringFunction RtlCompareUnicodeString; RtlCreateHeapFunction RtlCreateHeap; + RtlCreateUserThreadFunction RtlCreateUserThread; RtlDestroyHeapFunction RtlDestroyHeap; RtlFreeHeapFunction RtlFreeHeap; _strnicmpFunction _strnicmp; diff --git a/sandbox/src/sandbox_policy_base.cc b/sandbox/src/sandbox_policy_base.cc index 8e25b71..e65f648 100644 --- a/sandbox/src/sandbox_policy_base.cc +++ b/sandbox/src/sandbox_policy_base.cc @@ -441,6 +441,9 @@ bool PolicyBase::SetupAllInterceptions(TargetProcess* target) { } } + if (!handle_closer_.SetupHandleInterceptions(&manager)) + return false; + if (!SetupBasicInterceptions(&manager)) return false; |