From 37f2029c42d56e0d7a868eda1e2f2c62897fb9b0 Mon Sep 17 00:00:00 2001 From: "caitkp@chromium.org" Date: Tue, 18 Mar 2014 21:01:10 +0000 Subject: Make chrome_elf use thunks instead of function pointers. 1. Add functionality to ServiceResolverThunk to copy a thunk without patching. 2. Move chrome_elf thunk-handling code to a common location. 3. Use a thunk instead of a f'n ptr for redirects. BUG=334379 Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=255151 Review URL: https://codereview.chromium.org/183833004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@257749 0039d316-1c4b-4281-b951-d872f2087c98 --- sandbox/win/src/service_resolver.h | 9 +++++++++ sandbox/win/src/service_resolver_32.cc | 26 ++++++++++++++++++++++++++ sandbox/win/src/service_resolver_64.cc | 24 ++++++++++++++++++++++++ 3 files changed, 59 insertions(+) (limited to 'sandbox') diff --git a/sandbox/win/src/service_resolver.h b/sandbox/win/src/service_resolver.h index 0089692..20486c9 100644 --- a/sandbox/win/src/service_resolver.h +++ b/sandbox/win/src/service_resolver.h @@ -46,6 +46,15 @@ class ServiceResolverThunk : public ResolverThunk { // Call this to set up ntdll_base_ which will allow for local patches. virtual void AllowLocalPatches(); + // Verifies that the function specified by |target_name| in |target_module| is + // a service and copies the data from that function into |thunk_storage|. If + // |storage_bytes| is too small, then the method fails. + virtual NTSTATUS CopyThunk(const void* target_module, + const char* target_name, + BYTE* thunk_storage, + size_t storage_bytes, + size_t* storage_used); + protected: // The unit test will use this member to allow local patch on a buffer. HMODULE ntdll_base_; diff --git a/sandbox/win/src/service_resolver_32.cc b/sandbox/win/src/service_resolver_32.cc index 2e69dbc..9b8bbf9 100644 --- a/sandbox/win/src/service_resolver_32.cc +++ b/sandbox/win/src/service_resolver_32.cc @@ -179,6 +179,32 @@ size_t ServiceResolverThunk::GetThunkSize() const { return offsetof(ServiceFullThunk, internal_thunk) + GetInternalThunkSize(); } +NTSTATUS ServiceResolverThunk::CopyThunk(const void* target_module, + const char* target_name, + BYTE* thunk_storage, + size_t storage_bytes, + size_t* storage_used) { + NTSTATUS ret = ResolveTarget(target_module, target_name, &target_); + if (!NT_SUCCESS(ret)) + return ret; + + size_t thunk_bytes = GetThunkSize(); + if (storage_bytes < thunk_bytes) + return STATUS_UNSUCCESSFUL; + + ServiceFullThunk* thunk = reinterpret_cast(thunk_storage); + + if (!IsFunctionAService(&thunk->original) && + (!relaxed_ || !SaveOriginalFunction(&thunk->original, thunk_storage))) { + return STATUS_UNSUCCESSFUL; + } + + if (NULL != storage_used) + *storage_used = thunk_bytes; + + return ret; +} + bool ServiceResolverThunk::IsFunctionAService(void* local_thunk) const { ServiceEntry function_code; SIZE_T read; diff --git a/sandbox/win/src/service_resolver_64.cc b/sandbox/win/src/service_resolver_64.cc index 9612418..79c6b16 100644 --- a/sandbox/win/src/service_resolver_64.cc +++ b/sandbox/win/src/service_resolver_64.cc @@ -116,6 +116,30 @@ size_t ServiceResolverThunk::GetThunkSize() const { return sizeof(ServiceFullThunk); } +NTSTATUS ServiceResolverThunk::CopyThunk(const void* target_module, + const char* target_name, + BYTE* thunk_storage, + size_t storage_bytes, + size_t* storage_used) { + NTSTATUS ret = ResolveTarget(target_module, target_name, &target_); + if (!NT_SUCCESS(ret)) + return ret; + + size_t thunk_bytes = GetThunkSize(); + if (storage_bytes < thunk_bytes) + return STATUS_UNSUCCESSFUL; + + ServiceFullThunk* thunk = reinterpret_cast(thunk_storage); + + if (!IsFunctionAService(&thunk->original)) + return STATUS_UNSUCCESSFUL; + + if (NULL != storage_used) + *storage_used = thunk_bytes; + + return ret; +} + bool ServiceResolverThunk::IsFunctionAService(void* local_thunk) const { ServiceFullThunk function_code; SIZE_T read; -- cgit v1.1