[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH for-4.13 2/2] xen/nospec: Introduce CONFIG_SPECULATIVE_BRANCH_HARDEN and disable it




> On 1. Oct 2019, at 17:37, Andrew Cooper <andrew.cooper3@xxxxxxxxxx> wrote:
> 
> On 01/10/2019 15:32, Jan Beulich wrote:
>> On 01.10.2019 14:51, Andrew Cooper wrote:
>>> On 01/10/2019 13:21, Jan Beulich wrote:
>>>> On 30.09.2019 20:24, Andrew Cooper wrote:
>>>>> The code generation for barrier_nospec_true() is not correct.  We are 
>>>>> taking a
>>>>> perf it from the added fences, but not gaining any speculative safety.
>>>> You want to be more specific here, I think: ISTR you saying that the 
>>>> LFENCEs
>>>> get inserted at the wrong place.
>>> Correct.
>>> 
>>>> IIRC we want them on either side of a
>>>> conditional branch, i.e. immediately following a branch insn as well as 
>>>> right
>>>> at the branch target.
>>> Specifically, they must be at the head of both basic blocks following
>>> the conditional jump.
>>> 
>>>> I've taken, as a simple example,
>>>> p2m_mem_access_sanity_check(), and this looks to be the way gcc9 has 
>>>> generated
>>>> code (in a non-debug build). Hence either I'm mis-remembering what we want
>>>> things to look like, or there's more to it than code generation simply 
>>>> being
>>>> "not correct".
>>> This example demonstrates the problem, and actually throws a further
>>> spanner in the works of how make this safe, which hadn't occurred to me
>>> before.
>>> 
>>> The instruction stream from a caller of p2m_mem_access_sanity_check()
>>> will look something like this:
>>> 
>>> call p2m_mem_access_sanity_check
>>>     ...
>>>     lfence
>>>     ...
>>>     ret   
>>> cmp $0, %eax
>>> jne ...
>>> 
>>> Which is unsafe, because the only safe way to arrange this code would be:
>>> 
>>> call p2m_mem_access_sanity_check
>>>     ...
>>>     ret
>>> cmp $0, %eax
>>> jne 1f
>>> lfence
>>> ...
>>> 1: lfence
>>> …
>>> 

Does it mean the CPU speculates over a direct call (assuming no #PF etc) and
assumes some default return value to be used?

If not, maybe we should be more concerned about the value the cache-loading
gadget speculates with, rather than the sheer speculation over the branch.

Am I mis(understanding) something here? I would be thankful for explanation.

>>> There is absolutely no possible way for inline assembly to be used to
>>> propagate this safety property across translation units.  This is going
>>> to have to be an attribute of some form or another handled by the compiler.
>> But you realize that this particular example is basically a more
>> complex is_XYZ() check, which could be dealt with by inlining the
>> function. Of course there are going to be larger functions where
>> the result wants to be guarded like you say. But just like the
>> addition of the nospec macros to various is_XYZ() functions is a
>> manual operation (as long the compiler doesn't help), it would in
>> that case be a matter of latching the return value into a local
>> variable and using an appropriate guarding construct when
>> evaluating it.
> 
> And this reasoning demonstrates yet another problem (this one was raised
> at the meeting in Chicago).
> 
> evaluate_nospec() is not a useful construct if it needs inserting at
> every higher level predicate to result in safe code.  This is
> boarderline-impossible to review for, and extremely easy to break
> accidentally.
> 
>> 
>> So I'm afraid for now I still can't agree with your "not correct"
>> assessment - the generated code in the example looks correct to
>> me, and if further guarding was needed in users of this particular
>> function, it would be those users which would need further
>> massaging.
> 
> Safety against spectre v1 is not a matter of opinion.
> 

But the hardening wasn’t about spectre v1, but about cache-load gadgets?

> To protect against speculatively executing the wrong basic block, the
> pipeline must execute the conditional jump first, *then* hit an lfence
> to serialise the instruction stream and revector in the case of
> incorrect speculation.

That’s true, but there are also 2 aspects worth mentioning:
1) Example:

jne 1
PRIVILEGED
1:
ALWAYS_SAFE

We do not necessarily have to cover the 1: path with an lfence?
We could allow speculation there, as it is harmless.

2) cache-load protection

It might be ok to speculate over a conditional branch, when we can
guarantee that the value to be used in a dereference is not out-of-bound.
In that case an lfence is used to latch the value in the register. We can
still speculate over the branch and reach the dereference, but with a sane 
value.

I agree that lfence might not give us 100% security in every potential case,
but that is what "hardening" gives you...

> 
> The other way around is not safe.  Serialising the instruction stream
> doesn't do anything to protect against the attacker taking control of a
> later branch.
> 

Sure, but it may do something about the value used to dereference memory
when the speculation happens over the branch.

> The bigger problem is to do with classifying what we are protecting
> against.  In the case of is_control_domain(), it is any action based on
> the result of the decision.  For is_{pv,hvm}_domain(), is only (to a
> first approximation) speculative type confusion into the pv/hvm unions
> (which in practice extends to calling pv_/hvm_ functions as well).
> 
> As for the real concrete breakages.  In a staging build with GCC 6
> 
> $ objdump -d xen-syms | grep '<is_hvm_domain>:' | wc -l
> 18
> $ objdump -d xen-syms | grep '<is_pv_domain>:' | wc -l
> 9
> 
> All of which have the lfence too early to protect against speculative
> type confusion.
> 
> ~Andrew
> 
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@xxxxxxxxxxxxxxxxxxxx
> https://lists.xenproject.org/mailman/listinfo/xen-devel

Best Regards,
Pawel Wieczorkiewicz






Amazon Development Center Germany GmbH
Krausenstr. 38
10117 Berlin
Geschaeftsfuehrung: Christian Schlaeger, Ralf Herbrich
Eingetragen am Amtsgericht Charlottenburg unter HRB 149173 B
Sitz: Berlin
Ust-ID: DE 289 237 879


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.