1 #include <stdint.h> 2 #include <assert.h> 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include "pauth.h" 6 7 #define TESTS 1000 8 9 int main() 10 { 11 char base[TESTS]; 12 int i, count = 0; 13 float perc; 14 int pac_feature = get_pac_feature(); 15 16 /* 17 * Exit if no PAuth or FEAT_FPAC, which will SIGILL on AUTIA failure 18 * rather than return an error for us to check below. 19 */ 20 if (pac_feature == 0 || pac_feature >= 4) { 21 return 0; 22 } 23 24 for (i = 0; i < TESTS; i++) { 25 uintptr_t in, x, y; 26 27 in = i + (uintptr_t) base; 28 29 asm("mov %0, %[in]\n\t" 30 "pacia %0, sp\n\t" 31 "eor %0, %0, #4\n\t" /* corrupt single bit */ 32 "mov %1, %0\n\t" 33 "autia %1, sp\n\t" /* validate corrupted pointer */ 34 "xpaci %0\n\t" /* strip pac from corrupted pointer */ 35 : /* out */ "=r"(x), "=r"(y) 36 : /* in */ [in] "r" (in) 37 : /* clobbers */); 38 39 /* 40 * Once stripped, the corrupted pointer is of the form 0x0000...wxyz. 41 * We expect the autia to indicate failure, producing a pointer of the 42 * form 0x000e....wxyz. Use xpaci and != for the test, rather than 43 * extracting explicit bits from the top, because the location of the 44 * error code "e" depends on the configuration of virtual memory. 45 */ 46 if (x != y) { 47 count++; 48 } 49 } 50 51 perc = (float) count / (float) TESTS; 52 printf("Checks Passed: %0.2f%%\n", perc * 100.0); 53 assert(perc > 0.95); 54 return 0; 55 } 56