Skip to content

Incorrect code generation with -arch arm64e -mbranch-protection=standard or =pac-ret #60239

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
lelegard opened this issue Jan 23, 2023 · 3 comments
Labels
backend:AArch64 invalid Resolved as invalid, i.e. not a bug

Comments

@lelegard
Copy link

Summary

On macOS, Arm64, the combination of options -arch arm64e -mbranch-protection=standard generates invalid code (redundant pointer authentication) leading to application crash on return.

Platform

Demonstrated on a Macbook with M1 chip, macOS 13.1, arm64e API enabled, Apple clang 14.0.0. This is the clang version coming with the latest "Command Line Tools for Xcode 14.2" from December 13, 2022.

$ sw_vers 
ProductName:            macOS
ProductVersion:         13.1
BuildVersion:           22C65
$ 
$ uname -a
Darwin mactest 22.2.0 Darwin Kernel Version 22.2.0: Fri Nov 11 02:04:44 PST 2022; root:xnu-8792.61.2~4/RELEASE_ARM64_T8103 arm64
$ 
$ nvram boot-args
boot-args       -arm64e_preview_abi
$ 
$ clang --version
Apple clang version 14.0.0 (clang-1400.0.29.202)
Target: arm64-apple-darwin22.2.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
$ 

Demonstration

This simple "hello world" code crashes with -arch arm64e -mbranch-protection=standard. It does not crash without -mbranch-protection or with -mbranch-protection=bti only.

$ cat hi.c
#include <stdio.h>
int main(int argc, char* argv[])
{
    printf("hi\n");
}
$
$ clang -O2 -march=armv8.5-a -arch arm64e hi.c -o hi
$ ./hi
hi
$ clang -O2 -march=armv8.5-a -arch arm64e hi.c -o hi -mbranch-protection=bti
$ ./hi
hi
$ clang -O2 -march=armv8.5-a -arch arm64e hi.c -o hi -mbranch-protection=standard
$ ./hi
hi
Segmentation fault: 11
$

Details

The combination -arch arm64e -mbranch-protection=standard is fatal. The same problem is seen with -mbranch-protection=pac-ret instead of standard (the latter includes the former).

  • -mbranch-protection=pac-ret or =standard authenticates the caller's return address using pacia x30, sp, updating x30 with a pointer authentication code.
  • -arch arm64e authenticates the caller's return address using pacibsp (same as pacib x30, sp). This second instruction trashes the PAC in x30, recomputing a PAC with key B.
  • The return sequence is autibsp and retaa. The autibsp removes the PAC from x30. When retaa authenticates x30, there is no longer any PAC, the authentication fails and the program crashes.

Solution: There must be only one authentication sequence. Using -mbranch-protection=pac-ret or =standard shall not add PACIA instructions when -arch arm64e is specified since pointer authentication is already used. Alternatively, an error message may report the incompatible options. But no invalid code should be generated.

Generated code below:

$ clang -O2 -march=armv8.5-a -arch arm64e hi.c -mbranch-protection=standard -S -o -
        .section        __TEXT,__text,regular,pure_instructions
        .build_version macos, 13, 0     sdk_version 13, 1
        .ptrauth_abi_version 0
        .globl  _main                           ; -- Begin function main
        .p2align        2
_main:                                  ; @main
        .cfi_startproc
; %bb.0:
        bti     c
        pacia   x30, sp     <------------ generated by -mbranch-protection=standard
        .cfi_negate_ra_state
        pacibsp             <------------ generated by -arch arm64e
        stp     x29, x30, [sp, #-16]!           ; 16-byte Folded Spill
        mov     x29, sp
        .cfi_def_cfa w29, 16
        .cfi_offset w30, -8
        .cfi_offset w29, -16
Lloh0:
        adrp    x0, l_str@PAGE
Lloh1:
        add     x0, x0, l_str@PAGEOFF
        bl      _puts
        mov     w0, #0
        ldp     x29, x30, [sp], #16             ; 16-byte Folded Reload
        autibsp             <------------ generated by -arch arm64e
        retaa               <------------ generated by -mbranch-protection=standard
        .loh AdrpAdd    Lloh0, Lloh1
        .cfi_endproc
                                        ; -- End function
        .section        __TEXT,__cstring,cstring_literals
l_str:                                  ; @str
        .asciz  "hi"

.subsections_via_symbols
$ 
@llvmbot
Copy link
Member

llvmbot commented Jan 23, 2023

@llvm/issue-subscribers-backend-aarch64

@efriedma-quic
Copy link
Collaborator

We don't track issues with Apple clang here; Apple clang has changes that aren't part of the llvm.org source tree. See https://developer.apple.com/bug-reporting/ for instructions to report issues to Apple.

@efriedma-quic efriedma-quic closed this as not planned Won't fix, can't repro, duplicate, stale Jan 23, 2023
@EugeneZelenko EugeneZelenko added the invalid Resolved as invalid, i.e. not a bug label Jan 23, 2023
@lelegard
Copy link
Author

For the record, submitted to Apple with reference FB11965434

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:AArch64 invalid Resolved as invalid, i.e. not a bug
Projects
None yet
Development

No branches or pull requests

4 participants