Fixing a public but almost undocumented speculative execution vulnerability that is specific to aarch64.
Even though ERET always causes a jump to another address, aarch64 CPUs speculatively execute following instructions as if the ERET instruction was not a jump instruction.
The speculative execution does not cross privilege-levels (to the jump target as one would expect), but it continues on the kernel privilege level as if the ERET instruction did not change the control flow - thus execution anything that is accidentally linked after the ERET instruction. Later, the results of this speculative execution are always architecturally discarded, however they can leak data using microarchitectural side channels. This speculative execution is very reliable (seems to be unconditional) and it manages to complete even relatively performance-heavy operations (e.g. multiple dependent fetches from uncached memory).
It was quietly fixed in Linux by this patch:
And the misbehavior is demonstrated by this implementation:
This is the patch - the attachments probably do not work properly:
diff -u -r -N freebsdold/sys/arm64/arm64/exception.S freebsdnew/sys/arm64/arm64/exception.S
--- freebsdold/sys/arm64/arm64/exception.S 2019-12-16 15:25:23.876924499 -0800
+++ freebsdnew/sys/arm64/arm64/exception.S 2019-12-16 15:22:21.811969062 -0800
@@ -176,6 +176,8 @@
+ dsb sy
@@ -184,6 +186,8 @@
+ dsb sy
@@ -195,6 +199,8 @@
+ dsb sy
@@ -204,6 +210,8 @@
+ dsb sy
diff -u -r -N freebsdold/sys/arm64/arm64/swtch.S freebsdnew/sys/arm64/arm64/swtch.S
--- freebsdold/sys/arm64/arm64/swtch.S 2019-12-16 15:25:24.332926892 -0800
+++ freebsdnew/sys/arm64/arm64/swtch.S 2019-12-16 15:22:38.732057855 -0800
@@ -254,6 +254,8 @@
* will be set to the desired value anyway.
+ dsb sy
*** Bug 242675 has been marked as a duplicate of this bug. ***
*** Bug 242674 has been marked as a duplicate of this bug. ***
Thank you for the report and patch PoC Anthony
Do you know which CPUs this affects?
It probably affects all aarch64 CPUs that support speculative execution.
I concretely tested that on Cavium ThunderX2 T99 and on Cortex A-72 in
Raspberry Pi 4.
Created attachment 210049 [details]
Full report about the vulnerability.
A commit references this bug:
Date: Thu Dec 19 08:52:17 UTC 2019
New revision: 355907
Stop speculation past an eret instruction
On arm64 the eret instruction is used to return from an exception handler.
Some implementations may speculate past this instruction into the next
function. As the user may control many registers in these functions add
a synchronisation barrier sequence after the eret instruction to stop these
CPUs from speculating out of the exception handler.
Submitted by: Anthony Steinhauser <firstname.lastname@example.org> (previous version)
MFC after: 1 week
Taking a stab at opening this up to the public now that a fix has been committed and the issue has been somewhat described anyways in the commit message, and the rest of the materials referenced by Anthony are already public.
Re-assigned to andrew@ because secteam@ has no further action to take here while we don't do SA for arm64.
Marking it as 'in progress' for andrew@ to close when he feels it's completed.
^Triage: Keep secteam CC'd for comms/coordination if and where required