llvm-project/bolt/test/binary-analysis/AArch64/gs-pauth-address-checks.s
Anatoly Trosinenko 48a2836b4d
[BOLT] Gadget scanner: detect signing oracles (#134146)
Implement the detection of signing oracles. In this patch, a signing
oracle is defined as a sign instruction that accepts a "non-protected"
pointer, but for a slightly different definition of "non-protected"
compared to control flow instructions.

A second BitVector named TrustedRegs is added to the register state
computed by the data-flow analysis. The difference between a
"safe-to-dereference" and a "trusted" register states is that to make
an unsafe register trusted by authentication, one has to make sure
that the authentication succeeded. For example, on AArch64 without
FEAT_PAuth2 and FEAT_EPAC, an authentication instruction produces an
invalid pointer on failure, so that subsequent memory access triggers
an error, but re-signing such pointer would "fix" the signature.

Note that while a separate "trusted" register state may be redundant
depending on the specific semantics of auth and sign operations, it is
still important to check signing operations: while code like this

    resign:
      autda x0, x1
      pacda x0, x2
      ret

is probably safe provided `autda` generates an error on authentication
failure, this function

    sign_anything:
      pacda x0, x1
      ret

is inherently unsafe.
2025-05-20 13:42:53 +03:00

665 lines
26 KiB
ArmAsm

// RUN: %clang %cflags -march=armv8.3-a %s -o %t.exe -Wl,--emit-relocs
// RUN: llvm-bolt-binary-analysis --scanners=pauth %t.exe 2>&1 | FileCheck %s
.text
.globl raise_error
.type raise_error,@function
raise_error:
ret
.size raise_error, .-raise_error
.globl resign_no_check
.type resign_no_check,@function
resign_no_check:
// CHECK-LABEL: GS-PAUTH: signing oracle found in function resign_no_check, basic block {{[^,]+}}, at address
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: pacia x0, x2
// CHECK-NEXT: The 0 instructions that write to the affected registers after any authentication are:
autib x0, x1
pacia x0, x2
ret
.size resign_no_check, .-resign_no_check
// Test "xpac" check method.
.globl resign_xpaci_good
.type resign_xpaci_good,@function
resign_xpaci_good:
// CHECK-NOT: resign_xpaci_good
autib x0, x1
mov x16, x0
xpaci x16
cmp x0, x16
b.eq 1f
brk 0x1234
1:
pacia x0, x2
ret
.size resign_xpaci_good, .-resign_xpaci_good
.globl resign_xpacd_good
.type resign_xpacd_good,@function
resign_xpacd_good:
// CHECK-NOT: resign_xpacd_good
autdb x0, x1
mov x16, x0
xpacd x16
cmp x0, x16
b.eq 1f
brk 0x1234
1:
pacda x0, x2
ret
.size resign_xpacd_good, .-resign_xpacd_good
.globl resign_xpaci_wrong_error
.type resign_xpaci_wrong_error,@function
resign_xpaci_wrong_error:
// CHECK-LABEL: GS-PAUTH: signing oracle found in function resign_xpaci_wrong_error, basic block {{[^,]+}}, at address
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: pacia x0, x2
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
// CHECK-NEXT: 1. {{[0-9a-f]+}}: bl raise_error
paciasp
stp x29, x30, [sp, #-16]!
autib x0, x1
mov x16, x0
xpaci x16
cmp x0, x16
b.eq 1f
bl raise_error // should trigger breakpoint instead
1:
pacia x0, x2
ldp x29, x30, [sp], #16
autiasp
ret
.size resign_xpaci_wrong_error, .-resign_xpaci_wrong_error
.globl resign_xpaci_missing_brk
.type resign_xpaci_missing_brk,@function
resign_xpaci_missing_brk:
// CHECK-LABEL: GS-PAUTH: signing oracle found in function resign_xpaci_missing_brk, basic block {{[^,]+}}, at address
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: pacia x0, x2
// CHECK-NEXT: The 0 instructions that write to the affected registers after any authentication are:
autib x0, x1
mov x16, x0
xpaci x16
cmp x0, x16
b.eq 1f
1:
pacia x0, x2
ret
.size resign_xpaci_missing_brk, .-resign_xpaci_missing_brk
.globl resign_xpaci_missing_branch_and_brk
.type resign_xpaci_missing_branch_and_brk,@function
resign_xpaci_missing_branch_and_brk:
// CHECK-LABEL: GS-PAUTH: signing oracle found in function resign_xpaci_missing_branch_and_brk, basic block {{[^,]+}}, at address
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: pacia x0, x2
// CHECK-NEXT: The 0 instructions that write to the affected registers after any authentication are:
autib x0, x1
mov x16, x0
xpaci x16
cmp x0, x16
pacia x0, x2
ret
.size resign_xpaci_missing_branch_and_brk, .-resign_xpaci_missing_branch_and_brk
.globl resign_xpaci_unrelated_auth_and_check
.type resign_xpaci_unrelated_auth_and_check,@function
resign_xpaci_unrelated_auth_and_check:
// CHECK-LABEL: GS-PAUTH: signing oracle found in function resign_xpaci_unrelated_auth_and_check, basic block {{[^,]+}}, at address
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: pacia x10, x2
// CHECK-NEXT: The 0 instructions that write to the affected registers after any authentication are:
autib x10, x1 // made x10 safe-to-dereference
mov x16, x0 // start of checker sequence for x0
xpaci x16
cmp x0, x16
b.eq 1f
brk 0x1234
1:
pacia x10, x2
ret
.size resign_xpaci_unrelated_auth_and_check, .-resign_xpaci_unrelated_auth_and_check
// There are lots of operands to check in the pattern - let's at the very least
// check that each of the three instructions (mov, xpac, cmp) undergoes *some*
// matching. Pay a bit more attention to those instructions and their operands
// that can be obviously replaced without crashing at run-time and making the
// check obviously weaker.
.globl resign_xpaci_wrong_pattern_1
.type resign_xpaci_wrong_pattern_1,@function
resign_xpaci_wrong_pattern_1:
// CHECK-LABEL: GS-PAUTH: signing oracle found in function resign_xpaci_wrong_pattern_1, basic block {{[^,]+}}, at address
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: pacia x0, x2
// CHECK-NEXT: The 0 instructions that write to the affected registers after any authentication are:
autib x0, x1
mov x16, x10 // x10 instead of x0
xpaci x16
cmp x0, x16
b.eq 1f
brk 0x1234
1:
pacia x0, x2
ret
.size resign_xpaci_wrong_pattern_1, .-resign_xpaci_wrong_pattern_1
.globl resign_xpaci_wrong_pattern_2
.type resign_xpaci_wrong_pattern_2,@function
resign_xpaci_wrong_pattern_2:
// CHECK-LABEL: GS-PAUTH: signing oracle found in function resign_xpaci_wrong_pattern_2, basic block {{[^,]+}}, at address
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: pacia x0, x2
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
// CHECK-NEXT: 1. {{[0-9a-f]+}}: xpaci x0
autib x0, x1
mov x16, x0
xpaci x0 // x0 instead of x16
cmp x0, x16
b.eq 1f
brk 0x1234
1:
pacia x0, x2
ret
.size resign_xpaci_wrong_pattern_2, .-resign_xpaci_wrong_pattern_2
.globl resign_xpaci_wrong_pattern_3
.type resign_xpaci_wrong_pattern_3,@function
resign_xpaci_wrong_pattern_3:
// CHECK-LABEL: GS-PAUTH: signing oracle found in function resign_xpaci_wrong_pattern_3, basic block {{[^,]+}}, at address
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: pacia x0, x2
// CHECK-NEXT: The 0 instructions that write to the affected registers after any authentication are:
autib x0, x1
mov x16, x0
xpaci x16
cmp x16, x16 // x16 instead of x0
b.eq 1f
brk 0x1234
1:
pacia x0, x2
ret
.size resign_xpaci_wrong_pattern_3, .-resign_xpaci_wrong_pattern_3
.globl resign_xpaci_wrong_pattern_4
.type resign_xpaci_wrong_pattern_4,@function
resign_xpaci_wrong_pattern_4:
// CHECK-LABEL: GS-PAUTH: signing oracle found in function resign_xpaci_wrong_pattern_4, basic block {{[^,]+}}, at address
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: pacia x0, x2
// CHECK-NEXT: The 0 instructions that write to the affected registers after any authentication are:
autib x0, x1
mov x16, x0
xpaci x16
cmp x0, x0 // x0 instead of x16
b.eq 1f
brk 0x1234
1:
pacia x0, x2
ret
.size resign_xpaci_wrong_pattern_4, .-resign_xpaci_wrong_pattern_4
.globl resign_xpaci_wrong_pattern_5
.type resign_xpaci_wrong_pattern_5,@function
resign_xpaci_wrong_pattern_5:
// CHECK-LABEL: GS-PAUTH: signing oracle found in function resign_xpaci_wrong_pattern_5, basic block {{[^,]+}}, at address
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: pacia x0, x2
// CHECK-NEXT: The 0 instructions that write to the affected registers after any authentication are:
autib x0, x1
mov x16, x0
mov x16, x16 // replace xpaci with a no-op instruction
cmp x0, x16
b.eq 1f
brk 0x1234
1:
pacia x0, x2
ret
.size resign_xpaci_wrong_pattern_5, .-resign_xpaci_wrong_pattern_5
// Test "xpac-hint" check method.
.globl resign_xpaclri_good
.type resign_xpaclri_good,@function
resign_xpaclri_good:
// CHECK-NOT: resign_xpaclri_good
paciasp
stp x29, x30, [sp, #-16]!
autib x30, x1
mov x16, x30
xpaclri
cmp x30, x16
b.eq 1f
brk 0x1234
1:
pacia x30, x2
ldp x29, x30, [sp], #16
autiasp
ret
.size resign_xpaclri_good, .-resign_xpaclri_good
.globl xpaclri_check_keeps_lr_safe
.type xpaclri_check_keeps_lr_safe,@function
xpaclri_check_keeps_lr_safe:
// CHECK-NOT: xpaclri_check_keeps_lr_safe
// LR is implicitly safe-to-dereference and trusted here
mov x16, x30
xpaclri // clobbers LR
cmp x30, x16
b.eq 1f
brk 0x1234 // marks LR as trusted and safe-to-dereference
1:
ret // not reporting non-protected return
.size xpaclri_check_keeps_lr_safe, .-xpaclri_check_keeps_lr_safe
.globl xpaclri_check_requires_safe_lr
.type xpaclri_check_requires_safe_lr,@function
xpaclri_check_requires_safe_lr:
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function xpaclri_check_requires_safe_lr, basic block {{[^,]+}}, at address
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: ret
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
// CHECK-NEXT: 1. {{[0-9a-f]+}}: xpaclri
mov x30, x0
// LR is not safe-to-dereference here - check that xpac-hint checker
// does not make LR safe-to-dereference, but only *keeps* this state.
mov x16, x30
xpaclri
cmp x30, x16
b.eq 1f
brk 0x1234
1:
ret
.size xpaclri_check_requires_safe_lr, .-xpaclri_check_requires_safe_lr
.globl resign_xpaclri_wrong_reg
.type resign_xpaclri_wrong_reg,@function
resign_xpaclri_wrong_reg:
// CHECK-LABEL: GS-PAUTH: signing oracle found in function resign_xpaclri_wrong_reg, basic block {{[^,]+}}, at address
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: pacia x20, x2
// CHECK-NEXT: The 0 instructions that write to the affected registers after any authentication are:
paciasp
autib x20, x1 // consistently using x20 instead of x30
mov x16, x20
xpaclri // ... but xpaclri still operates on x30
cmp x20, x16
b.eq 1f
brk 0x1234
1:
pacia x20, x2
autiasp
ret
.size resign_xpaclri_wrong_reg, .-resign_xpaclri_wrong_reg
// Test that pointer should be authenticated AND checked to be safe-to-sign.
// Checking alone is not enough.
.globl resign_checked_not_authenticated
.type resign_checked_not_authenticated,@function
resign_checked_not_authenticated:
// CHECK-LABEL: GS-PAUTH: signing oracle found in function resign_checked_not_authenticated, basic block {{[^,]+}}, at address
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: pacia x0, x2
// CHECK-NEXT: The 0 instructions that write to the affected registers after any authentication are:
mov x16, x0
xpaci x16
cmp x0, x16
b.eq 1f
brk 0x1234
1:
pacia x0, x2
ret
.size resign_checked_not_authenticated, .-resign_checked_not_authenticated
// The particular register should be *first* written by an authentication
// instruction and *then* that new value should be checked.
// Such code pattern will probably crash at run-time anyway, but let's check
// "safe-to-dereference" -> "trusted" transition.
.globl resign_checked_before_authenticated
.type resign_checked_before_authenticated,@function
resign_checked_before_authenticated:
// CHECK-LABEL: GS-PAUTH: signing oracle found in function resign_checked_before_authenticated, basic block {{[^,]+}}, at address
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: pacia x0, x2
// CHECK-NEXT: The 0 instructions that write to the affected registers after any authentication are:
mov x16, x0
xpaci x16
cmp x0, x16
b.eq 1f
brk 0x1234
1:
autib x0, x1
pacia x0, x2
ret
.size resign_checked_before_authenticated, .-resign_checked_before_authenticated
// Test "high-bits-notbi" check method.
.globl resign_high_bits_tbz_good
.type resign_high_bits_tbz_good,@function
resign_high_bits_tbz_good:
// CHECK-NOT: resign_high_bits_tbz_good
autib x0, x1
eor x16, x0, x0, lsl #1
tbz x16, #62, 1f
brk 0x1234
1:
pacia x0, x2
ret
.size resign_high_bits_tbz_good, .-resign_high_bits_tbz_good
// Check BRK matching briefly - this logic is shared with the "xpac" sequence matcher.
.globl resign_high_bits_tbz_wrong_error
.type resign_high_bits_tbz_wrong_error,@function
resign_high_bits_tbz_wrong_error:
// CHECK-LABEL: GS-PAUTH: signing oracle found in function resign_high_bits_tbz_wrong_error, basic block {{[^,]+}}, at address
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: pacia x0, x2
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
// CHECK-NEXT: 1. {{[0-9a-f]+}}: bl raise_error
paciasp
stp x29, x30, [sp, #-16]!
autib x0, x1
eor x16, x0, x0, lsl #1
tbz x16, #62, 1f
bl raise_error // should trigger breakpoint instead
1:
pacia x0, x2
ldp x29, x30, [sp], #16
autiasp
ret
.size resign_high_bits_tbz_wrong_error, .-resign_high_bits_tbz_wrong_error
.globl resign_high_bits_tbz_wrong_bit
.type resign_high_bits_tbz_wrong_bit,@function
resign_high_bits_tbz_wrong_bit:
// CHECK-LABEL: GS-PAUTH: signing oracle found in function resign_high_bits_tbz_wrong_bit, basic block {{[^,]+}}, at address
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: pacia x0, x2
// CHECK-NEXT: The 0 instructions that write to the affected registers after any authentication are:
autib x0, x1
eor x16, x0, x0, lsl #1
tbz x16, #63, 1f
brk 0x1234
1:
pacia x0, x2
ret
.size resign_high_bits_tbz_wrong_bit, .-resign_high_bits_tbz_wrong_bit
.globl resign_high_bits_tbz_wrong_shift_amount
.type resign_high_bits_tbz_wrong_shift_amount,@function
resign_high_bits_tbz_wrong_shift_amount:
// CHECK-LABEL: GS-PAUTH: signing oracle found in function resign_high_bits_tbz_wrong_shift_amount, basic block {{[^,]+}}, at address
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: pacia x0, x2
// CHECK-NEXT: The 0 instructions that write to the affected registers after any authentication are:
autib x0, x1
eor x16, x0, x0, lsl #2
tbz x16, #62, 1f
brk 0x1234
1:
pacia x0, x2
ret
.size resign_high_bits_tbz_wrong_shift_amount, .-resign_high_bits_tbz_wrong_shift_amount
.globl resign_high_bits_tbz_wrong_shift_type
.type resign_high_bits_tbz_wrong_shift_type,@function
resign_high_bits_tbz_wrong_shift_type:
// CHECK-LABEL: GS-PAUTH: signing oracle found in function resign_high_bits_tbz_wrong_shift_type, basic block {{[^,]+}}, at address
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: pacia x0, x2
// CHECK-NEXT: The 0 instructions that write to the affected registers after any authentication are:
autib x0, x1
eor x16, x0, x0, lsr #1
tbz x16, #62, 1f
brk 0x1234
1:
pacia x0, x2
ret
.size resign_high_bits_tbz_wrong_shift_type, .-resign_high_bits_tbz_wrong_shift_type
.globl resign_high_bits_tbz_wrong_pattern_1
.type resign_high_bits_tbz_wrong_pattern_1,@function
resign_high_bits_tbz_wrong_pattern_1:
// CHECK-LABEL: GS-PAUTH: signing oracle found in function resign_high_bits_tbz_wrong_pattern_1, basic block {{[^,]+}}, at address
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: pacia x0, x2
// CHECK-NEXT: The 0 instructions that write to the affected registers after any authentication are:
autib x0, x1
eor x16, x0, x0, lsl #1
tbz x17, #62, 1f
brk 0x1234
1:
pacia x0, x2
ret
.size resign_high_bits_tbz_wrong_pattern_1, .-resign_high_bits_tbz_wrong_pattern_1
.globl resign_high_bits_tbz_wrong_pattern_2
.type resign_high_bits_tbz_wrong_pattern_2,@function
resign_high_bits_tbz_wrong_pattern_2:
// CHECK-LABEL: GS-PAUTH: signing oracle found in function resign_high_bits_tbz_wrong_pattern_2, basic block {{[^,]+}}, at address
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: pacia x0, x2
// CHECK-NEXT: The 0 instructions that write to the affected registers after any authentication are:
autib x0, x1
eor x16, x10, x0, lsl #1
tbz x16, #62, 1f
brk 0x1234
1:
pacia x0, x2
ret
.size resign_high_bits_tbz_wrong_pattern_2, .-resign_high_bits_tbz_wrong_pattern_2
.globl resign_high_bits_tbz_wrong_pattern_3
.type resign_high_bits_tbz_wrong_pattern_3,@function
resign_high_bits_tbz_wrong_pattern_3:
// CHECK-LABEL: GS-PAUTH: signing oracle found in function resign_high_bits_tbz_wrong_pattern_3, basic block {{[^,]+}}, at address
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: pacia x0, x2
// CHECK-NEXT: The 0 instructions that write to the affected registers after any authentication are:
autib x0, x1
eor x16, x0, x10, lsl #1
tbz x16, #62, 1f
brk 0x1234
1:
pacia x0, x2
ret
.size resign_high_bits_tbz_wrong_pattern_3, .-resign_high_bits_tbz_wrong_pattern_3
// Test checking by loading via the authenticated pointer.
.globl resign_load_good
.type resign_load_good,@function
resign_load_good:
// CHECK-NOT: resign_load_good
autdb x0, x1
ldr x3, [x0]
pacda x0, x2
ret
.size resign_load_good, .-resign_load_good
.globl resign_load_wreg_good
.type resign_load_wreg_good,@function
resign_load_wreg_good:
// CHECK-NOT: resign_load_wreg_good
autdb x0, x1
ldr w3, [x0]
pacda x0, x2
ret
.size resign_load_wreg_good, .-resign_load_wreg_good
.globl resign_load_byte_good
.type resign_load_byte_good,@function
resign_load_byte_good:
// CHECK-NOT: resign_load_byte_good
autdb x0, x1
ldrb w3, [x0]
pacda x0, x2
ret
.size resign_load_byte_good, .-resign_load_byte_good
.globl resign_load_pair_good
.type resign_load_pair_good,@function
resign_load_pair_good:
// CHECK-NOT: resign_load_pair_good
autdb x0, x1
ldp x3, x4, [x0]
pacda x0, x2
ret
.size resign_load_pair_good, .-resign_load_pair_good
.globl resign_load_imm_offset_good
.type resign_load_imm_offset_good,@function
resign_load_imm_offset_good:
// CHECK-NOT: resign_load_imm_offset_good
autdb x0, x1
ldr x3, [x0, #16]
pacda x0, x2
ret
.size resign_load_imm_offset_good, .-resign_load_imm_offset_good
.globl resign_load_preinc_good
.type resign_load_preinc_good,@function
resign_load_preinc_good:
// CHECK-NOT: resign_load_preinc_good
autdb x0, x1
ldr x3, [x0, #16]!
pacda x0, x2
ret
.size resign_load_preinc_good, .-resign_load_preinc_good
.globl resign_load_postinc_good
.type resign_load_postinc_good,@function
resign_load_postinc_good:
// CHECK-NOT: resign_load_postinc_good
autdb x0, x1
ldr x3, [x0], #16
pacda x0, x2
ret
.size resign_load_postinc_good, .-resign_load_postinc_good
.globl resign_load_pair_with_ptr_writeback_good
.type resign_load_pair_with_ptr_writeback_good,@function
resign_load_pair_with_ptr_writeback_good:
// CHECK-NOT: resign_load_pair_with_ptr_writeback_good
autdb x0, x1
ldp x3, x4, [x0, #16]! // three output registers (incl. tied x0 register)
pacda x0, x2
ret
.size resign_load_pair_with_ptr_writeback_good, .-resign_load_pair_with_ptr_writeback_good
.globl resign_load_overwrite
.type resign_load_overwrite,@function
resign_load_overwrite:
// CHECK-LABEL: GS-PAUTH: signing oracle found in function resign_load_overwrite, basic block {{[^,]+}}, at address
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: pacda x0, x2
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
// CHECK-NEXT: 1. {{[0-9a-f]+}}: ldr x0, [x0]
autdb x0, x1
ldr x0, [x0]
pacda x0, x2
ret
.size resign_load_overwrite, .-resign_load_overwrite
.globl resign_load_overwrite_out2
.type resign_load_overwrite_out2,@function
resign_load_overwrite_out2:
// CHECK-LABEL: GS-PAUTH: signing oracle found in function resign_load_overwrite_out2, basic block {{[^,]+}}, at address
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: pacda x0, x2
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
// CHECK-NEXT: 1. {{[0-9a-f]+}}: ldp x10, x0, [x0]
autdb x0, x1
ldp x10, x0, [x0]
pacda x0, x2
ret
.size resign_load_overwrite_out2, .-resign_load_overwrite_out2
.globl resign_load_partial_overwrite
.type resign_load_partial_overwrite,@function
resign_load_partial_overwrite:
// CHECK-LABEL: GS-PAUTH: signing oracle found in function resign_load_partial_overwrite, basic block {{[^,]+}}, at address
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: pacda x0, x2
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
// CHECK-NEXT: 1. {{[0-9a-f]+}}: ldr w0, [x0]
autdb x0, x1
ldr w0, [x0]
pacda x0, x2
ret
.size resign_load_partial_overwrite, .-resign_load_partial_overwrite
.globl resign_load_partial_overwrite_out2
.type resign_load_partial_overwrite_out2,@function
resign_load_partial_overwrite_out2:
// CHECK-LABEL: GS-PAUTH: signing oracle found in function resign_load_partial_overwrite_out2, basic block {{[^,]+}}, at address
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: pacda x0, x2
// CHECK-NEXT: The 1 instructions that write to the affected registers after any authentication are:
// CHECK-NEXT: 1. {{[0-9a-f]+}}: ldp w10, w0, [x0]
autdb x0, x1
ldp w10, w0, [x0]
pacda x0, x2
ret
.size resign_load_partial_overwrite_out2, .-resign_load_partial_overwrite_out2
// Test that base register + offset register addressing mode is rejected.
.globl resign_load_reg_plus_reg
.type resign_load_reg_plus_reg,@function
resign_load_reg_plus_reg:
// CHECK-LABEL: GS-PAUTH: signing oracle found in function resign_load_reg_plus_reg, basic block {{[^,]+}}, at address
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: pacda x0, x2
// CHECK-NEXT: The 0 instructions that write to the affected registers after any authentication are:
autdb x0, x1
ldr x3, [x0, x4]
pacda x0, x2
ret
.size resign_load_reg_plus_reg, .-resign_load_reg_plus_reg
.globl resign_load_reg_plus_reg_in2
.type resign_load_reg_plus_reg_in2,@function
resign_load_reg_plus_reg_in2:
// CHECK-LABEL: GS-PAUTH: signing oracle found in function resign_load_reg_plus_reg_in2, basic block {{[^,]+}}, at address
// CHECK-NEXT: The instruction is {{[0-9a-f]+}}: pacda x0, x2
// CHECK-NEXT: The 0 instructions that write to the affected registers after any authentication are:
autdb x0, x1
ldr x3, [x4, x0]
pacda x0, x2
ret
.size resign_load_reg_plus_reg_in2, .-resign_load_reg_plus_reg_in2
.globl resign_load_unscaled_good
.type resign_load_unscaled_good,@function
resign_load_unscaled_good:
// CHECK-NOT: resign_load_unscaled_good
autdb x0, x1
ldurb w3, [x0, #-1]
pacda x0, x2
ret
.size resign_load_unscaled_good, .-resign_load_unscaled_good
// Any basic block can check at most one register using a multi-instruction
// pointer-checking sequence, but it can contain an arbitrary number of single-
// instruction pointer checks.
.globl many_checked_regs
.type many_checked_regs,@function
many_checked_regs:
// CHECK-NOT: many_checked_regs
autdzb x0
autdzb x1
autdzb x2
b 1f
1:
ldr w3, [x0] // single-instruction check
ldr w3, [x1] // single-instruction check
mov x16, x2 // start of multi-instruction checker sequence
xpacd x16 // ...
cmp x2, x16 // ...
b.eq 2f // end of basic block
brk 0x1234
2:
pacdza x0
pacdza x1
pacdza x2
ret
.size many_checked_regs, .-many_checked_regs
.globl main
.type main,@function
main:
mov x0, 0
ret
.size main, .-main