Restructure sandbox code to reduce dependencies pulled in by intercept code.

BUG=322710
TEST=NONE

Review URL: https://codereview.chromium.org/84063004

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@238538 0039d316-1c4b-4281-b951-d872f2087c98
parent 6e6a9edf
...@@ -93,6 +93,7 @@ ...@@ -93,6 +93,7 @@
'src/restricted_token.cc', 'src/restricted_token.cc',
'src/restricted_token.h', 'src/restricted_token.h',
'src/sandbox_factory.h', 'src/sandbox_factory.h',
'src/sandbox_globals.cc',
'src/sandbox_nt_types.h', 'src/sandbox_nt_types.h',
'src/sandbox_nt_util.cc', 'src/sandbox_nt_util.cc',
'src/sandbox_nt_util.h', 'src/sandbox_nt_util.h',
......
// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. // Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
...@@ -601,6 +601,11 @@ typedef size_t (__cdecl *strlenFunction)( ...@@ -601,6 +601,11 @@ typedef size_t (__cdecl *strlenFunction)(
typedef size_t (__cdecl *wcslenFunction)( typedef size_t (__cdecl *wcslenFunction)(
IN const wchar_t* _Str); IN const wchar_t* _Str);
typedef void* (__cdecl *memcpyFunction)(
IN void* dest,
IN const void* src,
IN size_t count);
typedef NTSTATUS (WINAPI *RtlAnsiStringToUnicodeStringFunction)( typedef NTSTATUS (WINAPI *RtlAnsiStringToUnicodeStringFunction)(
IN OUT PUNICODE_STRING DestinationString, IN OUT PUNICODE_STRING DestinationString,
IN PANSI_STRING SourceString, IN PANSI_STRING SourceString,
......
...@@ -73,6 +73,7 @@ bool SetupNtdllImports(TargetProcess *child) { ...@@ -73,6 +73,7 @@ bool SetupNtdllImports(TargetProcess *child) {
INIT_GLOBAL_RTL(_strnicmp); INIT_GLOBAL_RTL(_strnicmp);
INIT_GLOBAL_RTL(strlen); INIT_GLOBAL_RTL(strlen);
INIT_GLOBAL_RTL(wcslen); INIT_GLOBAL_RTL(wcslen);
INIT_GLOBAL_RTL(memcpy);
#ifndef NDEBUG #ifndef NDEBUG
// Verify that the structure is fully initialized. // Verify that the structure is fully initialized.
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
namespace sandbox { namespace sandbox {
// The section for IPC and policy. // The section for IPC and policy.
SANDBOX_INTERCEPT HANDLE g_shared_section = NULL; SANDBOX_INTERCEPT HANDLE g_shared_section;
static bool s_is_broker = false; static bool s_is_broker = false;
......
// Copyright 2013 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.
#include <windows.h>
#include "sandbox/win/src/sandbox_nt_types.h"
#include "sandbox/win/src/sandbox_types.h"
namespace sandbox {
// The section for IPC and policy.
SANDBOX_INTERCEPT HANDLE g_shared_section = NULL;
// This is the list of all imported symbols from ntdll.dll.
SANDBOX_INTERCEPT NtExports g_nt = {};
} // namespace sandbox
...@@ -31,6 +31,7 @@ struct NtExports { ...@@ -31,6 +31,7 @@ struct NtExports {
_strnicmpFunction _strnicmp; _strnicmpFunction _strnicmp;
strlenFunction strlen; strlenFunction strlen;
wcslenFunction wcslen; wcslenFunction wcslen;
memcpyFunction memcpy;
}; };
// This is the value used for the ntdll level allocator. // This is the value used for the ntdll level allocator.
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
namespace sandbox { namespace sandbox {
// This is the list of all imported symbols from ntdll.dll. // This is the list of all imported symbols from ntdll.dll.
SANDBOX_INTERCEPT NtExports g_nt = { NULL }; SANDBOX_INTERCEPT NtExports g_nt;
} // namespace sandbox } // namespace sandbox
...@@ -208,15 +208,7 @@ bool ValidParameter(void* buffer, size_t size, RequiredAccess intent) { ...@@ -208,15 +208,7 @@ bool ValidParameter(void* buffer, size_t size, RequiredAccess intent) {
NTSTATUS CopyData(void* destination, const void* source, size_t bytes) { NTSTATUS CopyData(void* destination, const void* source, size_t bytes) {
NTSTATUS ret = STATUS_SUCCESS; NTSTATUS ret = STATUS_SUCCESS;
__try { __try {
if (SandboxFactory::GetTargetServices()->GetState()->InitCalled()) { g_nt.memcpy(destination, source, bytes);
memcpy(destination, source, bytes);
} else {
const char* from = reinterpret_cast<const char*>(source);
char* to = reinterpret_cast<char*>(destination);
for (size_t i = 0; i < bytes; i++) {
to[i] = from[i];
}
}
} __except(EXCEPTION_EXECUTE_HANDLER) { } __except(EXCEPTION_EXECUTE_HANDLER) {
ret = GetExceptionCode(); ret = GetExceptionCode();
} }
......
...@@ -45,6 +45,8 @@ void __cdecl operator delete(void* memory, void* buffer, ...@@ -45,6 +45,8 @@ void __cdecl operator delete(void* memory, void* buffer,
#define VERIFY_SUCCESS(action) (action) #define VERIFY_SUCCESS(action) (action)
#endif #endif
#define CHECK_NT(condition) { (condition) ? (void)0 : __debugbreak(); }
#define NOTREACHED_NT() DCHECK_NT(false) #define NOTREACHED_NT() DCHECK_NT(false)
namespace sandbox { namespace sandbox {
...@@ -94,7 +96,6 @@ enum RequiredAccess { ...@@ -94,7 +96,6 @@ enum RequiredAccess {
// write) // write)
bool ValidParameter(void* buffer, size_t size, RequiredAccess intent); bool ValidParameter(void* buffer, size_t size, RequiredAccess intent);
// Copies data from a user buffer to our buffer. Returns the operation status. // Copies data from a user buffer to our buffer. Returns the operation status.
NTSTATUS CopyData(void* destination, const void* source, size_t bytes); NTSTATUS CopyData(void* destination, const void* source, size_t bytes);
......
...@@ -28,11 +28,11 @@ void InitObjectAttribs(const std::wstring& name, ...@@ -28,11 +28,11 @@ void InitObjectAttribs(const std::wstring& name,
if (!RtlInitUnicodeString) { if (!RtlInitUnicodeString) {
HMODULE ntdll = ::GetModuleHandle(kNtdllName); HMODULE ntdll = ::GetModuleHandle(kNtdllName);
RtlInitUnicodeString = reinterpret_cast<RtlInitUnicodeStringFunction>( RtlInitUnicodeString = reinterpret_cast<RtlInitUnicodeStringFunction>(
GetProcAddress(ntdll, "RtlInitUnicodeString")); GetProcAddress(ntdll, "RtlInitUnicodeString"));
DCHECK(RtlInitUnicodeString); DCHECK(RtlInitUnicodeString);
} }
RtlInitUnicodeString(uni_name, name.c_str()); RtlInitUnicodeString(uni_name, name.c_str());
InitializeObjectAttributes(obj_attr, uni_name, attributes, root, NULL); InitializeObjectAttributes(obj_attr, uni_name, attributes, root, NULL);
} }
}; // namespace sandbox } // namespace sandbox
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef SANDBOX_SRC_SANDBOX_UTILS_H__ #ifndef SANDBOX_SRC_SANDBOX_UTILS_H_
#define SANDBOX_SRC_SANDBOX_UTILS_H__ #define SANDBOX_SRC_SANDBOX_UTILS_H_
#include <windows.h> #include <windows.h>
#include <string> #include <string>
...@@ -22,6 +22,6 @@ void InitObjectAttribs(const std::wstring& name, ...@@ -22,6 +22,6 @@ void InitObjectAttribs(const std::wstring& name,
OBJECT_ATTRIBUTES* obj_attr, OBJECT_ATTRIBUTES* obj_attr,
UNICODE_STRING* uni_name); UNICODE_STRING* uni_name);
}; // namespace sandbox } // namespace sandbox
#endif // SANDBOX_SRC_SANDBOX_UTILS_H__ #endif // SANDBOX_SRC_SANDBOX_UTILS_H_
// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. // Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "sandbox/win/src/service_resolver.h" #include "sandbox/win/src/service_resolver.h"
#include "base/logging.h"
#include "base/win/pe_image.h" #include "base/win/pe_image.h"
#include "sandbox/win/src/internal_types.h"
#include "sandbox/win/src/sandbox_nt_util.h"
namespace sandbox { namespace sandbox {
...@@ -24,7 +25,6 @@ NTSTATUS ServiceResolverThunk::ResolveInterceptor( ...@@ -24,7 +25,6 @@ NTSTATUS ServiceResolverThunk::ResolveInterceptor(
NTSTATUS ServiceResolverThunk::ResolveTarget(const void* module, NTSTATUS ServiceResolverThunk::ResolveTarget(const void* module,
const char* function_name, const char* function_name,
void** address) { void** address) {
DCHECK(address);
if (NULL == module) if (NULL == module)
return STATUS_UNSUCCESSFUL; return STATUS_UNSUCCESSFUL;
...@@ -32,11 +32,15 @@ NTSTATUS ServiceResolverThunk::ResolveTarget(const void* module, ...@@ -32,11 +32,15 @@ NTSTATUS ServiceResolverThunk::ResolveTarget(const void* module,
*address = module_image.GetProcAddress(function_name); *address = module_image.GetProcAddress(function_name);
if (NULL == *address) { if (NULL == *address) {
NOTREACHED(); NOTREACHED_NT();
return STATUS_UNSUCCESSFUL; return STATUS_UNSUCCESSFUL;
} }
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
void ServiceResolverThunk::AllowLocalPatches() {
ntdll_base_ = ::GetModuleHandle(kNtdllName);
}
} // namespace sandbox } // namespace sandbox
...@@ -43,6 +43,9 @@ class ServiceResolverThunk : public ResolverThunk { ...@@ -43,6 +43,9 @@ class ServiceResolverThunk : public ResolverThunk {
// Implementation of Resolver::GetThunkSize. // Implementation of Resolver::GetThunkSize.
virtual size_t GetThunkSize() const; virtual size_t GetThunkSize() const;
// Call this to set up ntdll_base_ which will allow for local patches.
virtual void AllowLocalPatches();
protected: protected:
// The unit test will use this member to allow local patch on a buffer. // The unit test will use this member to allow local patch on a buffer.
HMODULE ntdll_base_; HMODULE ntdll_base_;
......
...@@ -4,8 +4,8 @@ ...@@ -4,8 +4,8 @@
#include "sandbox/win/src/service_resolver.h" #include "sandbox/win/src/service_resolver.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "sandbox/win/src/sandbox_nt_util.h"
#include "sandbox/win/src/win_utils.h" #include "sandbox/win/src/win_utils.h"
namespace { namespace {
...@@ -144,14 +144,14 @@ bool ServiceResolverThunk::IsFunctionAService(void* local_thunk) const { ...@@ -144,14 +144,14 @@ bool ServiceResolverThunk::IsFunctionAService(void* local_thunk) const {
NTSTATUS ServiceResolverThunk::PerformPatch(void* local_thunk, NTSTATUS ServiceResolverThunk::PerformPatch(void* local_thunk,
void* remote_thunk) { void* remote_thunk) {
ServiceFullThunk* full_local_thunk = reinterpret_cast<ServiceFullThunk*>( ServiceFullThunk* full_local_thunk =
local_thunk); reinterpret_cast<ServiceFullThunk*>(local_thunk);
ServiceFullThunk* full_remote_thunk = reinterpret_cast<ServiceFullThunk*>( ServiceFullThunk* full_remote_thunk =
remote_thunk); reinterpret_cast<ServiceFullThunk*>(remote_thunk);
// Patch the original code. // Patch the original code.
ServiceEntry local_service; ServiceEntry local_service;
DCHECK_GE(GetInternalThunkSize(), sizeof(local_service)); DCHECK_NT(GetInternalThunkSize() >= sizeof(local_service));
if (!SetInternalThunk(&local_service, sizeof(local_service), NULL, if (!SetInternalThunk(&local_service, sizeof(local_service), NULL,
interceptor_)) interceptor_))
return STATUS_UNSUCCESSFUL; return STATUS_UNSUCCESSFUL;
...@@ -181,12 +181,12 @@ NTSTATUS ServiceResolverThunk::PerformPatch(void* local_thunk, ...@@ -181,12 +181,12 @@ NTSTATUS ServiceResolverThunk::PerformPatch(void* local_thunk,
} }
bool Wow64ResolverThunk::IsFunctionAService(void* local_thunk) const { bool Wow64ResolverThunk::IsFunctionAService(void* local_thunk) const {
NOTREACHED(); NOTREACHED_NT();
return false; return false;
} }
bool Win2kResolverThunk::IsFunctionAService(void* local_thunk) const { bool Win2kResolverThunk::IsFunctionAService(void* local_thunk) const {
NOTREACHED(); NOTREACHED_NT();
return false; return false;
} }
......
...@@ -44,7 +44,7 @@ class ResolverThunkTest : public T { ...@@ -44,7 +44,7 @@ class ResolverThunkTest : public T {
EXPECT_EQ(STATUS_SUCCESS, ret); EXPECT_EQ(STATUS_SUCCESS, ret);
target_ = fake_target_; target_ = fake_target_;
ntdll_base_ = ::GetModuleHandle(L"ntdll.dll");
return ret; return ret;
}; };
...@@ -108,6 +108,8 @@ NTSTATUS PatchNtdllWithResolver(const char* function, bool relaxed, ...@@ -108,6 +108,8 @@ NTSTATUS PatchNtdllWithResolver(const char* function, bool relaxed,
scoped_ptr<char[]> thunk(new char[thunk_size]); scoped_ptr<char[]> thunk(new char[thunk_size]);
size_t used; size_t used;
resolver->AllowLocalPatches();
NTSTATUS ret = resolver->Setup(ntdll_base, NULL, function, NULL, NTSTATUS ret = resolver->Setup(ntdll_base, NULL, function, NULL,
function_entry, thunk.get(), thunk_size, function_entry, thunk.get(), thunk_size,
&used); &used);
...@@ -224,4 +226,41 @@ TEST(ServiceResolverTest, MultiplePatchedServices) { ...@@ -224,4 +226,41 @@ TEST(ServiceResolverTest, MultiplePatchedServices) {
#endif #endif
} }
TEST(ServiceResolverTest, LocalPatchesAllowed) {
sandbox::ServiceResolverThunk* resolver = GetTestResolver(true);
HMODULE ntdll_base = ::GetModuleHandle(L"ntdll.dll");
ASSERT_TRUE(NULL != ntdll_base);
const char kFunctionName[] = "NtClose";
void* target = ::GetProcAddress(ntdll_base, kFunctionName);
ASSERT_TRUE(NULL != target);
BYTE service[50];
memcpy(service, target, sizeof(service));
static_cast<WinXpResolverTest*>(resolver)->set_target(service);
// Any pointer will do as an interception_entry_point
void* function_entry = resolver;
size_t thunk_size = resolver->GetThunkSize();
scoped_ptr<char[]> thunk(new char[thunk_size]);
size_t used;
NTSTATUS ret = STATUS_UNSUCCESSFUL;
// First try patching without having allowed local patches.
ret = resolver->Setup(ntdll_base, NULL, kFunctionName, NULL,
function_entry, thunk.get(), thunk_size,
&used);
EXPECT_FALSE(NT_SUCCESS(ret));
// Now allow local patches and check that things work.
resolver->AllowLocalPatches();
ret = resolver->Setup(ntdll_base, NULL, kFunctionName, NULL,
function_entry, thunk.get(), thunk_size,
&used);
EXPECT_EQ(STATUS_SUCCESS, ret);
}
} // namespace } // namespace
...@@ -6,10 +6,10 @@ ...@@ -6,10 +6,10 @@
#include <map> #include <map>
#include "base/logging.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "sandbox/win/src/internal_types.h" #include "sandbox/win/src/internal_types.h"
#include "sandbox/win/src/nt_internals.h" #include "sandbox/win/src/nt_internals.h"
#include "sandbox/win/src/sandbox_nt_util.h"
namespace { namespace {
...@@ -104,7 +104,7 @@ DWORD IsReparsePoint(const std::wstring& full_path, bool* result) { ...@@ -104,7 +104,7 @@ DWORD IsReparsePoint(const std::wstring& full_path, bool* result) {
error != ERROR_PATH_NOT_FOUND && error != ERROR_PATH_NOT_FOUND &&
error != ERROR_INVALID_NAME) { error != ERROR_INVALID_NAME) {
// Unexpected error. // Unexpected error.
NOTREACHED(); NOTREACHED_NT();
return error; return error;
} }
} else if (FILE_ATTRIBUTE_REPARSE_POINT & attributes) { } else if (FILE_ATTRIBUTE_REPARSE_POINT & attributes) {
...@@ -124,7 +124,7 @@ DWORD IsReparsePoint(const std::wstring& full_path, bool* result) { ...@@ -124,7 +124,7 @@ DWORD IsReparsePoint(const std::wstring& full_path, bool* result) {
// we'll get from |handle| will be \device\harddiskvolume1\some\foo\bar. // we'll get from |handle| will be \device\harddiskvolume1\some\foo\bar.
bool SameObject(HANDLE handle, const wchar_t* full_path) { bool SameObject(HANDLE handle, const wchar_t* full_path) {
std::wstring path(full_path); std::wstring path(full_path);
DCHECK(!path.empty()); DCHECK_NT(!path.empty());
// Check if it's a pipe. // Check if it's a pipe.
if (IsPipe(path)) if (IsPipe(path))
...@@ -319,5 +319,5 @@ void ResolveNTFunctionPtr(const char* name, void* ptr) { ...@@ -319,5 +319,5 @@ void ResolveNTFunctionPtr(const char* name, void* ptr) {
*function_ptr = ::GetProcAddress(ntdll, name); *function_ptr = ::GetProcAddress(ntdll, name);
} }
CHECK(*function_ptr); CHECK_NT(*function_ptr);
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment