From ec96daabd8fad129ea3660d479fa63941712c410 Mon Sep 17 00:00:00 2001
From: Sudakshina Das <sudi.das@arm.com>
Date: Thu, 26 Mar 2020 11:49:48 +0000
Subject: [PATCH 12/12] aarch64: Configure option to build glibc with branch
 protection

If gcc is configured with --enable-standard-branch-protection then
the built glibc should have branch protection suppport too, which
includes bti and pac-ret. The new configure option is only for
additional configure checks, it does not try to add new CFLAGS
(i.e. -mbranch-protection=standard ), it expects gcc to default to
using branch protection, since likely the static linked compiler
libraries are not compatible otherwise.

The -z force-bti linker flag is also passed with branch protection,
but this is not very useful: by default the BTI property marking
is set on the linker output if all linker inputs have it and it is
silently missing otherwise, -z force-bti at least warns if an input
is missing the property, but that's not a fatal error.
(Using --fatal-warnings ld flag does not work in the test system.)

Co-authored-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
---
 configure                    | 14 +++++++++++++-
 configure.ac                 |  6 ++++++
 sysdeps/aarch64/Makefile     |  4 ++++
 sysdeps/aarch64/configure    | 31 +++++++++++++++++++++++++++++++
 sysdeps/aarch64/configure.ac | 19 +++++++++++++++++++
 5 files changed, 73 insertions(+), 1 deletion(-)

diff --git a/configure b/configure
index 8df47d61f8..fff5734f6d 100755
--- a/configure
+++ b/configure
@@ -794,6 +794,7 @@ enable_pt_chown
 enable_tunables
 enable_mathvec
 enable_cet
+enable_standard_branch_protection
 with_cpu
 '
       ac_precious_vars='build_alias
@@ -1471,6 +1472,9 @@ Optional Features:
                           depends on architecture]
   --enable-cet            enable Intel Control-flow Enforcement Technology
                           (CET), x86 only
+  --enable-standard-branch-protection
+                          enable AArch64 Branch Target Identification and
+                          Return Address Signing, AArch64 only
 
 Optional Packages:
   --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
@@ -3785,7 +3789,7 @@ main ()
 {
 
 #ifndef __CET__
-#error no CET compiler support
+# error no CET compiler support
 #endif
   ;
   return 0;
@@ -3806,6 +3810,14 @@ else
 fi
 
 
+# Check whether --enable-standard-branch-protection was given.
+if test "${enable_standard_branch_protection+set}" = set; then :
+  enableval=$enable_standard_branch_protection; libc_cv_branch_protection=$enableval
+else
+  libc_cv_branch_protection=no
+fi
+
+
 # We keep the original values in `$config_*' and never modify them, so we
 # can write them unchanged into config.make.  Everything else uses
 # $machine, $vendor, and $os, and changes them whenever convenient.
diff --git a/configure.ac b/configure.ac
index 5f229679a9..e08b0f3766 100644
--- a/configure.ac
+++ b/configure.ac
@@ -486,6 +486,12 @@ AC_ARG_ENABLE([cet],
 	      [enable_cet=$enableval],
 	      [enable_cet=$libc_cv_compiler_default_cet])
 
+AC_ARG_ENABLE([standard-branch-protection],
+	      AC_HELP_STRING([--enable-standard-branch-protection],
+			     [enable AArch64 Branch Target Identification and Return Address Signing, AArch64 only]),
+	      [libc_cv_branch_protection=$enableval],
+	      [libc_cv_branch_protection=no])
+
 # We keep the original values in `$config_*' and never modify them, so we
 # can write them unchanged into config.make.  Everything else uses
 # $machine, $vendor, and $os, and changes them whenever convenient.
diff --git a/sysdeps/aarch64/Makefile b/sysdeps/aarch64/Makefile
index 5ae8b082b0..313c371e72 100644
--- a/sysdeps/aarch64/Makefile
+++ b/sysdeps/aarch64/Makefile
@@ -1,5 +1,9 @@
 long-double-fcts = yes
 
+ifeq (yes,$(enable-branch-protection))
+sysdep-LDFLAGS += -Wl,-z,force-bti
+endif
+
 ifeq ($(subdir),elf)
 sysdep-dl-routines += dl-bti
 endif
diff --git a/sysdeps/aarch64/configure b/sysdeps/aarch64/configure
index 5bd355a691..83a6c8c852 100644
--- a/sysdeps/aarch64/configure
+++ b/sysdeps/aarch64/configure
@@ -172,3 +172,34 @@ else
   config_vars="$config_vars
 default-abi = lp64"
 fi
+
+if test "$libc_cv_branch_protection" = yes; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for branch protection support" >&5
+$as_echo_n "checking for branch protection support... " >&6; }
+if ${libc_cv_branch_protection_support+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat > conftest.c <<EOF
+void foo (void) { }
+EOF
+    libc_cv_branch_protection_support=no
+    if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -nostdlib -nostartfiles $no_ssp -fPIC -shared -Wl,-z,force-bti,--fatal-warnings -o conftest.so conftest.c'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; } \
+       && LC_ALL=C $READELF -Wn conftest.so | \
+	  grep -q 'NT_GNU_PROPERTY_TYPE_0.*AArch64 feature:.* BTI'; then
+      libc_cv_branch_protection_support=yes
+    fi
+    rm -rf conftest.*
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_branch_protection_support" >&5
+$as_echo "$libc_cv_branch_protection_support" >&6; }
+  if test $libc_cv_branch_protection_support = no; then
+    as_fn_error $? "branch-protection is enabled, but the toolchain does not support it." "$LINENO" 5
+  fi
+fi
+config_vars="$config_vars
+enable-branch-protection = $libc_cv_branch_protection"
diff --git a/sysdeps/aarch64/configure.ac b/sysdeps/aarch64/configure.ac
index 7851dd4dac..d16ba3710a 100644
--- a/sysdeps/aarch64/configure.ac
+++ b/sysdeps/aarch64/configure.ac
@@ -20,3 +20,22 @@ if test $libc_cv_aarch64_be = yes; then
 else
   LIBC_CONFIG_VAR([default-abi], [lp64])
 fi
+
+if test "$libc_cv_branch_protection" = yes; then
+  AC_CACHE_CHECK([for branch protection support],
+    [libc_cv_branch_protection_support],
+    [cat > conftest.c <<EOF
+void foo (void) { }
+EOF
+    libc_cv_branch_protection_support=no
+    if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -nostdlib -nostartfiles $no_ssp -fPIC -shared -Wl,-z,force-bti,--fatal-warnings -o conftest.so conftest.c]) \
+       && LC_ALL=C $READELF -Wn conftest.so | \
+	  grep -q 'NT_GNU_PROPERTY_TYPE_0.*AArch64 feature:.* BTI'; then
+      libc_cv_branch_protection_support=yes
+    fi
+    rm -rf conftest.*])
+  if test $libc_cv_branch_protection_support = no; then
+    AC_MSG_ERROR([branch-protection is enabled, but the toolchain does not support it.])
+  fi
+fi
+LIBC_CONFIG_VAR([enable-branch-protection], [$libc_cv_branch_protection])
-- 
2.17.1

