Spectre V1 defense in GCC
Spectre V1 defense in GCC
Posted Jul 13, 2018 16:46 UTC (Fri) by anton (subscriber, #25547)Parent article: Spectre V1 defense in GCC
almost all architectures have some sort of compare-and-assign operation that (1) is a single instruction without a branch, so the branch predictor does not enter the picture, and (2) is defined by the architecture to not be subject to speculation in its own right.2) is extremely doubtful. Speculation is a microarchitectural feature (i.e., it differs in different implementations of the same architecture, because it is not architecturally visible (except in timings)), and architecture handbooks are normally silent about it.
However, it is quite likely that these conditional instructions are not subject to speculation, because a major reason for introducing them was to avoid the cost of misprediction in cases where the programmer/compiler knows that the condition is hard to predict; so speculativing on the condition outcome would be counterproductive for typical uses of these instructions. Also, while value prediction has been subject of academic papers for quite a while, I am not aware that it has arrived in commercially available CPUs yet. But then, some CPU manufacturers are no longer marketing their CPUs by talking about the microarchitecture, so they might have introduced value prediction under the radar.
Otherwise, the article is pretty weak IMO:
- It does not show me an example of the use of the new builtin.
- The article claims that preserving
correct
from one branch to the next is important, but fails to explain why, and it's certainly not obvious. Unless this is about always checking the same index bounds, I fail to see what this achieves.
Posted Jul 13, 2018 17:08 UTC (Fri)
by corbet (editor, #1)
[Link] (4 responses)
Propagating correct is important because speculation can go through numerous branches; as soon as one has gone wrong, you know that any others down the chain are suspect too.
Posted Jul 13, 2018 17:28 UTC (Fri)
by anton (subscriber, #25547)
[Link] (2 responses)
Posted Jul 13, 2018 17:44 UTC (Fri)
by corbet (editor, #1)
[Link] (1 responses)
Why would you not clamp sensitive accesses when you know that the assumptions the code was written under do not actually hold?
That's how I understand it, anyway.
Posted Jul 13, 2018 18:04 UTC (Fri)
by anton (subscriber, #25547)
[Link]
Posted Jul 19, 2018 23:16 UTC (Thu)
by mcortese (guest, #52099)
[Link]
I have some doubts, too.
Let me take the article's example and add a second condition further down the code (I'll not use a syntax too similar to C to avoid suggesting that it could be subject to the compiler's transformations and optimizations).
My understanding is that the variable 'correct' must be propagated between the two conditional blocks. But if the variable 'correct' must be recalculated anyway, why do we have to carry it along between the two block? In other words, wouldn't this work just the same?
I'm sorry you didn't like the article.
Spectre V1 defense in GCC
Maybe, but in what way does that help? One has to add protection to the other branches anyway. If the next index is outside the bounds, the protection will make sure it is squashed, so it does not help there. If the next index is inside the bounds, propagating correct will squash it on the speculative path when it otherwise would not, but what does that gain?
Spectre V1 defense in GCC
Once speculation has gone off the rails, just about anything can happen. Subsequent branches could well assume that previous bounds checks had been done correctly and do the wrong thing when the invariant no longer holds. Branches and calls can also be nested, of course, which makes such problems more likely.
Spectre V1 defense in GCC
If the next branch is after the if ends, the compiler cannot make such assumptions, but for nested ifs, it can. But still, it would be sufficient to make sure that the conditional move that checks the index and squashes it if necessary is not subject to such range-propagating optimizations, just like the conditional move that squashed the index of the first access. So, it's still not clear what the advantage of this propagation is.
Spectre V1 defense in GCC
Spectre V1 defense in GCC
correct := all_ones
/* first conditional block */
if condition
correct := condition ? correct : all_zeros
use correct as a mask
...
end if
/* second conditional block */
if condition
correct := condition ? correct : all_zeros
use correct as a mask
...
end if
/* first conditional block */
if condition
correct := condition ? all_ones : all_zeros
use correct as a mask
...
free correct /* don't need it anymore */
end if
/* second conditional block */
if condition
correct := condition ? all_ones : all_zeros
use correct as a mask
...
free correct /* don't need it anymore */
end if