diff mbox series

[3/7] configure: add CET support

Message ID 20190313124042.12855-4-pbonzini@redhat.com
State New
Headers show
Series CET support | expand

Commit Message

Paolo Bonzini March 13, 2019, 12:40 p.m. UTC
CET requires object files to note which features are supported.  The linker
will merge them to the set of features that are supported by all object
files.  The compiler creates these notes when the -fcf-protection option
is passed, but we have to blacklist some object files that only support
a subset of the full CET feature set.  The next patches will improve the
situation so that QEMU can be built with full protection.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 configure          | 27 +++++++++++++++++++++++++++
 Makefile.target    |  3 +++
 util/Makefile.objs |  5 +++++
 3 files changed, 35 insertions(+)

Comments

Eric Blake March 13, 2019, 12:59 p.m. UTC | #1
On 3/13/19 7:40 AM, Paolo Bonzini wrote:
> CET requires object files to note which features are supported.  The linker

CET = ?

> will merge them to the set of features that are supported by all object
> files.  The compiler creates these notes when the -fcf-protection option
> is passed, but we have to blacklist some object files that only support
> a subset of the full CET feature set.  The next patches will improve the
> situation so that QEMU can be built with full protection.
> 
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  configure          | 27 +++++++++++++++++++++++++++
>  Makefile.target    |  3 +++
>  util/Makefile.objs |  5 +++++
>  3 files changed, 35 insertions(+)
> 

> @@ -1757,6 +1762,7 @@ disabled with --disable-FEATURE, default is enabled if available:
>    lzfse           support of lzfse compression library
>                    (for reading lzfse-compressed dmg images)
>    seccomp         seccomp support
> +  cet             Control-flow Enforcement Technology

Ah. Still, might be worth mentioning in the commit body as well.
Paolo Bonzini March 13, 2019, 1:28 p.m. UTC | #2
On 13/03/19 13:59, Eric Blake wrote:
> On 3/13/19 7:40 AM, Paolo Bonzini wrote:
>> CET requires object files to note which features are supported.  The linker
> 
> CET = ?
> 
>> will merge them to the set of features that are supported by all object
>> files.  The compiler creates these notes when the -fcf-protection option
>> is passed, but we have to blacklist some object files that only support
>> a subset of the full CET feature set.  The next patches will improve the
>> situation so that QEMU can be built with full protection.
>>
>> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
>> ---
>>  configure          | 27 +++++++++++++++++++++++++++
>>  Makefile.target    |  3 +++
>>  util/Makefile.objs |  5 +++++
>>  3 files changed, 35 insertions(+)
>>
> 
>> @@ -1757,6 +1762,7 @@ disabled with --disable-FEATURE, default is enabled if available:
>>    lzfse           support of lzfse compression library
>>                    (for reading lzfse-compressed dmg images)
>>    seccomp         seccomp support
>> +  cet             Control-flow Enforcement Technology
> 
> Ah. Still, might be worth mentioning in the commit body as well.

Actually I might change it to cf-protection, since that's what the GCC
flag is named.

Paolo
Florian Weimer March 13, 2019, 1:31 p.m. UTC | #3
* Paolo Bonzini:

> Actually I might change it to cf-protection, since that's what the GCC
> flag is named.

The GCC flag is supposed to generic, so that it can be used for similar
features other architectures might provide.  Your code looks rather
x86-centric to me, so CET seems appropriate here.

Thanks,
Florian
Paolo Bonzini March 13, 2019, 1:35 p.m. UTC | #4
On 13/03/19 14:31, Florian Weimer wrote:
> * Paolo Bonzini:
> 
>> Actually I might change it to cf-protection, since that's what the GCC
>> flag is named.
> 
> The GCC flag is supposed to generic, so that it can be used for similar
> features other architectures might provide.  Your code looks rather
> x86-centric to me, so CET seems appropriate here.

The configure option is generic.  When enabled, the Makefiles will
*disable* CET features selectively on object files that do not support
that feature, and the disabled feature will propagate to the binary.

Even without any further target-specific patches, user-mode emulation
binaries will always have shadow stacks, because they don't need
coroutines and don't include the problematic util/coroutine-ucontext.o
object file.  Likewise, system-mode emulation binaries will have
indirect branch tracking if built without binary translation support
(i.e. Xen/KVM only).

