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