1570af302Sopenharmony_ci#include <stdlib.h> 2570af302Sopenharmony_ci#include <signal.h> 3570af302Sopenharmony_ci#include "syscall.h" 4570af302Sopenharmony_ci#include "pthread_impl.h" 5570af302Sopenharmony_ci#include "atomic.h" 6570af302Sopenharmony_ci#include "lock.h" 7570af302Sopenharmony_ci#include "ksigaction.h" 8570af302Sopenharmony_ci#if defined(MUSL_AARCH64_ARCH) 9570af302Sopenharmony_ci#include <stdint.h> 10570af302Sopenharmony_ci#include <stdio.h> 11570af302Sopenharmony_ci#include <inttypes.h> 12570af302Sopenharmony_ci#include <info/fatal_message.h> 13570af302Sopenharmony_ci 14570af302Sopenharmony_ci#define MESSAGE_BUFFER_SIZE 512 15570af302Sopenharmony_ci 16570af302Sopenharmony_ci/** 17570af302Sopenharmony_ci * @brief Retrieves the current value of the x1 register on AArch64. 18570af302Sopenharmony_ci * 19570af302Sopenharmony_ci * This function is used in CFI checks to obtain the function address 20570af302Sopenharmony_ci * stored in the x1 register during calls involving function pointers, 21570af302Sopenharmony_ci * virtual calls (vcall), and non-virtual calls (nvcall) using vtable addresses. 22570af302Sopenharmony_ci * 23570af302Sopenharmony_ci * @return Value of the x1 register. 24570af302Sopenharmony_ci */ 25570af302Sopenharmony_ciuint64_t fetch_function_address() 26570af302Sopenharmony_ci{ 27570af302Sopenharmony_ci uint64_t val; 28570af302Sopenharmony_ci __asm__ __volatile__( 29570af302Sopenharmony_ci "mov %0, x1" 30570af302Sopenharmony_ci : "=r" (val) 31570af302Sopenharmony_ci : 32570af302Sopenharmony_ci : "memory" 33570af302Sopenharmony_ci ); 34570af302Sopenharmony_ci return val; 35570af302Sopenharmony_ci} 36570af302Sopenharmony_ci#endif 37570af302Sopenharmony_ci 38570af302Sopenharmony_ci_Noreturn void __cfi_fail_report(void) 39570af302Sopenharmony_ci{ 40570af302Sopenharmony_ci#if defined(MUSL_AARCH64_ARCH) 41570af302Sopenharmony_ci uint64_t function_address = fetch_function_address(); 42570af302Sopenharmony_ci char message[MESSAGE_BUFFER_SIZE]; 43570af302Sopenharmony_ci snprintf(message, sizeof(message), 44570af302Sopenharmony_ci " CFI check failed. Function Address: 0x%" PRIx64, function_address); 45570af302Sopenharmony_ci set_fatal_message(message); 46570af302Sopenharmony_ci#endif 47570af302Sopenharmony_ci abort(); 48570af302Sopenharmony_ci} 49570af302Sopenharmony_ci 50570af302Sopenharmony_ci_Noreturn void abort(void) 51570af302Sopenharmony_ci{ 52570af302Sopenharmony_ci#ifdef __LITEOS_A__ 53570af302Sopenharmony_ci sigset_t set, pending; 54570af302Sopenharmony_ci sigemptyset(&set); 55570af302Sopenharmony_ci sigaddset(&set, SIGABRT); 56570af302Sopenharmony_ci 57570af302Sopenharmony_ci sigpending(&pending); 58570af302Sopenharmony_ci __syscall(SYS_rt_sigprocmask, SIG_UNBLOCK, &set, 0, _NSIG / 8); 59570af302Sopenharmony_ci if (!sigismember(&pending, SIGABRT)) { 60570af302Sopenharmony_ci raise(SIGABRT); 61570af302Sopenharmony_ci } 62570af302Sopenharmony_ci#else 63570af302Sopenharmony_ci raise(SIGABRT); 64570af302Sopenharmony_ci#endif 65570af302Sopenharmony_ci 66570af302Sopenharmony_ci /* If there was a SIGABRT handler installed and it returned, or if 67570af302Sopenharmony_ci * SIGABRT was blocked or ignored, take an AS-safe lock to prevent 68570af302Sopenharmony_ci * sigaction from installing a new SIGABRT handler, uninstall any 69570af302Sopenharmony_ci * handler that may be present, and re-raise the signal to generate 70570af302Sopenharmony_ci * the default action of abnormal termination. */ 71570af302Sopenharmony_ci __block_all_sigs(0); 72570af302Sopenharmony_ci LOCK(__abort_lock); 73570af302Sopenharmony_ci#ifdef __LITEOS_A__ 74570af302Sopenharmony_ci signal(SIGABRT, SIG_DFL); 75570af302Sopenharmony_ci#else 76570af302Sopenharmony_ci __syscall(SYS_rt_sigaction, SIGABRT, 77570af302Sopenharmony_ci &(struct k_sigaction){.handler = SIG_DFL}, 0, _NSIG/8); 78570af302Sopenharmony_ci#endif 79570af302Sopenharmony_ci __syscall(SYS_tkill, __pthread_self()->tid, SIGABRT); 80570af302Sopenharmony_ci __syscall(SYS_rt_sigprocmask, SIG_UNBLOCK, 81570af302Sopenharmony_ci &(long[_NSIG/(8*sizeof(long))]){1UL<<(SIGABRT-1)}, 0, _NSIG/8); 82570af302Sopenharmony_ci 83570af302Sopenharmony_ci /* Beyond this point should be unreachable. */ 84570af302Sopenharmony_ci a_crash(); 85570af302Sopenharmony_ci raise(SIGKILL); 86570af302Sopenharmony_ci _Exit(127); 87570af302Sopenharmony_ci} 88