This patchset enables PAC and BTI for nettle.
Daiki has a patch here that I gave commented on: - https://git.lysator.liu.se/nettle/nettle/-/merge_requests/65
I also have an open public github with these changes at: https://github.com/billatarm/nettle/pull/1
Overally the patches are very similair, I just chose a different construct in how the various things are propgrated from configure to m4 which I think is a better seperation of duties.
I wanted to share these over the mailing list as I am unable to create a fork on the GitLab instance and send a PR that way.
Bill Roberts (2): x68_64: move machine specific asm to arch asm.m4 aarch64: enable PAC/BTI
arm64/machine.m4 | 57 +++++++++++++++++++++++++++++++++++++++++++++++ asm.m4 | 2 +- config.m4.in | 4 ++++ configure.ac | 43 +++++++++++++++++++++++++++++++++++ x86_64/machine.m4 | 5 +++++ 5 files changed, 110 insertions(+), 1 deletion(-)
Move the endbranch macro from the toplevel asm.m4 to the machine specific x86_64/asm.m4. This follows the powerpc prologue and epilogue approach.
Signed-off-by: Bill Roberts bill.roberts@arm.com --- asm.m4 | 2 +- x86_64/machine.m4 | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/asm.m4 b/asm.m4 index 2bb1068c..40fbd202 100644 --- a/asm.m4 +++ b/asm.m4 @@ -30,7 +30,7 @@ define(`GMP_NUMB_BITS',`')dnl define(`PROLOGUE', `.globl C_NAME($1) DECLARE_FUNC(C_NAME($1)) -C_NAME($1): ASM_X86_ENDBR') +C_NAME($1):')
define(`EPILOGUE', `ifelse(ELF_STYLE,yes, diff --git a/x86_64/machine.m4 b/x86_64/machine.m4 index 28b258cd..3fc3098b 100644 --- a/x86_64/machine.m4 +++ b/x86_64/machine.m4 @@ -1,3 +1,8 @@ +define(`PROLOGUE', +`.globl C_NAME($1) +DECLARE_FUNC(C_NAME($1)) +C_NAME($1): ASM_X86_ENDBR') + C OFFSET(i) C Expands to 4*i, or to the empty string if i is zero define(`OFFSET', `ifelse($1,0,,eval(4*$1))')
Enable Pointer Authentication Codes (PAC) and Branch Target Identification (BTI) support for ARM 64 targets.
PAC works by signing the LR with either an A key or B key and verifying the return address. Since the assembly code does not push and pop the link register to the stack, and it remains in the register file, their is no need to sign the LR, so PAC is essentially just adding it to the GNU notes section for auditing purposes.
BTI works by marking all call and jump positions with bti c and bti j instructions. If execution control transfers via an indirect branch or call to an instruction other than a BTI instruction, the execution is killed via SIGILL.
For BTI to work, all object files linked for a unit of execution, whether an executable or a library must have the GNU Notes section of the ELF file marked to indicate BTI support. This is so loader/linkers can apply the proper permission bits (PROT_BRI) on the memory region.
PAC can also be annotated in the GNU ELF notes section, but it's not required for enablement, as interleaved PAC and non-pac code works as expected since it's the callee that performs all the checking.
Testing was done under the following CFLAGS and CXXFLAGS for all combinations: 1. -mbranch-protection=none 2. -mbranch-protection=standard 3. -mbranch-protection=pac-ret 4. -mbranch-protection=pac-ret+b-key 5. -mbranch-protection=bti
Signed-off-by: Bill Roberts bill.roberts@arm.com --- arm64/machine.m4 | 57 ++++++++++++++++++++++++++++++++++++++++++++++++ config.m4.in | 4 ++++ configure.ac | 43 ++++++++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+)
diff --git a/arm64/machine.m4 b/arm64/machine.m4 index d47825ae..9abcecd7 100644 --- a/arm64/machine.m4 +++ b/arm64/machine.m4 @@ -1,3 +1,46 @@ +dnl Support macros for +dnl - Armv8.3-A Pointer Authentication and +dnl - Armv8.5-A Branch Target Identification +dnl Further documentation can be found at: +dnl - https://developer.arm.com/documentation/101028/0012/5--Feature-test-macros +dnl Note that the hint instrunctions are used which means that on older assemblers they will assemble +dnl and that they are in the NOP space on older architectures and are NOP'd. +define(`bti_c', `hint #34') + +dnl ASM_AARCH64_BTI_ENABLE - BTI Enabled +dnl GNU Notes section in ELF contain these values and can be read with readelf -n +dnl BTI Is required to be marked so the linker knows what mprotect flags to enable +dnl BTI is shown enabled in bit 0 and PAC in bit 1 for GNU Notes. This is required +dnl for the loader to set PROT_BTI on the shared library pages. +define(`GNU_PROPERTY_AARCH64_BTI',`ifelse( + ASM_AARCH64_BTI_ENABLE, `1', `1', + `0'dnl + )'dnl +) + +dnl ASM_AARCH64_PAC_A_ENABLE - PAC A Key Enabled (nothing to do as leaf functions) +dnl ASM_AARCH64_PAC_B_ENABLE - PAC B Key Enabled (nothing to do as leaf functions) +dnl GNU Notes PAC bit is a nice to have for auditing purposes and is located in bit 2. +dnl NOTE: Even though GNU Notes only marks PAC enabled or not and is agnostic, we'll +dnl keep the distinction between the A and B key so the plumbing is present if an +dnl asm routine ever needs to use pac instructions. +define(`GNU_PROPERTY_AARCH64_POINTER_AUTH', `ifelse( + ASM_AARCH64_PAC_A_ENABLE, `1', `2', + ASM_AARCH64_PAC_B_ENABLE, `1', `2', + `0'dnl + )'dnl +) + +define(`bti_prologue', `ifelse( + ASM_AARCH64_BTI_ENABLE, `1', `bti_c', + )' +) + +define(`PROLOGUE', +`.globl C_NAME($1) +DECLARE_FUNC(C_NAME($1)) +C_NAME($1): bti_prologue') + C Get 32-bit floating-point register from vector register C SFP(VR) define(`SFP',``s'substr($1,1,len($1))') @@ -69,3 +112,17 @@ define(`AESD_LAST_ROUND_4B', m4_assert_numargs(6)` AESD_LAST_ROUND_1B($3,$5,$6) AESD_LAST_ROUND_1B($4,$5,$6) ') + +ifelse(ASM_IS_ELF, `1', ` + .pushsection .note.gnu.property, "a"; + .balign 8; + .long 4; + .long 0x10; + .long 0x5; + .asciz "GNU"; + .long 0xc0000000; /* GNU_PROPERTY_AARCH64_FEATURE_1_AND */ + .long 4; + .long(GNU_PROPERTY_AARCH64_POINTER_AUTH | GNU_PROPERTY_AARCH64_BTI); + .long 0; + .popsection; +') diff --git a/config.m4.in b/config.m4.in index b98a5817..56cd5f34 100644 --- a/config.m4.in +++ b/config.m4.in @@ -1,5 +1,6 @@ define(`srcdir', ``@srcdir@'')dnl define(`SYMBOL_PREFIX', `@ASM_SYMBOL_PREFIX@'`$1')dnl +define(`ASM_IS_ELF', `@ASM_IS_ELF@')dnl define(`ELF_STYLE', `@ASM_ELF_STYLE@')dnl define(`COFF_STYLE', `@ASM_COFF_STYLE@')dnl define(`TYPE_FUNCTION', `@ASM_TYPE_FUNCTION@')dnl @@ -12,6 +13,9 @@ define(`WORDS_BIGENDIAN', `@ASM_WORDS_BIGENDIAN@')dnl define(`ASM_X86_ENDBR',`@ASM_X86_ENDBR@')dnl define(`ASM_X86_MARK_CET_ALIGN',`@ASM_X86_MARK_CET_ALIGN@')dnl define(`ASM_PPC_WANT_R_REGISTERS',`@ASM_PPC_WANT_R_REGISTERS@')dnl +define(`ASM_AARCH64_BTI_ENABLE',`@ASM_AARCH64_BTI_ENABLE@')dnl +define(`ASM_AARCH64_PAC_A_ENABLE',`@ASM_AARCH64_PAC_A_ENABLE@')dnl +define(`ASM_AARCH64_PAC_B_ENABLE',`@ASM_AARCH64_PAC_B_ENABLE@')dnl divert(1) @ASM_X86_MARK_CET@ @ASM_MARK_NOEXEC_STACK@ diff --git a/configure.ac b/configure.ac index fa3d8cee..3309517e 100644 --- a/configure.ac +++ b/configure.ac @@ -1078,7 +1078,47 @@ if test "$nettle_cv_asm_x86_gnu_property" = yes; then .popsection' fi
+dnl See: https://developer.arm.com/documentation/101028/0012/5--Feature-test-macros +AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM([ + #if !defined(__ARM_FEATURE_BTI_DEFAULT) && __ARM_FEATURE_BTI_DEFAULT != 1 + #error "BTI is not enabled" + #endif + ]) +], +[ASM_AARCH64_BTI_ENABLE=1], +[]) +AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM([ + #if !(defined(__ARM_FEATURE_PAC_DEFAULT) && __ARM_FEATURE_PAC_DEFAULT & 1) + #error "PAC A Key not supported" + #endif + ]) +], +[ASM_AARCH64_PAC_A_ENABLE=1], +[]) +AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM([ + #if !(defined(__ARM_FEATURE_PAC_DEFAULT) && __ARM_FEATURE_PAC_DEFAULT & 2) + #error "PAC B Key not supported" + #endif + ]) +], +[ASM_AARCH64_PAC_B_ENABLE=1], +[]) + +AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM([ + #if !defined __ELF__ + #error ELF not detected + #endif + ]) +], +[ASM_IS_ELF=1], +[ASM_IS_ELF=0]) + AC_SUBST(ASM_SYMBOL_PREFIX) +AC_SUBST(ASM_IS_ELF) AC_SUBST(ASM_ELF_STYLE) AC_SUBST(ASM_COFF_STYLE) AC_SUBST(ASM_TYPE_FUNCTION) @@ -1092,6 +1132,9 @@ AC_SUBST(EMULATOR) AC_SUBST(ASM_X86_ENDBR) AC_SUBST(ASM_X86_MARK_CET) AC_SUBST(ASM_X86_MARK_CET_ALIGN) +AC_SUBST(ASM_AARCH64_BTI_ENABLE) +AC_SUBST(ASM_AARCH64_PAC_A_ENABLE) +AC_SUBST(ASM_AARCH64_PAC_B_ENABLE)
AC_SUBST(LIBNETTLE_MAJOR) AC_SUBST(LIBNETTLE_MINOR)
nettle-bugs@lists.lysator.liu.se