What the next patches do is to enable the full set of control flow
protections on all binaries on Intel targets.  However, a subset can be
made available without any target-specific code, and that part is
supposed to be generic just like GCC's -fcf-protection flag.

And yes, all this probably should go in more verbose commit messages...

Paolo
Richard Henderson March 14, 2019, 12:56 a.m. UTC | #5
On 3/13/19 5:40 AM, Paolo Bonzini wrote:
> +##########################################
> +# detect CET support in the toolchain
> +
> +if test "$cet" != no; then
> +  write_c_skeleton;
> +  if ! compile_prog "-fcf-protection" "" ; then
> +    if test "$cet" = yes; then
> +      feature_not_found "cet" 'CET is not supported by your toolchain'
> +    fi
> +    cet=no
> +  fi
> +fi
> +if test "$cet" = ""; then
> +  cet=yes
> +  QEMU_CFLAGS="-fcf-protection $QEMU_CFLAGS"
> +fi

Hmm.  The gcc for aarch64 names the similar feature -mbranch-protection.  I'm
rather annoyed that the i386 gcc folk appropriated a generic -f name without
actually making the feature generic at the same time.

Thankfully the aarch64 version does not include shadow stacks, and so is less
invasive into the normal abi -- ARM uses pointer authentication instead.


r~
Paolo Bonzini March 14, 2019, 10:46 a.m. UTC | #6
On 14/03/19 01:56, Richard Henderson wrote:
> Hmm.  The gcc for aarch64 names the similar feature -mbranch-protection.  I'm
> rather annoyed that the i386 gcc folk appropriated a generic -f name without
> actually making the feature generic at the same time.

Wouldn't -fcf-protection=branch also apply to ARM BTI?  Pointer
authentication can even be enabled by default on GCC 9 if I remember
correctly, so it doesn't need an option at all.

> Thankfully the aarch64 version does not include shadow stacks, and so is less
> invasive into the normal abi -- ARM uses pointer authentication instead.

Branch target authentication should probably should be one or more
separate -fcf-protection options, but it is reasonable to make it
generic as well.

One could even implement a (much) weaker version of pointer
authentication without hardware support.  You could mangle the return
address on entry and return, for example with a XOR/XOR or ADD/SUB of a
per-thread datum, and likewise mangle function pointers with a
per-process datum or with a hash based on the function's type signature.
 Both would need debugger support, and the latter would require
modifying hand-written assembly.

Paolo
Richard Henderson March 14, 2019, 3:23 p.m. UTC | #7
On 3/14/19 3:46 AM, Paolo Bonzini wrote:
> On 14/03/19 01:56, Richard Henderson wrote:
>> Hmm.  The gcc for aarch64 names the similar feature -mbranch-protection.  I'm
>> rather annoyed that the i386 gcc folk appropriated a generic -f name without
>> actually making the feature generic at the same time.
> 
> Wouldn't -fcf-protection=branch also apply to ARM BTI?

It should, but doesn't.  Which was sort of my point re non-coordination of
development.


r~
Paolo Bonzini March 14, 2019, 3:41 p.m. UTC | #8
On 14/03/19 16:23, Richard Henderson wrote:
> On 3/14/19 3:46 AM, Paolo Bonzini wrote:
>> On 14/03/19 01:56, Richard Henderson wrote:
>>> Hmm.  The gcc for aarch64 names the similar feature -mbranch-protection.  I'm
>>> rather annoyed that the i386 gcc folk appropriated a generic -f name without
>>> actually making the feature generic at the same time.
>>
>> Wouldn't -fcf-protection=branch also apply to ARM BTI?
> 
> It should, but doesn't.  Which was sort of my point re non-coordination of
> development.

I agree.  We should open a GCC bug about it, to make sure that in the
long run -fcf-protection does suffice on all architectures.

Paolo
diff mbox series

Patch

diff --git a/configure b/configure
index 42a7e479fd..4470fe8e74 100755
--- a/configure
+++ b/configure
@@ -446,6 +446,7 @@  win_sdk="no"
 want_tools="yes"
 libiscsi=""
 libnfs=""
