diff options
author | Jakub Pawlowski <jpawlowski@google.com> | 2017-04-05 09:22:29 -0700 |
---|---|---|
committer | Jakub Pawlowski <jpawlowski@google.com> | 2018-10-12 19:25:59 +0200 |
commit | e280f12834190c543be1ad4fddf6a642f65b998a (patch) | |
tree | a398a922d546c95123c3cc6e78091bef5378969b /base/memory/protected_memory_cfi.h | |
parent | 23b27ba5c54bf6368980117d91bc51c4495e2c50 (diff) | |
download | libchrome-e280f12834190c543be1ad4fddf6a642f65b998a.tar.gz |
Uprev libchrome to r576279 (1/many)
This patch brings the latest and greatest features of libchrome to
android. It contains ~2600 patches.
Reason for uprev: libbluetooth want to use some of the most recent
features avaliable.
Test: libchrome_test
Change-Id: Iccdec267948daab29e6328694f4c7d2f71ea26ca
Merged-In: Iccdec267948daab29e6328694f4c7d2f71ea26ca
Diffstat (limited to 'base/memory/protected_memory_cfi.h')
-rw-r--r-- | base/memory/protected_memory_cfi.h | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/base/memory/protected_memory_cfi.h b/base/memory/protected_memory_cfi.h new file mode 100644 index 0000000000..a90023bc81 --- /dev/null +++ b/base/memory/protected_memory_cfi.h @@ -0,0 +1,86 @@ +// Copyright 2017 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. + +// Helper routines to call function pointers stored in protected memory with +// Control Flow Integrity indirect call checking disabled. Some indirect calls, +// e.g. dynamically resolved symbols in another DSO, can not be accounted for by +// CFI-icall. These routines allow those symbols to be called without CFI-icall +// checking safely by ensuring that they are placed in protected memory. + +#ifndef BASE_MEMORY_PROTECTED_MEMORY_CFI_H_ +#define BASE_MEMORY_PROTECTED_MEMORY_CFI_H_ + +#include <utility> + +#include "base/cfi_buildflags.h" +#include "base/compiler_specific.h" +#include "base/macros.h" +#include "base/memory/protected_memory.h" +#include "build/build_config.h" + +#if BUILDFLAG(CFI_ICALL_CHECK) && !PROTECTED_MEMORY_ENABLED +#error "CFI-icall enabled for platform without protected memory support" +#endif // BUILDFLAG(CFI_ICALL_CHECK) && !PROTECTED_MEMORY_ENABLED + +namespace base { +namespace internal { + +// This class is used to exempt calls to function pointers stored in +// ProtectedMemory from cfi-icall checking. It's not secure to use directly, it +// should only be used by the UnsanitizedCfiCall() functions below. Given an +// UnsanitizedCfiCall object, you can use operator() to call the encapsulated +// function pointer without cfi-icall checking. +template <typename FunctionType> +class UnsanitizedCfiCall { + public: + explicit UnsanitizedCfiCall(FunctionType function) : function_(function) {} + UnsanitizedCfiCall(UnsanitizedCfiCall&&) = default; + + template <typename... Args> + NO_SANITIZE("cfi-icall") + auto operator()(Args&&... args) { + return function_(std::forward<Args>(args)...); + } + + private: + FunctionType function_; + + DISALLOW_IMPLICIT_CONSTRUCTORS(UnsanitizedCfiCall); +}; + +} // namespace internal + +// These functions can be used to call function pointers in ProtectedMemory +// without cfi-icall checking. They are intended to be used to create an +// UnsanitizedCfiCall object and immediately call it. UnsanitizedCfiCall objects +// should not initialized directly or stored because they hold a function +// pointer that will be called without CFI-icall checking in mutable memory. The +// functions can be used as shown below: + +// ProtectedMemory<void (*)(int)> p; +// UnsanitizedCfiCall(p)(5); /* In place of (*p)(5); */ + +template <typename T> +auto UnsanitizedCfiCall(const ProtectedMemory<T>& PM) { +#if PROTECTED_MEMORY_ENABLED + DCHECK(&PM >= ProtectedMemoryStart && &PM < ProtectedMemoryEnd); +#endif // PROTECTED_MEMORY_ENABLED + return internal::UnsanitizedCfiCall<T>(*PM); +} + +// struct S { void (*fp)(int); } s; +// ProtectedMemory<S> p; +// UnsanitizedCfiCall(p, &S::fp)(5); /* In place of p->fp(5); */ + +template <typename T, typename Member> +auto UnsanitizedCfiCall(const ProtectedMemory<T>& PM, Member member) { +#if PROTECTED_MEMORY_ENABLED + DCHECK(&PM >= ProtectedMemoryStart && &PM < ProtectedMemoryEnd); +#endif // PROTECTED_MEMORY_ENABLED + return internal::UnsanitizedCfiCall<decltype(*PM.*member)>(*PM.*member); +} + +} // namespace base + +#endif // BASE_MEMORY_PROTECTED_MEMORY_CFI_H_ |