Sik wrote:
OK the more stuff gets disclosed the more things seem to change so huuuuh screw it. How do Meltdown and Spectre actually work?
Google Project Zero has the descriptions.
Basically, It's the nature of speculative execution creating observable effects on the cache. Think about the following code
Code:
// flush caches
if index1 < array1.length {
value1 = array1[index1] // index1 is bogus, pointing to kernel address
index2 = (value1 & 1) * 0x100 + 0x200 // index2 := 0x100 or 0x300
if index2 < array2.length {
value2 = array2[index2] // legal access
}
}
In theory, the entire if-block should not be executed, but with speculative execution (and if array1.length is not in cache), the branch is executed anyway and results will be discarded later, "supposedly creating no side effect" to the program's logic. However, running the inside block in "speculative execution" will bypass any permission checking and either array2[0x100] or array2[0x300] will be fetched to cache.
Now by re-reading array2[0x200] and array2[0x300] and check the timing, you can deduce the lower bit of value1, which is the content of kernel memory. Repeat all these and you have a full memory dump.
For meltdown its similar:
Code:
mov rax, [kernel_address] // trigger exception, which can be handled gracefully and return rax = 0
and rax, 1
mov rbx, [user_address + rax* 0x100]
if [user_address + 0x100] is in the cache, the bit is 1.
These problems cannot be easily fixed without architectural changes, thus the workaround is simply unmap (most) kernel address from user context.
NOTE: credits to project zero.