tech-kern archive

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

Spectre



Hi folks.

<insert caveat about possibly me misunderstanding things>

Spectre is also a vulnerability. It's been discussed in the context of
web browsers, but it does have repercussions for kernel.

The gist of it seems to be, if you have code that looks like this:

Variant 1:

if (malicious offset is safe)
  value  = array[malicious_offset];
  value2 = (value & 1)
  value3 = array2[value2]

You can read arbitrary memory, as cached memory will be faster. repeat
this bit by bit.

Variant 2:
relies on poisoning the branch predictor

if_transmit = mydriver_transmit;
..

  regular code
  if_transmit(); /* indirect call */
..

malicious_ptr:
  value  = array[malicious_offset];
  value2 = (value & 1)
  value3 = array2[value2]

Now, we poison the branch target buffer, to predict that
if_transmit = malicious_ptr.

It does not even appear like a possible code path, but it is.
This means that code being loaded is enough to pose a risk, even if
there is no easy path to it.


Some things that help this:
- Rather than look for a gadget like this, they went for eBPF, which is
  like dtrace. It also has a JIT. You can load bytecode and it will
  verify and execute it. So you can make your own speculation-gadget.

- Some archs do not allow fine-grained cache control like x86 clflush,
  but this isn't necessary for abuse. just fill the cache before going.
  they have done similar from JavaScript.

Some that harm it:
- Even speculative execution obeys access restrictions, so SMEP, SMAP,
  marking memory NX will prevent execution.

- Instructions like 'lfence' stop speculative execution.

- Intel and AMD have pushed microcode updates that introduce
  instructions, for Intel they are 'IBPB' and 'IBRS'.

- ARM has 'BPIALL' to invalidate the branch target to stop branch
  predictor poisoning

- Retpoline, stuff_RSB etc. to modify jumps to be less likely to jump
  into user-controlled code.

People seemed to occasionally mentioned that 'as many as 100
instructions will be executed speculatively', so that is how far we are
talking.


Own thoughts:
- Variant 1 seems possible to avoid with low cost. It will likely result
  in an error somewhere along the line, which is detectable. Flushing
  the entire cache on userret will make it hard to exploit. Do all
  bound checks failing result in an easily noticed error?

- Variant 2 however is harder without custom instructions. Those may
  rely on a CPU being new enough to receive microcode updates, and
  them being applied.

- I'm not sure how easy it is to find a good enough gadget without
  something like eBPF, but the mere presence of the code in memory was a
  risk.

- Linux could've marked eBPF non-executable when it is unused, so its
  presence in memory does not pose risk.



Discuss.


Home | Main Index | Thread Index | Old Index