brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.2 KiB · 7810b2d Raw
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