Bug 242676 - Mitigating speculative execution beyond ERET on aarch64
Summary: Mitigating speculative execution beyond ERET on aarch64
Status: In Progress
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: CURRENT
Hardware: arm64 Any
: Normal Affects Many People
Assignee: Andrew Turner
URL:
Keywords: security
: 242674 242675 (view as bug list)
Depends on:
Blocks:
 
Reported: 2019-12-16 23:53 UTC by Anthony Steinhauser
Modified: 2019-12-20 01:13 UTC (History)
4 users (show)

See Also:
koobs: mfc-stable12?
koobs: mfc-stable11?
koobs: mfc-stable10?


Attachments
Full report about the vulnerability. (92.52 KB, application/pdf)
2019-12-19 01:25 UTC, Anthony Steinhauser
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Anthony Steinhauser 2019-12-16 23:53:28 UTC
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:
https://github.com/torvalds/linux/commit/679db70801da9fda91d26caf13bf5b5ccc74e8e8

And the misbehavior is demonstrated by this implementation:
https://github.com/google/safeside/blob/master/demos/eret_hvc_smc_wrapper.cc
https://github.com/google/safeside/blob/master/kernel_modules/kmod_eret_hvc_smc/eret_hvc_smc_module.c

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 @@
 	bl	do_el1h_sync
 	restore_registers 1
 	eret
+	dsb sy
+	isb
 END(handle_el1h_sync)
 
 ENTRY(handle_el1h_irq)
@@ -184,6 +186,8 @@
 	bl	intr_irq_handler
 	restore_registers 1
 	eret
+	dsb sy
+	isb
 END(handle_el1h_irq)
 
 ENTRY(handle_el0_sync)
@@ -195,6 +199,8 @@
 	do_ast
 	restore_registers 0
 	eret
+	dsb sy
+	isb
 END(handle_el0_sync)
 
 ENTRY(handle_el0_irq)
@@ -204,6 +210,8 @@
 	do_ast
 	restore_registers 0
 	eret
+	dsb sy
+	isb
 END(handle_el0_irq)
 
 ENTRY(handle_serror)
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.
 	 */
 	eret
+	dsb sy
+	isb
 	
 END(fork_trampoline)
Comment 1 Kubilay Kocak freebsd_committer freebsd_triage 2019-12-17 08:44:02 UTC
*** Bug 242675 has been marked as a duplicate of this bug. ***
Comment 2 Kubilay Kocak freebsd_committer freebsd_triage 2019-12-17 08:44:15 UTC
*** Bug 242674 has been marked as a duplicate of this bug. ***
Comment 3 Kubilay Kocak freebsd_committer freebsd_triage 2019-12-17 08:45:43 UTC
Thank you for the report and patch PoC Anthony
Comment 4 Andrew Turner freebsd_committer 2019-12-18 15:15:10 UTC
Do you know which CPUs this affects?
Comment 5 Anthony Steinhauser 2019-12-19 01:21:48 UTC
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.
Comment 6 Anthony Steinhauser 2019-12-19 01:25:21 UTC
Created attachment 210049 [details]
Full report about the vulnerability.
Comment 7 commit-hook freebsd_committer 2019-12-19 08:52:41 UTC
A commit references this bug:

Author: andrew
Date: Thu Dec 19 08:52:17 UTC 2019
New revision: 355907
URL: https://svnweb.freebsd.org/changeset/base/355907

Log:
  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.

  PR:		242676
  Submitted by:	Anthony Steinhauser <asteinhauser@google.com> (previous version)
  MFC after:	1 week

Changes:
  head/sys/arm64/arm64/exception.S
  head/sys/arm64/arm64/swtch.S
  head/sys/arm64/include/asm.h
Comment 8 Kyle Evans freebsd_committer 2019-12-19 14:43:33 UTC
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.
Comment 9 Kubilay Kocak freebsd_committer freebsd_triage 2019-12-20 01:13:32 UTC
^Triage: Keep secteam CC'd for comms/coordination if and where required