[llvm-branch-commits] [llvm] [BOLT] Gadget scanner: add less strict version of tail call checker (PR #188974)

Anatoly Trosinenko via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Sat Mar 28 02:13:15 PDT 2026


atrosinenko wrote:

> what other cases benefit from this PR?

It might be possible to omit the fine-grained toggles "activate on return instructions" (no heuristics) vs. "activate on ret-like tail call branches" (relies on heuristics). However, the check performed by `shouldReportUnsafeTailCall` still has to be split into the lightweight and the stricter variants. This could technically be done by invoking `shouldReportUnsafeTailCall` iff `EnabledDetectors & (opts::GS_PTRAUTH_TAIL_CALLS | opts::GS_PTRAUTH_RETURN_TARGETS)` while passing `Strict = EnabledDetectors & opts::GS_PTRAUTH_TAIL_CALLS` and not modifying the command line interface exposed to the user.

Anyway, with pac-ret enabled in the compiler, we would expect any epilogue to include the authentication as long as LR was reloaded from the stack. On the other hand, inserting the full-fledged checks into tail calls that the authentication **succeeded** is a significantly less obvious trade-off. Currently, we don't have a straightforward way to ask gadget scanner to detect both
```
bad_ret:
  stp     x29, x30, [sp, #-0x10]!
  ldp     x29, x30, [sp], #0x10
  ret                             ; implicitly "ret x30"

bad_tail_call:
  stp     x29, x30, [sp, #-0x10]!
  ldp     x29, x30, [sp], #0x10
  b       callee                  ; does not use x30 itself, it is later used in the callee
```
and requiring something along these lines instead
```
good_ret:
  paciasp
  stp     x29, x30, [sp, #-0x10]!
  ldp     x29, x30, [sp], #0x10
  autiasp
  ret

good_tail_call:
  paciasp
  stp     x29, x30, [sp, #-0x10]!
  ldp     x29, x30, [sp], #0x10
  autiasp
  b       callee
```
without requiring every tail call to be done like this
```
good_tail_call:
  paciasp
  stp     x29, x30, [sp, #-0x10]!
  ldp     x29, x30, [sp], #0x10
  autiasp
  ldr     x16, [x30]              ; check
  b       callee
```
or even
```
good_tail_call:
  paciasp
  stp     x29, x30, [sp, #-0x10]!
  ldp     x29, x30, [sp], #0x10
  autiasp
  mov     x16, x30                ; check
  xpaclri                         ; check
  cmp     x16, x30                ; check
  b.eq    .Lsuccess               ; check
  brk     0xc470                  ; check
.Lsuccess:
  b       callee
```
Well, we could pass `--scanners=ptrauth-pac-ret,ptrauth-tail-calls --auth-traps-on-failure`: 1) require *safe-to-dereference* return destination for regular returns, 2) require *trusted* LR before tail calls, 3) promote *safe-to-deference* register property to *trusted* by promising that authentication failure results in an error - but that's quite hackish :)

By the way, now I wonder whether I should additionally enable `GS_PTRAUTH_SIGN_ORACLES` in the `ptrauth-pac-ret` preset to catch the code like this artificial example:
```
lr_clobbered_before_signing:
  mov x30, x0
  paciasp
  stp     x29, x30, [sp, #-0x10]!
  ldp     x29, x30, [sp], #0x10
  autiasp
  ret
```

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


More information about the llvm-branch-commits mailing list