Spectre (unlike Metldown) works thanks to how the CPU handles branches prediction. From the same paper you refer to
[2.3] Speculative execution requires that the processor make guesses as to the likely outcome of branch instructions. Better predictions improve performance by increasing the number of speculatively executed operations that can be successfully committed.
(...)
To predict whether a conditional branch is taken or not,
the processor maintains a record of recent branches outcomes.
Then
[4] The code fragment begins with a bounds check on x
which is essential for security. In particular, this check prevents the processor from reading sensitive memory outside of array1
. Otherwise, an out-of-bounds input x
could trigger an exception or could cause the processor to access sensitive memory by supplying x = (address of a secret byte to read)−(base address of array1)
.
But the paper goes on and explains why this might work anyway, not triggering an exception:
Unfortunately, during speculative execution, the conditional branch for the bounds check can follow the incorrect path. For example, suppose an adversary causes the code to run such that:
• the value of x
is maliciously chosen (and out-ofbounds) such that array1[x]
resolves to a secret byte k somewhere in the victim’s memory;
• array1
size and array2
are not present in the processor’s cache, but k is cached; and
• previous operations received values of x
that were valid, leading the branch predictor to assume the if will likely be true.
Finally the CPU, after the x
value is evaluated to be too high, will effectively bypass the if
body and will not retire the retrieved y
value. However the cache status has changed, and this is where the attack takes place:
The processor realizes that its speculative execution was erroneous, and rewinds its register state. However, on actual processors, the speculative read from array2
affects the cache state in an address-specific manner, where the address depends on k
The unauthorized access to array1[x]
is made during the speculative code execution, and thus does not raise an exception because the CPU "knows" that the outcome of that speculative execution will not be retired if the condition from the branch that precedes happens to be false.
(Unlike Meltdown which triggers an exception when the executed user code does access an unauthorized area - Meltdown exploits a race condition between the time taken to retire the exception and the few out of order instructions that follow that access which are pre-executed (and that will not be retired)).
array1[10]
is not valid and it should throw an exception prior to the attach that will take place. Isn't that? – mahmoodif (arr[x] != NULL) *arr[x] = 3;
, where*arr[x] = 3
can be speculatively run whenx
isNULL
, would trigger an exception which the user shouldn't get, because the branch condition will eventually evaluate to false and the speculative run code is not retired. – Breaking not so bad