summaryrefslogtreecommitdiff
path: root/base/memory/protected_memory_cfi.h
diff options
context:
space:
mode:
authorJakub Pawlowski <jpawlowski@google.com>2017-04-05 09:22:29 -0700
committerJakub Pawlowski <jpawlowski@google.com>2018-10-12 19:25:59 +0200
commite280f12834190c543be1ad4fddf6a642f65b998a (patch)
treea398a922d546c95123c3cc6e78091bef5378969b /base/memory/protected_memory_cfi.h
parent23b27ba5c54bf6368980117d91bc51c4495e2c50 (diff)
downloadlibchrome-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.h86
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_