// Copyright 2020 The Crashpad Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef CRASHPAD_UTIL_MISC_NO_CFI_ICALL_H_ #define CRASHPAD_UTIL_MISC_NO_CFI_ICALL_H_ #include <type_traits> #include <utility> #include "base/compiler_specific.h" #include "build/build_config.h" #if BUILDFLAG(IS_WIN) #include <windows.h> #endif // BUILDFLAG(IS_WIN) namespace crashpad { namespace { template <typename Functor> struct FunctorTraits; FunctorTraits<R (*)(Args...) noexcept>; FunctorTraits<R (*)(Args..., ...) noexcept>; #if BUILDFLAG(IS_WIN) && defined(ARCH_CPU_X86) template <typename R, typename... Args> struct FunctorTraits<R(__stdcall*)(Args...) noexcept> { template <typename... RunArgs> DISABLE_CFI_ICALL static R Invoke(R(__stdcall* function)(Args...), RunArgs&&... args) { return function(std::forward<RunArgs>(args)...); } }; #endif // BUILDFLAG(IS_WIN) && ARCH_CPU_X86 #if __cplusplus >= 201703L // These specializations match functions which are not explicitly declared // noexcept. They must only be present at C++17 when noexcept is part of a // function's type. If they are present earlier, they redefine the // specializations above. FunctorTraits<R (*)(Args...)>; FunctorTraits<R (*)(Args..., ...)>; #if BUILDFLAG(IS_WIN) && defined(ARCH_CPU_X86) template <typename R, typename... Args> struct FunctorTraits<R(__stdcall*)(Args...)> { template <typename... RunArgs> DISABLE_CFI_ICALL static R Invoke(R(__stdcall* function)(Args...), RunArgs&&... args) { return function(std::forward<RunArgs>(args)...); } }; #endif // BUILDFLAG(IS_WIN) && ARCH_CPU_X86 #endif // __cplusplus >= 201703L } // namespace //! \brief Disables cfi-icall for calls made through a function pointer. //! //! Clang provides several Control-Flow-Integrity (CFI) sanitizers, among them, //! cfi-icall, which attempts to verify that the dynamic type of a function //! matches the static type of the function pointer used to call it. //! //! https://clang.llvm.org/docs/ControlFlowIntegrity.html#indirect-function-call-checking //! //! However, cfi-icall does not have enough information to check indirect calls //! to functions in other modules, such as through the pointers returned by //! `dlsym()`. In these cases, CFI aborts the program upon executing the //! indirect call. //! //! This class encapsulates cross-DSO function pointers to disable cfi-icall //! precisely when calling these pointers. template <typename Functor> class NoCfiIcall { … }; } // namespace crashpad #endif // CRASHPAD_UTIL_MISC_NO_CFI_ICALL_H_