Evgenii Stepanov | 0a3637d | 2016-07-06 13:20:59 -0700 | [diff] [blame^] | 1 | #include <assert.h> |
| 2 | #include <stdint.h> |
| 3 | #include <stdlib.h> |
| 4 | |
| 5 | // This library is built for all targets, including host tests, so __cfi_slowpath may not be |
| 6 | // present. But it is only used in the bionic loader tests. |
| 7 | extern "C" __attribute__((weak)) void __cfi_slowpath(uint64_t, void*); |
| 8 | |
| 9 | static int g_count; |
| 10 | static uint64_t g_last_type_id; |
| 11 | static void* g_last_address; |
| 12 | static void* g_last_diag; |
| 13 | |
| 14 | extern "C" { |
| 15 | |
| 16 | // Mock a CFI-enabled library without relying on the compiler. |
| 17 | __attribute__((aligned(4096))) void __cfi_check(uint64_t CallSiteTypeId, void* TargetAddr, |
| 18 | void* Diag) { |
| 19 | ++g_count; |
| 20 | g_last_type_id = CallSiteTypeId; |
| 21 | g_last_address = TargetAddr; |
| 22 | g_last_diag = Diag; |
| 23 | } |
| 24 | |
| 25 | int get_count() { |
| 26 | return g_count; |
| 27 | } |
| 28 | |
| 29 | uint64_t get_last_type_id() { |
| 30 | return g_last_type_id; |
| 31 | } |
| 32 | |
| 33 | void* get_last_address() { |
| 34 | return g_last_address; |
| 35 | } |
| 36 | |
| 37 | void* get_last_diag() { |
| 38 | return g_last_diag; |
| 39 | } |
| 40 | |
| 41 | void* get_global_address() { |
| 42 | return &g_count; |
| 43 | } |
| 44 | } |
| 45 | |
| 46 | // Check that CFI is set up in module constructors and destructors. |
| 47 | struct A { |
| 48 | void check_cfi_self() { |
| 49 | g_last_type_id = 0; |
| 50 | assert(&__cfi_slowpath); |
| 51 | // CFI check for an invalid address. Normally, this would kill the process by routing the call |
| 52 | // back to the calling module's __cfi_check, which does the right thing based on |
| 53 | // -fsanitize-recover / -fsanitize-trap. But this module has custom __cfi_check that does not do |
| 54 | // any of that, so the result looks like a passing check. |
| 55 | int zz; |
| 56 | __cfi_slowpath(13, static_cast<void*>(&zz)); |
| 57 | assert(g_last_type_id == 13); |
| 58 | // CFI check for a libc function. This never goes into this module's __cfi_check, and must pass. |
| 59 | __cfi_slowpath(14, reinterpret_cast<void*>(&exit)); |
| 60 | assert(g_last_type_id == 13); |
| 61 | } |
| 62 | A() { |
| 63 | check_cfi_self(); |
| 64 | } |
| 65 | ~A() { |
| 66 | check_cfi_self(); |
| 67 | } |
| 68 | } a; |