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