[llvm-dev] Spectre V1 Mitigation - Internals?

Praveen Velliengiri via llvm-dev
Tue, 17 Sep 2019 14:57:37 -0000

Hi,
Thanks for your email, I understand that the execution stalls until the
predicated state is computed, then we mask pointers with all_zeros_mask if
there is a mis-prediction. But I understand that as soon as the condition
value is available, the processor can check about it's assumptions and
revert back.

That is,
If the branch prediction is correct during speculation, we mask with
all_ones, the processor can follow the predicted branch to retire.
But if the processor mispredicted the branch, it will revert back as soon
as condition become available if this is the case then we don't execute
speculatively the operations : pointer1 &= predicate_state - (if branch)
and *pointer2 & predicted_state - (else branch) right? Or
out-of-processor's allow such access?

Plus, why we are masking with all_zeros_mask during mis-prediction. Is
there any reason for choosing all_zeros_mask?

Cheers,
Praveen



On Tue, 17 Sep 2019 at 17:08, Jeremy Lakeman <Jeremy.Lakeman at gmail.com>
wrote:

> There's a difference between control flow speculation and data flow.
> By entangling the control flow & data, the cpu should stall the memory
> load until the condition is known, since the pointer value also isn't
known.
>
> I assume that actual experts (not me) tested this, and / or asked intel if
> this was sufficient to prevent the speculative memory load, given how
> speculation is actually implemented.
>
> On Tue, 17 Sep 2019 at 02:04, Praveen Velliengiri via llvm-dev <
> llvm-dev at lists.llvm.org> wrote:
>
>> Hi all,
>>
>> I understand how the speculative information flow attack works. I'm
>> trying get my head around the spectre v1 mitigation of LLVM.
>> In the design document here :
>>
https://llvm.org/docs/SpeculativeLoadHardening.html#speculative-load-hardening.
>>
<https://llvm.org/docs/SpeculativeLoadHardening.html#speculative-load-hardening>
>>
>> Example:
>>
>> void leak(int data);void example(int* pointer1, int* pointer2) {
>>   if (condition)
>>     leak(*pointer1);
>>   else
>>     leak(*pointer2);}
>>
>> After the applying the mitigation the code resembles like:
>>
>> void leak(int data);
>> void example(int* pointer1, int* pointer2) {
>>   uintptr_t predicate_state = all_ones_mask;
>>   if (condition) {
>>     predicate_state = !condition ? all_zeros_mask : predicate_state;
>>     pointer1 &= predicate_state;
>>     leak(*pointer1);
>>   } else {
>>     int value2 = *pointer2 & predicate_state;
>>     leak(value2);
>>   }
>> }
>>
>> Let's assume that the branch is mispredicted and if body is taken.
The value predicate_state mask is depend on the "result of the
condition" but which is not yet available hence
>>
>> speculative execution. My question whether the value of predicate_state
is also guessed by the processor? If it is correct, then the value of
predicate_state will be
>> predicate_state, if the processor mis-predicts the condition as true.
Is my assumption is correct? i.e predicate_state = ! 1 ? all_zeros_mask :
predicate_state, where processor predicts
>> condition as true.
>>
>> Or Whether the execution stalls at "predicate_state = !condition ?
all_zeros_mask : predicate_state until the result of condition became available?
If this is true, why we have to
>>
>> harden the pointers in the first place, because after the condition is
actually computed, the processors will revert back right the execution trace of
mis-prediction.
>>
>> I know that I'm missing something fundamental here, I would highly
appreciate your help on this? Please let me know if you more info!
>>
>> Cheeers,
>>
>> Praveen
>>
>>
>> _______________________________________________
>> LLVM Developers mailing list
>> llvm-dev at lists.llvm.org
>> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://lists.llvm.org/pipermail/llvm-dev/attachments/20190917/d9102c55/attachment-0001.html>