[llvm] [BOLT] Gadget scanner: detect non-protected indirect calls (PR #131899)
Jacob Bramley via llvm-commits
llvm-commits at lists.llvm.org
Wed Mar 26 07:49:22 PDT 2025
================
@@ -0,0 +1,777 @@
+// 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
+
+// PACRET-NOT: non-protected call found in function
+
+ .text
+
+ .globl good_direct_call
+ .type good_direct_call, at function
+good_direct_call:
+// CHECK-NOT: good_direct_call
+ paciasp
+ stp x29, x30, [sp, #-16]!
+ mov x29, sp
+
+ bl callee_ext
+
+ ldp x29, x30, [sp], #16
+ autiasp
+ ret
+ .size good_direct_call, .-good_direct_call
+
+ .globl good_indirect_call_arg
+ .type good_indirect_call_arg, at function
+good_indirect_call_arg:
+// CHECK-NOT: good_indirect_call_arg
+ paciasp
+ stp x29, x30, [sp, #-16]!
+ mov x29, sp
+
+ autia x0, x1
+ blr x0
+
+ ldp x29, x30, [sp], #16
+ autiasp
+ ret
+ .size good_indirect_call_arg, .-good_indirect_call_arg
+
+ .globl good_indirect_call_mem
+ .type good_indirect_call_mem, at function
+good_indirect_call_mem:
+// CHECK-NOT: good_indirect_call_mem
+ paciasp
+ stp x29, x30, [sp, #-16]!
+ mov x29, sp
+
+ ldr x16, [x0]
+ autia x16, x0
+ blr x16
+
+ ldp x29, x30, [sp], #16
+ autiasp
+ ret
+ .size good_indirect_call_mem, .-good_indirect_call_mem
+
+ .globl good_indirect_call_arg_v83
+ .type good_indirect_call_arg_v83, at function
+good_indirect_call_arg_v83:
+// CHECK-NOT: good_indirect_call_arg_v83
+ paciasp
+ stp x29, x30, [sp, #-16]!
+ mov x29, sp
+
+ blraa x0, x1
+
+ ldp x29, x30, [sp], #16
+ autiasp
+ ret
+ .size good_indirect_call_arg_v83, .-good_indirect_call_arg_v83
+
+ .globl good_indirect_call_mem_v83
+ .type good_indirect_call_mem_v83, at function
+good_indirect_call_mem_v83:
+// CHECK-NOT: good_indirect_call_mem_v83
+ paciasp
+ stp x29, x30, [sp, #-16]!
+ mov x29, sp
+
+ ldr x16, [x0]
+ blraa x16, x0
+
+ ldp x29, x30, [sp], #16
+ autiasp
+ ret
+ .size good_indirect_call_mem_v83, .-good_indirect_call_mem_v83
+
+ .globl bad_indirect_call_arg
+ .type bad_indirect_call_arg, at function
+bad_indirect_call_arg:
+// CHECK-LABEL: GS-PAUTH: non-protected call found in function bad_indirect_call_arg, basic block {{[^,]+}}, at address
+// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x0
+// CHECK-NEXT: The 0 instructions that write to the affected registers after any authentication are:
+ paciasp
+ stp x29, x30, [sp, #-16]!
+ mov x29, sp
+
+ blr x0
+
+ ldp x29, x30, [sp], #16
+ autiasp
+ ret
+ .size bad_indirect_call_arg, .-bad_indirect_call_arg
+
+ .globl bad_indirect_call_mem
+ .type bad_indirect_call_mem, at function
+bad_indirect_call_mem:
+// CHECK-LABEL: GS-PAUTH: non-protected call found in function bad_indirect_call_mem, basic block {{[^,]+}}, at address
+// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x16
+// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
+// CHECK-NEXT: 1. {{[0-9a-f]+}}: ldr x16, [x0]
+// 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]+}}: ldr x16, [x0]
+// CHECK-NEXT: {{[0-9a-f]+}}: blr x16
+// 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
+
+ ldr x16, [x0]
+ blr x16
+
+ ldp x29, x30, [sp], #16
+ autiasp
+ ret
+ .size bad_indirect_call_mem, .-bad_indirect_call_mem
+
+ .globl bad_indirect_call_arg_clobber
+ .type bad_indirect_call_arg_clobber, at function
+bad_indirect_call_arg_clobber:
+// CHECK-LABEL: GS-PAUTH: non-protected call found in function bad_indirect_call_arg_clobber, basic block {{[^,]+}}, at address
+// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x0
+// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
+// CHECK-NEXT: 1. {{[0-9a-f]+}}: mov w0, w2
+// 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]+}}: mov w0, w2
+// CHECK-NEXT: {{[0-9a-f]+}}: blr 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
+ mov w0, w2
+ blr x0
+
+ ldp x29, x30, [sp], #16
+ autiasp
+ ret
+ .size bad_indirect_call_arg_clobber, .-bad_indirect_call_arg_clobber
+
+ .globl bad_indirect_call_mem_clobber
+ .type bad_indirect_call_mem_clobber, at function
+bad_indirect_call_mem_clobber:
+// CHECK-LABEL: GS-PAUTH: non-protected call found in function bad_indirect_call_mem_clobber, basic block {{[^,]+}}, at address
+// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: blr x16
+// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
+// CHECK-NEXT: 1. {{[0-9a-f]+}}: mov w16, w2
+// 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]+}}: ldr x16, [x0]
+// CHECK-NEXT: {{[0-9a-f]+}}: autia x16, x0
+// CHECK-NEXT: {{[0-9a-f]+}}: mov w16, w2
+// CHECK-NEXT: {{[0-9a-f]+}}: blr x16
+// 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
+
+ ldr x16, [x0]
+ autia x16, x0
+ mov w16, w2
+ blr x16
+
+ ldp x29, x30, [sp], #16
+ autiasp
+ ret
+ .size bad_indirect_call_mem_clobber, .-bad_indirect_call_mem_clobber
+
+ .globl good_indirect_call_mem_chain_of_auts
+ .type good_indirect_call_mem_chain_of_auts, at function
+good_indirect_call_mem_chain_of_auts:
+// CHECK-NOT: good_indirect_call_mem_chain_of_auts
+ paciasp
+ stp x29, x30, [sp, #-16]!
+ mov x29, sp
+
+ ldr x16, [x0]
+ autia x16, x1
+ ldr x16, [x16]
----------------
jacobbramley wrote:
A more advanced (future) scanner might be upset about using `autia` (not `autda`) to authenticate a data pointer. In that case, we could update the test, but perhaps `autda` is more realistic.
Likewise below.
https://github.com/llvm/llvm-project/pull/131899
More information about the llvm-commits
mailing list