Baber
Baber

Reputation: 321

Clang compiler flag -mbranch-protection=pac-ret+bti not generating bti instruction

I am experiencing a strange behavior of the clang compiler flag -mbranch-protection=pac-ret+bti. By looking into the documentation, the intended behavior appears to generate both PAC (paciasp) as well as BTI instructions. I am seeing paciasp instruction but not the BTI instruction in the assembly when compiling with -mbranch-protection=pac-ret+bti.

When compiling with -mbranch-protection=bti, the BTI instruction is being generated at the start of the function marking the valid entry point in a function as it should be.

This seems a bit unusual. PAC protects from ROP attacks, while BTI protects from JOP attacks. Is this a bug in the implementation? Any further clarification will be appreciated.

Note that BTI is supported from armv8.5-a and PAC from armv8.3-a onwards. The compiler will generate nop for the previous architectures. Clang version 12.0 is used in the test.

Simple Code Example (test.c):

#include<stdio.h>

int main(int argc, char** argv){
    printf("%s", "Hello Main!");
}

Compilation with PAC+BTI:

$ clang -S -mbranch-protection=pac-ret+bti -arch arm64e -march=armv8.7-a -o test.s test.c

Output:

main:
  paciasp
  -----
  -----
  -----
  retaa

Note: No BTI instruction generated in this case.

Compilation with BTI:

clang -S -mbranch-protection=bti -arch arm64e -march=armv8.7-a -o test.s test.c

Output:

main:
  bti c
  -----
  -----
  -----

Upvotes: 2

Views: 564

Answers (1)

M A
M A

Reputation: 11

When activating PAC with BTI, paciasp instruction serves also as a landing pad (BTI-like). This is an optimization that is done by ARM to save one extra instruction. No bugs.

Upvotes: 1

Related Questions