[llvm] [BOLT] Gadget scanner: detect authentication oracles (PR #135663)

Anatoly Trosinenko via llvm-commits llvm-commits at lists.llvm.org
Wed May 28 10:07:54 PDT 2025


================
@@ -0,0 +1,739 @@
+// RUN: %clang %cflags -march=armv8.3-a %s -o %t.exe
+// RUN: llvm-bolt-binary-analysis --scanners=pacret %t.exe 2>&1 | FileCheck -check-prefix=PACRET %s
+// RUN: llvm-bolt-binary-analysis --scanners=pauth  %t.exe 2>&1 | FileCheck %s
+
+// The detection of compiler-generated explicit pointer checks is tested in
+// gs-pauth-address-checks.s, for that reason only test here "dummy-load" and
+// "high-bits-notbi" checkers, as the shortest examples of checkers that are
+// detected per-instruction and per-BB.
+
+// PACRET-NOT: authentication oracle found in function
+
+        .text
+
+        .type   sym, at function
+sym:
+        ret
+        .size sym, .-sym
+
+        .globl  callee
+        .type   callee, at function
+callee:
+        ret
+        .size callee, .-callee
+
+        .globl  good_ret
+        .type   good_ret, at function
+good_ret:
+// CHECK-NOT: good_ret
+        autia   x0, x1
+        ret     x0
+        .size good_ret, .-good_ret
+
+        .globl  good_call
+        .type   good_call, at function
+good_call:
+// CHECK-NOT: good_call
+        paciasp
+        stp     x29, x30, [sp, #-16]!
+        mov     x29, sp
+
+        autia   x0, x1
+        blr     x0
+
+        ldp     x29, x30, [sp], #16
+        autiasp
+        ret
+        .size good_call, .-good_call
+
+        .globl  good_branch
+        .type   good_branch, at function
+good_branch:
+// CHECK-NOT: good_branch
+        autia   x0, x1
+        br      x0
+        .size good_branch, .-good_branch
+
+        .globl  good_load_other_reg
+        .type   good_load_other_reg, at function
+good_load_other_reg:
+// CHECK-NOT: good_load_other_reg
+        autia   x0, x1
+        ldr     x2, [x0]
+        ret
+        .size good_load_other_reg, .-good_load_other_reg
+
+        .globl  good_load_same_reg
+        .type   good_load_same_reg, at function
+good_load_same_reg:
+// CHECK-NOT: good_load_same_reg
+        autia   x0, x1
+        ldr     x0, [x0]
+        ret
+        .size good_load_same_reg, .-good_load_same_reg
+
+        .globl  good_explicit_check
+        .type   good_explicit_check, at function
+good_explicit_check:
+// CHECK-NOT: good_explicit_check
+        autia   x0, x1
+        eor     x16, x0, x0, lsl #1
+        tbz     x16, #62, 1f
+        brk     0x1234
+1:
+        ret
+        .size good_explicit_check, .-good_explicit_check
+
+        .globl  bad_unchecked
+        .type   bad_unchecked, at function
+bad_unchecked:
+// CHECK-LABEL: GS-PAUTH: authentication oracle found in function bad_unchecked, basic block {{[^,]+}}, at address
+// CHECK-NEXT:  The instruction is     {{[0-9a-f]+}}:      autia   x0, x1
+// CHECK-NEXT:  The 0 instructions that leak the affected registers are:
+        autia   x0, x1
+        ret
+        .size bad_unchecked, .-bad_unchecked
+
+        .globl  bad_leaked_to_subroutine
+        .type   bad_leaked_to_subroutine, at function
+bad_leaked_to_subroutine:
+// CHECK-LABEL: GS-PAUTH: authentication oracle found in function bad_leaked_to_subroutine, basic block {{[^,]+}}, at address
+// CHECK-NEXT:  The instruction is     {{[0-9a-f]+}}:      autia   x0, x1
+// CHECK-NEXT:  The 1 instructions that leak the affected registers are:
+// CHECK-NEXT:  1.     {{[0-9a-f]+}}:      bl      callee
+// CHECK-NEXT:  This happens in the following basic block:
+// CHECK-NEXT:  {{[0-9a-f]+}}:   paciasp
+// CHECK-NEXT:  {{[0-9a-f]+}}:   stp     x29, x30, [sp, #-0x10]!
+// CHECK-NEXT:  {{[0-9a-f]+}}:   mov     x29, sp
+// CHECK-NEXT:  {{[0-9a-f]+}}:   autia   x0, x1
+// CHECK-NEXT:  {{[0-9a-f]+}}:   bl      callee
+// CHECK-NEXT:  {{[0-9a-f]+}}:   ldr     x2, [x0]
+// CHECK-NEXT:  {{[0-9a-f]+}}:   ldp     x29, x30, [sp], #0x10
+// CHECK-NEXT:  {{[0-9a-f]+}}:   autiasp
+// CHECK-NEXT:  {{[0-9a-f]+}}:   ret
+        paciasp
+        stp     x29, x30, [sp, #-16]!
+        mov     x29, sp
+
+        autia   x0, x1
+        bl      callee
+        ldr     x2, [x0]
+
+        ldp     x29, x30, [sp], #16
+        autiasp
+        ret
+        .size bad_leaked_to_subroutine, .-bad_leaked_to_subroutine
+
+        .globl  bad_unknown_usage_read
+        .type   bad_unknown_usage_read, at function
+bad_unknown_usage_read:
+// CHECK-LABEL: GS-PAUTH: authentication oracle found in function bad_unknown_usage_read, basic block {{[^,]+}}, at address
+// CHECK-NEXT:  The instruction is     {{[0-9a-f]+}}:      autia   x0, x1
+// CHECK-NEXT:  The 1 instructions that leak the affected registers are:
+// CHECK-NEXT:  1.     {{[0-9a-f]+}}:      mul     x3, x0, x1
+// CHECK-NEXT:  This happens in the following basic block:
+// CHECK-NEXT:  {{[0-9a-f]+}}:   autia   x0, x1
+// CHECK-NEXT:  {{[0-9a-f]+}}:   mul     x3, x0, x1
+// CHECK-NEXT:  {{[0-9a-f]+}}:   ldr     x2, [x0]
+// CHECK-NEXT:  {{[0-9a-f]+}}:   ret
+        autia   x0, x1
+        mul     x3, x0, x1
+        ldr     x2, [x0]
----------------
atrosinenko wrote:

Added a few more test cases based on this discussion. Turned out, false negative are possible, if no RET instructions are reachable from the instruction to be reported as an authentication oracle. Added a FIXME so far, as it probably deserves a separate PR...

https://github.com/llvm/llvm-project/pull/135663


More information about the llvm-commits mailing list