+cet="no"      # leave it disabled until we can test performance
 coroutine=""
 coroutine_pool=""
 debug_stack_usage="no"
@@ -1246,6 +1247,10 @@  for opt do
   ;;
   --with-pkgversion=*) pkgversion="$optarg"
   ;;
+  --enable-cet) cet="yes"
+  ;;
+  --disable-cet) cet="no"
+  ;;
   --with-coroutine=*) coroutine="$optarg"
   ;;
   --disable-coroutine-pool) coroutine_pool="no"
@@ -1757,6 +1762,7 @@  disabled with --disable-FEATURE, default is enabled if available:
   lzfse           support of lzfse compression library
                   (for reading lzfse-compressed dmg images)
   seccomp         seccomp support
+  cet             Control-flow Enforcement Technology
   coroutine-pool  coroutine freelist (better performance)
   glusterfs       GlusterFS backend
   tpm             TPM support
@@ -5074,6 +5080,23 @@  if have_backend "dtrace"; then
   fi
 fi
 
+##########################################
+# detect CET support in the toolchain
+
+if test "$cet" != no; then
+  write_c_skeleton;
+  if ! compile_prog "-fcf-protection" "" ; then
+    if test "$cet" = yes; then
+      feature_not_found "cet" 'CET is not supported by your toolchain'
+    fi
+    cet=no
+  fi
+fi
+if test "$cet" = ""; then
+  cet=yes
+  QEMU_CFLAGS="-fcf-protection $QEMU_CFLAGS"
+fi
+
 ##########################################
 # check and set a backend for coroutine
 
@@ -6258,6 +6281,7 @@  echo "netmap support    $netmap"
 echo "Linux AIO support $linux_aio"
 echo "ATTR/XATTR support $attr"
 echo "Install blobs     $blobs"
+echo "CET support       $cet"
 echo "KVM support       $kvm"
 echo "HAX support       $hax"
 echo "HVF support       $hvf"
@@ -6468,6 +6492,9 @@  fi
 if test "$profiler" = "yes" ; then
   echo "CONFIG_PROFILER=y" >> $config_host_mak
 fi
+if test "$cet" = "yes" ; then
+  echo "CONFIG_CET=y" >> $config_host_mak
+fi
 if test "$slirp" != "no"; then
   echo "CONFIG_SLIRP=y" >> $config_host_mak
   echo "CONFIG_SMBD_COMMAND=\"$smbd\"" >> $config_host_mak
diff --git a/Makefile.target b/Makefile.target
index d8048aab8f..fa143d7b4b 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -113,6 +113,9 @@  obj-y += exec.o
 obj-y += accel/
 obj-$(CONFIG_TCG) += tcg/tcg.o tcg/tcg-op.o tcg/tcg-op-vec.o tcg/tcg-op-gvec.o
 obj-$(CONFIG_TCG) += tcg/tcg-common.o tcg/optimize.o
+ifeq ($(CONFIG_CET),y)
+tcg/tcg.o-cflags := -fcf-protection=return
+endif
 obj-$(CONFIG_TCG_INTERPRETER) += tcg/tci.o
 obj-$(CONFIG_TCG_INTERPRETER) += disas/tci.o
 obj-$(CONFIG_TCG) += fpu/softfloat.o
diff --git a/util/Makefile.objs b/util/Makefile.objs
index 0808d86a19..93a8397aae 100644
--- a/util/Makefile.objs
+++ b/util/Makefile.objs
@@ -39,6 +39,11 @@  util-obj-y += qemu-coroutine.o qemu-coroutine-lock.o qemu-coroutine-io.o
 util-obj-y += qemu-coroutine-sleep.o
 util-obj-y += coroutine-$(CONFIG_COROUTINE_BACKEND).o
 coroutine-x86.o-cflags := -mno-red-zone
+ifeq ($(CONFIG_CET),y)
+coroutine-sigaltstack.o-cflags := -fcf-protection=branch
+coroutine-ucontext.o-cflags := -fcf-protection=branch
+coroutine-x86.o-cflags += -fcf-protection=branch
+endif
 util-obj-y += buffer.o
 util-obj-y += timed-average.o
 util-obj-y += base64.o