214 lines · plain
1// RUN: %clang %cflags -march=armv8.3-a %s -o %t.exe -Wl,--emit-relocs2// RUN: llvm-bolt-binary-analysis --scanners=pauth %t.exe 2>&1 | FileCheck %s3 4// Test what instructions can be used to terminate the program abnormally5// on security violation.6//7// All test cases have the same structure:8//9// cbz x0, 1f // [a], ensures [c] is never reported as unreachable10// autia x2, x311// cbz x1, 2f // [b]12// [instruction under test]13// 1:14// ret // [c]15// 2:16// ldr x0, [x2]17// ret18//19// This is to handle three possible cases: the instruction under test may be20// considered by BOLT as21// * trapping (and thus no-return): after being authenticated, x2 is ether22// checked by LDR (if [b] is taken) or the program is terminated23// immediately without leaking x2 (if [b] falls through to the trapping24// instruction under test). Nothing is reported.25// * non-trapping, but no-return (such as calling abort()): x2 is leaked if [b]26// falls through. Authentication oracle is reported.27// * non-trapping and falling-through (i.e. a regular instruction):28// x2 is leaked by [c]. Authentication oracle is reported.29 30 .text31 32 .globl brk_key_ia33 .type brk_key_ia,@function34brk_key_ia:35// CHECK-NOT: brk_key_ia36 cbz x0, 1f37 autia x2, x338 cbz x1, 2f39 brk 0xc470401:41 ret422:43 ldr x0, [x2]44 ret45 .size brk_key_ia, .-brk_key_ia46 47 .globl brk_key_ib48 .type brk_key_ib,@function49brk_key_ib:50// CHECK-NOT: brk_key_ib51 cbz x0, 1f52 autia x2, x353 cbz x1, 2f54 brk 0xc471551:56 ret572:58 ldr x0, [x2]59 ret60 .size brk_key_ib, .-brk_key_ib61 62 .globl brk_key_da63 .type brk_key_da,@function64brk_key_da:65// CHECK-NOT: brk_key_da66 cbz x0, 1f67 autia x2, x368 cbz x1, 2f69 brk 0xc472701:71 ret722:73 ldr x0, [x2]74 ret75 .size brk_key_da, .-brk_key_da76 77 .globl brk_key_db78 .type brk_key_db,@function79brk_key_db:80// CHECK-NOT: brk_key_db81 cbz x0, 1f82 autia x2, x383 cbz x1, 2f84 brk 0xc473851:86 ret872:88 ldr x0, [x2]89 ret90 .size brk_key_db, .-brk_key_db91 92// The immediate operand of BRK instruction may indicate whether the instruction93// is intended to be a non-recoverable trap: for example, for this code94//95// int test_trap(void) {96// __builtin_trap();97// return 42;98// }99// int test_debugtrap(void) {100// __builtin_debugtrap();101// return 42;102// }103//104// Clang produces the following assembly:105//106// test_trap:107// brk #0x1108// test_debugtrap:109// brk #0xf000110// mov w0, #42111// ret112//113// In GCC, __builtin_trap() uses "brk 0x3e8" (i.e. decimal 1000) and114// __builtin_debugtrap() is not supported.115//116// At the time of writing these test cases, any BRK instruction is considered117// no-return by BOLT, thus it ends its basic block and prevents falling through118// to the next BB.119// FIXME: Make BOLT handle __builtin_debugtrap() properly from the CFG point120// of view.121 122 .globl brk_gcc_builtin_trap123 .type brk_gcc_builtin_trap,@function124brk_gcc_builtin_trap:125// CHECK-NOT: brk_gcc_builtin_trap126 cbz x0, 1f127 autia x2, x3128 cbz x1, 2f129 brk 0x3e8 // __builtin_trap()1301:131 ret1322:133 ldr x0, [x2]134 ret135 .size brk_gcc_builtin_trap, .-brk_gcc_builtin_trap136 137 .globl brk_clang_builtin_trap138 .type brk_clang_builtin_trap,@function139brk_clang_builtin_trap:140// CHECK-NOT: brk_clang_builtin_trap141 cbz x0, 1f142 autia x2, x3143 cbz x1, 2f144 brk 0x1 // __builtin_trap()1451:146 ret1472:148 ldr x0, [x2]149 ret150 .size brk_clang_builtin_trap, .-brk_clang_builtin_trap151 152 .globl brk_clang_builtin_debugtrap153 .type brk_clang_builtin_debugtrap,@function154brk_clang_builtin_debugtrap:155// CHECK-LABEL: GS-PAUTH: authentication oracle found in function brk_clang_builtin_debugtrap, basic block {{[^,]+}}, at address156// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: autia x2, x3157// CHECK-NEXT: The 0 instructions that leak the affected registers are:158 cbz x0, 1f159 autia x2, x3160 cbz x1, 2f161 brk 0xf000 // __builtin_debugtrap()1621:163 ret1642:165 ldr x0, [x2]166 ret167 .size brk_clang_builtin_debugtrap, .-brk_clang_builtin_debugtrap168 169// Conservatively assume BRK with an unknown immediate operand as not suitable170// for terminating the program on security violation.171 .globl brk_unknown_imm172 .type brk_unknown_imm,@function173brk_unknown_imm:174// CHECK-LABEL: GS-PAUTH: authentication oracle found in function brk_unknown_imm, basic block {{[^,]+}}, at address175// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: autia x2, x3176// CHECK-NEXT: The 0 instructions that leak the affected registers are:177 cbz x0, 1f178 autia x2, x3179 cbz x1, 2f180 brk 0x35721811:182 ret1832:184 ldr x0, [x2]185 ret186 .size brk_unknown_imm, .-brk_unknown_imm187 188// Conservatively assume calling the abort() function may be an unsafe way to189// terminate the program, as there is some amount of instructions that would190// be executed when the program state is already tampered with.191 .globl call_abort_fn192 .type call_abort_fn,@function193call_abort_fn:194// CHECK-LABEL: GS-PAUTH: authentication oracle found in function call_abort_fn, basic block {{[^,]+}}, at address195// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: autia x2, x3196// CHECK-NEXT: The 0 instructions that leak the affected registers are:197 cbz x0, 1f198 autia x2, x3199 cbz x1, 2f200 b abort // a no-return tail call to abort()2011:202 ret2032:204 ldr x0, [x2]205 ret206 .size call_abort_fn, .-call_abort_fn207 208 .globl main209 .type main,@function210main:211 mov x0, 0212 ret213 .size main, .-main214