1b7a85887Skettenis /* Public domain */ 2b7a85887Skettenis 3b7a85887Skettenis #include <signal.h> 4*f2888ae1Santon #include <stdint.h> 5*f2888ae1Santon #include <stdio.h> 6b7a85887Skettenis #include <stdlib.h> 7b7a85887Skettenis 8b7a85887Skettenis extern void foo(void); 9b7a85887Skettenis void (*foobar)(void) = foo; 10b7a85887Skettenis 11b7a85887Skettenis void bar(void)12b7a85887Skettenisbar(void) 13b7a85887Skettenis { 14b7a85887Skettenis foobar(); 15b7a85887Skettenis } 16b7a85887Skettenis 17b7a85887Skettenis void handler(int sig,siginfo_t * si,void * context)18b7a85887Skettenishandler(int sig, siginfo_t *si, void *context) 19b7a85887Skettenis { 20b7a85887Skettenis if (si->si_signo == SIGILL && si->si_code == ILL_BTCFI) 21b7a85887Skettenis exit(0); 22b7a85887Skettenis } 23b7a85887Skettenis 24*f2888ae1Santon #if defined(__amd64__) 25*f2888ae1Santon static int has_cet_ibt(void)26*f2888ae1Santonhas_cet_ibt(void) 27*f2888ae1Santon { 28*f2888ae1Santon uint32_t d; 29*f2888ae1Santon 30*f2888ae1Santon asm("cpuid" : "=d" (d) : "a" (7), "c" (0)); 31*f2888ae1Santon return (d & (1U << 20)) ? 1 : 0; 32*f2888ae1Santon } 33*f2888ae1Santon #endif 34*f2888ae1Santon 35b7a85887Skettenis int main(void)36b7a85887Skettenismain(void) 37b7a85887Skettenis { 38b7a85887Skettenis struct sigaction sa; 39b7a85887Skettenis 40*f2888ae1Santon #if defined(__amd64__) 41*f2888ae1Santon if (!has_cet_ibt()) { 42*f2888ae1Santon printf("Unsupported CPU\n"); 43*f2888ae1Santon printf("SKIPPED\n"); 44*f2888ae1Santon exit(0); 45*f2888ae1Santon } 46*f2888ae1Santon #endif 47*f2888ae1Santon 48b7a85887Skettenis sa.sa_sigaction = handler; 49b7a85887Skettenis sa.sa_mask = 0; 50b7a85887Skettenis sa.sa_flags = SA_SIGINFO; 51b7a85887Skettenis sigaction(SIGILL, &sa, NULL); 52b7a85887Skettenis 53b7a85887Skettenis bar(); 54b7a85887Skettenis exit(1); 55b7a85887Skettenis } 56