Message ID | e6d61e792176ff26969e04f70fb6c431461fa13b.1589552055.git.szabolcs.nagy@arm.com |
---|---|
State | New |
Headers | show |
Series | aarch64: branch protection support | expand |
On 15/05/2020 11:40, Szabolcs Nagy wrote: > Return address signing requires unwinder support, which is > present in libgcc since >=gcc-7, however due to bugs the > support may be broken in <gcc-10 (and similarly there may > be issues in custom unwinders), so pac-ret is not always > safe to use. So in assembly code glibc should only use > pac-ret if the compiler uses it too. Unfortunately there > is no predefined feature macro for it set by the compiler > so pac-ret is inferred from the code generation. OK with this fixes below. Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org> > --- > config.h.in | 3 +++ > sysdeps/aarch64/configure | 39 ++++++++++++++++++++++++++++++++++++ > sysdeps/aarch64/configure.ac | 21 +++++++++++++++++++ > 3 files changed, 63 insertions(+) > > diff --git a/config.h.in b/config.h.in > index 506b0c416c..f441470385 100644 > --- a/config.h.in > +++ b/config.h.in > @@ -112,6 +112,9 @@ > /* AArch64 BTI support enabled. */ > #undef HAVE_AARCH64_BTI > > +/* AArch64 PAC-RET code generation is enabled. */ > +#undef HAVE_AARCH64_PAC_RET > + > /* C-SKY ABI version. */ > #undef CSKYABI > Use #define HAVE_AARCH64_PAC_RET 0 instead so we can check the define value instead of the its existence. > diff --git a/sysdeps/aarch64/configure b/sysdeps/aarch64/configure > index 70477a7fa5..5f1cdf5d9b 100644 > --- a/sysdeps/aarch64/configure > +++ b/sysdeps/aarch64/configure > @@ -214,3 +214,42 @@ if test $libc_cv_aarch64_bti = yes; then > $as_echo "#define HAVE_AARCH64_BTI 1" >>confdefs.h > > fi > + > +# Check if glibc is built with return address signing, i.e. > +# if -mbranch-protection=pac-ret is on. We need this because > +# pac-ret relies on unwinder support so it's not safe to use > +# it in assembly code unconditionally, but there is no > +# feature test macro for it in gcc. > +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if pac-ret is enabled" >&5 > +$as_echo_n "checking if pac-ret is enabled... " >&6; } > +if ${libc_cv_aarch64_pac_ret+:} false; then : > + $as_echo_n "(cached) " >&6 > +else > + cat > conftest.c <<EOF > +int bar (void); > +int foo (void) { return bar () + 1; } > +EOF > + libc_cv_aarch64_pac_ret=no > + if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -S -o conftest.s 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; }; } \ > + && { ac_try='grep -q -E '\''(hint( | )+25|paciasp)'\'' conftest.s' > + { { 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; }; } > + then > + libc_cv_aarch64_pac_ret=yes > + fi > + rm -rf conftest.* > +fi > +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_aarch64_pac_ret" >&5 > +$as_echo "$libc_cv_aarch64_pac_ret" >&6; } > +if test $libc_cv_aarch64_pac_ret = yes; then > + $as_echo "#define HAVE_AARCH64_PAC_RET 1" >>confdefs.h > + > +fi > diff --git a/sysdeps/aarch64/configure.ac b/sysdeps/aarch64/configure.ac > index 798f494740..8248ecf2ed 100644 > --- a/sysdeps/aarch64/configure.ac > +++ b/sysdeps/aarch64/configure.ac > @@ -39,3 +39,24 @@ EOF > if test $libc_cv_aarch64_bti = yes; then > AC_DEFINE(HAVE_AARCH64_BTI) > fi > + > +# Check if glibc is built with return address signing, i.e. > +# if -mbranch-protection=pac-ret is on. We need this because Two spaces after period. > +# pac-ret relies on unwinder support so it's not safe to use > +# it in assembly code unconditionally, but there is no > +# feature test macro for it in gcc. > +AC_CACHE_CHECK([if pac-ret is enabled], [libc_cv_aarch64_pac_ret], [dnl > + cat > conftest.c <<EOF > +int bar (void); > +int foo (void) { return bar () + 1; } > +EOF > + libc_cv_aarch64_pac_ret=no > + if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS -S -o conftest.s conftest.c]) \ > + && AC_TRY_COMMAND([grep -q -E '\''(hint( | )+25|paciasp)'\'' conftest.s]) I am not sure this expression is doing what it is intended to do, I think you are matching the gcc output because it also add an extra comment with 'paciasp'. I think what you need here is "(hint[[:space:]]+25|paciasp)". > + then > + libc_cv_aarch64_pac_ret=yes > + fi > + rm -rf conftest.*]) > +if test $libc_cv_aarch64_pac_ret = yes; then > + AC_DEFINE(HAVE_AARCH64_PAC_RET) > +fi >
diff --git a/config.h.in b/config.h.in index 506b0c416c..f441470385 100644 --- a/config.h.in +++ b/config.h.in @@ -112,6 +112,9 @@ /* AArch64 BTI support enabled. */ #undef HAVE_AARCH64_BTI +/* AArch64 PAC-RET code generation is enabled. */ +#undef HAVE_AARCH64_PAC_RET + /* C-SKY ABI version. */ #undef CSKYABI diff --git a/sysdeps/aarch64/configure b/sysdeps/aarch64/configure index 70477a7fa5..5f1cdf5d9b 100644 --- a/sysdeps/aarch64/configure +++ b/sysdeps/aarch64/configure @@ -214,3 +214,42 @@ if test $libc_cv_aarch64_bti = yes; then $as_echo "#define HAVE_AARCH64_BTI 1" >>confdefs.h fi + +# Check if glibc is built with return address signing, i.e. +# if -mbranch-protection=pac-ret is on. We need this because +# pac-ret relies on unwinder support so it's not safe to use +# it in assembly code unconditionally, but there is no +# feature test macro for it in gcc. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if pac-ret is enabled" >&5 +$as_echo_n "checking if pac-ret is enabled... " >&6; } +if ${libc_cv_aarch64_pac_ret+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat > conftest.c <<EOF +int bar (void); +int foo (void) { return bar () + 1; } +EOF + libc_cv_aarch64_pac_ret=no + if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -S -o conftest.s 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; }; } \ + && { ac_try='grep -q -E '\''(hint( | )+25|paciasp)'\'' conftest.s' + { { 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; }; } + then + libc_cv_aarch64_pac_ret=yes + fi + rm -rf conftest.* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_aarch64_pac_ret" >&5 +$as_echo "$libc_cv_aarch64_pac_ret" >&6; } +if test $libc_cv_aarch64_pac_ret = yes; then + $as_echo "#define HAVE_AARCH64_PAC_RET 1" >>confdefs.h + +fi diff --git a/sysdeps/aarch64/configure.ac b/sysdeps/aarch64/configure.ac index 798f494740..8248ecf2ed 100644 --- a/sysdeps/aarch64/configure.ac +++ b/sysdeps/aarch64/configure.ac @@ -39,3 +39,24 @@ EOF if test $libc_cv_aarch64_bti = yes; then AC_DEFINE(HAVE_AARCH64_BTI) fi + +# Check if glibc is built with return address signing, i.e. +# if -mbranch-protection=pac-ret is on. We need this because +# pac-ret relies on unwinder support so it's not safe to use +# it in assembly code unconditionally, but there is no +# feature test macro for it in gcc. +AC_CACHE_CHECK([if pac-ret is enabled], [libc_cv_aarch64_pac_ret], [dnl + cat > conftest.c <<EOF +int bar (void); +int foo (void) { return bar () + 1; } +EOF + libc_cv_aarch64_pac_ret=no + if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS -S -o conftest.s conftest.c]) \ + && AC_TRY_COMMAND([grep -q -E '\''(hint( | )+25|paciasp)'\'' conftest.s]) + then + libc_cv_aarch64_pac_ret=yes + fi + rm -rf conftest.*]) +if test $libc_cv_aarch64_pac_ret = yes; then + AC_DEFINE(HAVE_AARCH64_PAC_RET) +fi