On Mon, Jul 9, 2018 at 6:39 PM Richard Earnshaw
<richard.earns...@arm.com> wrote:
>
>
> The patches I posted earlier this year for mitigating against
> CVE-2017-5753 (Spectre variant 1) attracted some useful feedback, from
> which it became obvious that a rethink was needed.  This mail, and the
> following patches attempt to address that feedback and present a new
> approach to mitigating against this form of attack surface.
>
> There were two major issues with the original approach:
>
> - The speculation bounds were too tightly constrained - essentially
>   they had to represent and upper and lower bound on a pointer, or a
>   pointer offset.
> - The speculation constraints could only cover the immediately preceding
>   branch, which often did not fit well with the structure of the existing
>   code.
>
> An additional criticism was that the shape of the intrinsic did not
> fit particularly well with systems that used a single speculation
> barrier that essentially had to wait until all preceding speculation
> had to be resolved.
>
> To address all of the above, these patches adopt a new approach, based
> in part on a posting by Chandler Carruth to the LLVM developers list
> (https://lists.llvm.org/pipermail/llvm-dev/2018-March/122085.html),
> but which we have extended to deal with inter-function speculation.
> The patches divide the problem into two halves.
>
> The first half is some target-specific code to track the speculation
> condition through the generated code to provide an internal variable
> which can tell us whether or not the CPU's control flow speculation
> matches the data flow calculations.  The idea is that the internal
> variable starts with the value TRUE and if the CPU's control flow
> speculation ever causes a jump to the wrong block of code the variable
> becomes false until such time as the incorrect control flow
> speculation gets unwound.
>
> The second half is that a new intrinsic function is introduced that is
> much simpler than we had before.  The basic version of the intrinsic
> is now simply:
>
>       T var = __builtin_speculation_safe_value (T unsafe_var);
>
> Full details of the syntax can be found in the documentation patch, in
> patch 1.  In summary, when not speculating the intrinsic returns
> unsafe_var; when speculating then if it can be shown that the
> speculative flow has diverged from the intended control flow then zero
> is returned.  An optional second argument can be used to return an
> alternative value to zero.  The builtin may cause execution to pause
> until the speculation state is resolved.

So a trivial target implementation would be to emit a barrier and then
it would always return unsafe_var and never zero.  What I don't understand
fully is what users should do here, thus what the value of ever returning
"unsafe" is.  Also I wonder why the API is forcing you to single-out a
special value instead of doing

 bool safe = __builtin_speculation_safe_value_p (T unsafe_value);
 if (!safe)
   /* what now? */

I'm only guessing that the correct way to handle "unsafe" is basically

 while (__builtin_speculation_safe_value (val) == 0)
    ;

use val, it's now safe

that is, the return value is only interesting in sofar as to whether it is equal
to val or the special value?

That said, I wonder why we don't hide that details from the user and
provide a predicate instead.

Richard.

> There are seven patches in this set, as follows.
>
> 1) Introduces the new intrinsic __builtin_sepculation_safe_value.
> 2) Adds a basic hard barrier implementation for AArch32 (arm) state.
> 3) Adds a basic hard barrier implementation for AArch64 state.
> 4) Adds a new command-line option -mtrack-speculation (currently a no-op).
> 5) Disables CB[N]Z and TB[N]Z when -mtrack-speculation.
> 6) Adds the new speculation tracking pass for AArch64
> 7) Uses the new speculation tracking pass to generate CSDB-based barrier
>    sequences
>
> I haven't added a speculation-tracking pass for AArch32 at this time.
> It is possible to do this, but would require quite a lot of rework for
> the arm backend due to the limited number of registers that are
> available.
>
> Although patch 6 is AArch64 specific, I'd appreciate a review from
> someone more familiar with the branch edge code than myself.  There
> appear to be a number of tricky issues with more complex edges so I'd
> like a second opinion on that code in case I've missed an important
> case.
>
> R.
>
>
>
> Richard Earnshaw (7):
>   Add __builtin_speculation_safe_value
>   Arm - add speculation_barrier pattern
>   AArch64 - add speculation barrier
>   AArch64 - Add new option -mtrack-speculation
>   AArch64 - disable CB[N]Z TB[N]Z when tracking speculation
>   AArch64 - new pass to add conditional-branch speculation tracking
>   AArch64 - use CSDB based sequences if speculation tracking is enabled
>
>  gcc/builtin-types.def                     |   6 +
>  gcc/builtins.c                            |  57 ++++
>  gcc/builtins.def                          |  20 ++
>  gcc/c-family/c-common.c                   | 143 +++++++++
>  gcc/c-family/c-cppbuiltin.c               |   5 +-
>  gcc/config.gcc                            |   2 +-
>  gcc/config/aarch64/aarch64-passes.def     |   1 +
>  gcc/config/aarch64/aarch64-protos.h       |   3 +-
>  gcc/config/aarch64/aarch64-speculation.cc | 494 
> ++++++++++++++++++++++++++++++
>  gcc/config/aarch64/aarch64.c              |  88 +++++-
>  gcc/config/aarch64/aarch64.md             | 140 ++++++++-
>  gcc/config/aarch64/aarch64.opt            |   4 +
>  gcc/config/aarch64/iterators.md           |   3 +
>  gcc/config/aarch64/t-aarch64              |  10 +
>  gcc/config/arm/arm.md                     |  21 ++
>  gcc/config/arm/unspecs.md                 |   1 +
>  gcc/doc/cpp.texi                          |   4 +
>  gcc/doc/extend.texi                       |  29 ++
>  gcc/doc/invoke.texi                       |  10 +-
>  gcc/doc/md.texi                           |  15 +
>  gcc/doc/tm.texi                           |  20 ++
>  gcc/doc/tm.texi.in                        |   2 +
>  gcc/target.def                            |  23 ++
>  gcc/targhooks.c                           |  27 ++
>  gcc/targhooks.h                           |   2 +
>  gcc/testsuite/gcc.dg/spec-barrier-1.c     |  40 +++
>  gcc/testsuite/gcc.dg/spec-barrier-2.c     |  19 ++
>  gcc/testsuite/gcc.dg/spec-barrier-3.c     |  13 +
>  28 files changed, 1191 insertions(+), 11 deletions(-)
>  create mode 100644 gcc/config/aarch64/aarch64-speculation.cc
>  create mode 100644 gcc/testsuite/gcc.dg/spec-barrier-1.c
>  create mode 100644 gcc/testsuite/gcc.dg/spec-barrier-2.c
>  create mode 100644 gcc/testsuite/gcc.dg/spec-barrier-3.c

Reply via email to