This repository has been archived by the owner on Nov 8, 2023. It is now read-only.
mirrored from https://android.googlesource.com/platform/bionic.git
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
25 changed files
with
791 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,6 +29,7 @@ | |
#ifndef __DLFCN_H__ | ||
#define __DLFCN_H__ | ||
|
||
#include <stdint.h> | ||
#include <sys/cdefs.h> | ||
|
||
__BEGIN_DECLS | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
/* | ||
* Copyright (C) 2016 The Android Open Source Project | ||
* | ||
* 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 CFI_SHADOW_H | ||
#define CFI_SHADOW_H | ||
|
||
#include <stdint.h> | ||
|
||
#include "private/bionic_page.h" | ||
#include "private/bionic_macros.h" | ||
|
||
constexpr unsigned kLibraryAlignmentBits = 18; | ||
constexpr size_t kLibraryAlignment = 1UL << kLibraryAlignmentBits; | ||
|
||
// This class defines format of the shadow region for Control Flow Integrity support. | ||
// See documentation in http://clang.llvm.org/docs/ControlFlowIntegrityDesign.html#shared-library-support. | ||
// | ||
// CFI shadow is effectively a very fast and specialized implementation of dladdr: given an address that | ||
// belongs to a shared library or an executable, it can find the address of a specific export in that | ||
// library (a function called "__cfi_check"). This is only guaranteed to work for | ||
// addresses of possible CFI targets inside a library: indirectly called functions and virtual | ||
// tables. A random address inside a library may not work in the future (but it does in the current | ||
// implementation). | ||
// | ||
// Implementation is a sparse array of uint16_t where each element describes the location of | ||
// __cfi_check for a 2**kShadowGranularity range of memory. Array elements (called "shadow values" | ||
// below) are interpreted as follows. | ||
// | ||
// For an address P and corresponding shadow value V, the address of __cfi_check is calculated as | ||
// align_up(P, 2**kShadowGranularity) - (V - 2) * (2 ** kCfiCheckGranularity) | ||
// | ||
// Special shadow values: | ||
// 0 = kInvalidShadow, this memory range has no valid CFI targets. | ||
// 1 = kUncheckedShadow, any address is this memory range is a valid CFI target | ||
// | ||
// Loader requirement: each aligned 2**kShadowGranularity region of address space may contain at | ||
// most one DSO. | ||
// Compiler requirement: __cfi_check is aligned at kCfiCheckGranularity. | ||
// Compiler requirement: __cfi_check for a given DSO is located below any CFI target for that DSO. | ||
class CFIShadow { | ||
public: | ||
static constexpr uintptr_t kShadowGranularity = kLibraryAlignmentBits; | ||
static constexpr uintptr_t kCfiCheckGranularity = 12; | ||
|
||
// Each uint16_t element of the shadow corresponds to this much application memory. | ||
static constexpr uintptr_t kShadowAlign = 1UL << kShadowGranularity; | ||
|
||
// Alignment of __cfi_check. | ||
static constexpr uintptr_t kCfiCheckAlign = 1UL << kCfiCheckGranularity; // 4K | ||
|
||
#if defined(__aarch64__) | ||
static constexpr uintptr_t kMaxTargetAddr = 0x7fffffffff; | ||
#elif defined (__LP64__) | ||
static constexpr uintptr_t kMaxTargetAddr = 0x7fffffffffff; | ||
#else | ||
static constexpr uintptr_t kMaxTargetAddr = 0xffffffff; | ||
#endif | ||
|
||
// Shadow is 2 -> 2**kShadowGranularity. | ||
static constexpr uintptr_t kShadowSize = | ||
align_up((kMaxTargetAddr >> (kShadowGranularity - 1)), PAGE_SIZE); | ||
|
||
// Returns offset inside the shadow region for an address. | ||
static constexpr uintptr_t MemToShadowOffset(uintptr_t x) { | ||
return (x >> kShadowGranularity) << 1; | ||
} | ||
|
||
typedef int (*CFICheckFn)(uint64_t, void *, void *); | ||
|
||
public: | ||
enum ShadowValues : uint16_t { | ||
kInvalidShadow = 0, // Not a valid CFI target. | ||
kUncheckedShadow = 1, // Unchecked, valid CFI target. | ||
kRegularShadowMin = 2 // This and all higher values encode a negative offset to __cfi_check in | ||
// the units of kCfiCheckGranularity, starting with 0 at | ||
// kRegularShadowMin. | ||
}; | ||
}; | ||
|
||
#endif // CFI_SHADOW_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
/* | ||
* Copyright (C) 2016 The Android Open Source Project | ||
* | ||
* 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. | ||
*/ | ||
|
||
#include <sys/mman.h> | ||
|
||
#include "private/CFIShadow.h" | ||
|
||
__attribute__((__weak__, visibility("default"))) extern "C" void __loader_cfi_fail( | ||
uint64_t CallSiteTypeId, void* Ptr, void* DiagData, void* CallerPc); | ||
|
||
// Base address of the CFI shadow. Passed down from the linker in __cfi_init() | ||
// and does not change after that. The contents of the shadow change in | ||
// dlopen/dlclose. | ||
static struct { | ||
uintptr_t v; | ||
char padding[PAGE_SIZE - sizeof(v)]; | ||
} shadow_base_storage alignas(PAGE_SIZE); | ||
|
||
extern "C" uintptr_t* __cfi_init(uintptr_t shadow_base) { | ||
shadow_base_storage.v = shadow_base; | ||
static_assert(sizeof(shadow_base_storage) == PAGE_SIZE, ""); | ||
mprotect(&shadow_base_storage, PAGE_SIZE, PROT_READ); | ||
return &shadow_base_storage.v; | ||
} | ||
|
||
static uint16_t shadow_load(void* p) { | ||
uintptr_t addr = reinterpret_cast<uintptr_t>(p); | ||
uintptr_t ofs = CFIShadow::MemToShadowOffset(addr); | ||
if (ofs > CFIShadow::kShadowSize) return CFIShadow::kInvalidShadow; | ||
return *reinterpret_cast<uint16_t*>(shadow_base_storage.v + ofs); | ||
} | ||
|
||
static uintptr_t cfi_check_addr(uint16_t v, void* Ptr) { | ||
uintptr_t addr = reinterpret_cast<uintptr_t>(Ptr); | ||
uintptr_t aligned_addr = align_up(addr, CFIShadow::kShadowAlign); | ||
uintptr_t p = aligned_addr - (static_cast<uintptr_t>(v - CFIShadow::kRegularShadowMin) | ||
<< CFIShadow::kCfiCheckGranularity); | ||
#ifdef __arm__ | ||
// Assume Thumb encoding. FIXME: force thumb at compile time? | ||
p++; | ||
#endif | ||
return p; | ||
} | ||
|
||
static inline void cfi_slowpath_common(uint64_t CallSiteTypeId, void* Ptr, void* DiagData) { | ||
uint16_t v = shadow_load(Ptr); | ||
switch (v) { | ||
case CFIShadow::kInvalidShadow: | ||
__loader_cfi_fail(CallSiteTypeId, Ptr, DiagData, __builtin_return_address(0)); | ||
break; | ||
case CFIShadow::kUncheckedShadow: | ||
break; | ||
default: | ||
reinterpret_cast<CFIShadow::CFICheckFn>(cfi_check_addr(v, Ptr))(CallSiteTypeId, Ptr, DiagData); | ||
} | ||
} | ||
|
||
extern "C" void __cfi_slowpath(uint64_t CallSiteTypeId, void* Ptr) { | ||
cfi_slowpath_common(CallSiteTypeId, Ptr, nullptr); | ||
} | ||
|
||
extern "C" void __cfi_slowpath_diag(uint64_t CallSiteTypeId, void* Ptr, void* DiagData) { | ||
cfi_slowpath_common(CallSiteTypeId, Ptr, DiagData); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.