xref: /aosp_15_r20/bionic/libc/private/CFIShadow.h (revision 8d67ca893c1523eb926b9080dbe4e2ffd2a27ba1)
1*8d67ca89SAndroid Build Coastguard Worker /*
2*8d67ca89SAndroid Build Coastguard Worker  * Copyright (C) 2016 The Android Open Source Project
3*8d67ca89SAndroid Build Coastguard Worker  *
4*8d67ca89SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*8d67ca89SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*8d67ca89SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*8d67ca89SAndroid Build Coastguard Worker  *
8*8d67ca89SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*8d67ca89SAndroid Build Coastguard Worker  *
10*8d67ca89SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*8d67ca89SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*8d67ca89SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*8d67ca89SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*8d67ca89SAndroid Build Coastguard Worker  * limitations under the License.
15*8d67ca89SAndroid Build Coastguard Worker  */
16*8d67ca89SAndroid Build Coastguard Worker 
17*8d67ca89SAndroid Build Coastguard Worker #ifndef CFI_SHADOW_H
18*8d67ca89SAndroid Build Coastguard Worker #define CFI_SHADOW_H
19*8d67ca89SAndroid Build Coastguard Worker 
20*8d67ca89SAndroid Build Coastguard Worker #include <stdint.h>
21*8d67ca89SAndroid Build Coastguard Worker 
22*8d67ca89SAndroid Build Coastguard Worker #include "platform/bionic/page.h"
23*8d67ca89SAndroid Build Coastguard Worker #include "platform/bionic/macros.h"
24*8d67ca89SAndroid Build Coastguard Worker 
25*8d67ca89SAndroid Build Coastguard Worker constexpr unsigned kLibraryAlignmentBits = 18;
26*8d67ca89SAndroid Build Coastguard Worker constexpr size_t kLibraryAlignment = 1UL << kLibraryAlignmentBits;
27*8d67ca89SAndroid Build Coastguard Worker 
28*8d67ca89SAndroid Build Coastguard Worker // This class defines format of the shadow region for Control Flow Integrity support.
29*8d67ca89SAndroid Build Coastguard Worker // See documentation in http://clang.llvm.org/docs/ControlFlowIntegrityDesign.html#shared-library-support.
30*8d67ca89SAndroid Build Coastguard Worker //
31*8d67ca89SAndroid Build Coastguard Worker // CFI shadow is effectively a very fast and specialized implementation of dladdr: given an address that
32*8d67ca89SAndroid Build Coastguard Worker // belongs to a shared library or an executable, it can find the address of a specific export in that
33*8d67ca89SAndroid Build Coastguard Worker // library (a function called "__cfi_check"). This is only guaranteed to work for
34*8d67ca89SAndroid Build Coastguard Worker // addresses of possible CFI targets inside a library: indirectly called functions and virtual
35*8d67ca89SAndroid Build Coastguard Worker // tables. A random address inside a library may not work in the future (but it does in the current
36*8d67ca89SAndroid Build Coastguard Worker // implementation).
37*8d67ca89SAndroid Build Coastguard Worker //
38*8d67ca89SAndroid Build Coastguard Worker // Implementation is a sparse array of uint16_t where each element describes the location of
39*8d67ca89SAndroid Build Coastguard Worker // __cfi_check for a 2**kShadowGranularity range of memory. Array elements (called "shadow values"
40*8d67ca89SAndroid Build Coastguard Worker // below) are interpreted as follows.
41*8d67ca89SAndroid Build Coastguard Worker //
42*8d67ca89SAndroid Build Coastguard Worker // For an address P and corresponding shadow value V, the address of __cfi_check is calculated as
43*8d67ca89SAndroid Build Coastguard Worker //   align_up(P, 2**kShadowGranularity) - (V - 2) * (2 ** kCfiCheckGranularity)
44*8d67ca89SAndroid Build Coastguard Worker //
45*8d67ca89SAndroid Build Coastguard Worker // Special shadow values:
46*8d67ca89SAndroid Build Coastguard Worker //        0 = kInvalidShadow, this memory range has no valid CFI targets.
47*8d67ca89SAndroid Build Coastguard Worker //        1 = kUncheckedShadow, any address is this memory range is a valid CFI target
48*8d67ca89SAndroid Build Coastguard Worker //
49*8d67ca89SAndroid Build Coastguard Worker // Loader requirement: each aligned 2**kShadowGranularity region of address space may contain at
50*8d67ca89SAndroid Build Coastguard Worker // most one DSO.
51*8d67ca89SAndroid Build Coastguard Worker // Compiler requirement: __cfi_check is aligned at kCfiCheckGranularity.
52*8d67ca89SAndroid Build Coastguard Worker // Compiler requirement: __cfi_check for a given DSO is located below any CFI target for that DSO.
53*8d67ca89SAndroid Build Coastguard Worker class CFIShadow {
54*8d67ca89SAndroid Build Coastguard Worker  public:
55*8d67ca89SAndroid Build Coastguard Worker   static constexpr uintptr_t kShadowGranularity = kLibraryAlignmentBits;
56*8d67ca89SAndroid Build Coastguard Worker   static constexpr uintptr_t kCfiCheckGranularity = 12;
57*8d67ca89SAndroid Build Coastguard Worker 
58*8d67ca89SAndroid Build Coastguard Worker   // Each uint16_t element of the shadow corresponds to this much application memory.
59*8d67ca89SAndroid Build Coastguard Worker   static constexpr uintptr_t kShadowAlign = 1UL << kShadowGranularity;
60*8d67ca89SAndroid Build Coastguard Worker 
61*8d67ca89SAndroid Build Coastguard Worker   // Alignment of __cfi_check.
62*8d67ca89SAndroid Build Coastguard Worker   static constexpr uintptr_t kCfiCheckAlign = 1UL << kCfiCheckGranularity;  // 4K
63*8d67ca89SAndroid Build Coastguard Worker 
64*8d67ca89SAndroid Build Coastguard Worker #if defined (__LP64__)
65*8d67ca89SAndroid Build Coastguard Worker   static constexpr uintptr_t kMaxTargetAddr = 0xffffffffffff;
66*8d67ca89SAndroid Build Coastguard Worker #else
67*8d67ca89SAndroid Build Coastguard Worker   static constexpr uintptr_t kMaxTargetAddr = 0xffffffff;
68*8d67ca89SAndroid Build Coastguard Worker #endif
69*8d67ca89SAndroid Build Coastguard Worker 
70*8d67ca89SAndroid Build Coastguard Worker   // Shadow is 2 -> 2**kShadowGranularity.
71*8d67ca89SAndroid Build Coastguard Worker   static constexpr uintptr_t kShadowSize = kMaxTargetAddr >> (kShadowGranularity - 1);
72*8d67ca89SAndroid Build Coastguard Worker 
73*8d67ca89SAndroid Build Coastguard Worker   // Returns offset inside the shadow region for an address.
MemToShadowOffset(uintptr_t x)74*8d67ca89SAndroid Build Coastguard Worker   static constexpr uintptr_t MemToShadowOffset(uintptr_t x) {
75*8d67ca89SAndroid Build Coastguard Worker     return (x >> kShadowGranularity) << 1;
76*8d67ca89SAndroid Build Coastguard Worker   }
77*8d67ca89SAndroid Build Coastguard Worker 
78*8d67ca89SAndroid Build Coastguard Worker   typedef int (*CFICheckFn)(uint64_t, void *, void *);
79*8d67ca89SAndroid Build Coastguard Worker 
80*8d67ca89SAndroid Build Coastguard Worker  public:
81*8d67ca89SAndroid Build Coastguard Worker   enum ShadowValues : uint16_t {
82*8d67ca89SAndroid Build Coastguard Worker     kInvalidShadow = 0,    // Not a valid CFI target.
83*8d67ca89SAndroid Build Coastguard Worker     kUncheckedShadow = 1,  // Unchecked, valid CFI target.
84*8d67ca89SAndroid Build Coastguard Worker     kRegularShadowMin = 2  // This and all higher values encode a negative offset to __cfi_check in
85*8d67ca89SAndroid Build Coastguard Worker                            // the units of kCfiCheckGranularity, starting with 0 at
86*8d67ca89SAndroid Build Coastguard Worker                            // kRegularShadowMin.
87*8d67ca89SAndroid Build Coastguard Worker   };
88*8d67ca89SAndroid Build Coastguard Worker };
89*8d67ca89SAndroid Build Coastguard Worker 
90*8d67ca89SAndroid Build Coastguard Worker #endif  // CFI_SHADOW_H
91