[kernel][x86] user_copy: Move CLAC/STAC to immediately around REP MOVSB
Where available, Zircon enables SMAP; this means accesses to non-
supervisor pages in supervisor mode need to be bracketed by CLAC/
STAC instructions (to disable that checking).
Move the CLAC and STAC instruction pair to immediately before/after
REP MOVSB, with no other intervening memory accesses.
The old code would perform one supervisor access inside the CLAC/STAC
unprotected region, to the |fault_return| address. If a caller managed
to trick this function into being called with a user |fault_return|,
the kernel would write unexpectedly to user mode addresses.
No functional change, cinches the belt and suspenders a little tighter.
Change-Id: Iacc09fdc71c17486874cc4a0ecf1fe0e1fbdfcba
diff --git a/zircon/kernel/arch/x86/user_copy.S b/zircon/kernel/arch/x86/user_copy.S
index e3459b0..ec87d88 100644
--- a/zircon/kernel/arch/x86/user_copy.S
+++ b/zircon/kernel/arch/x86/user_copy.S
@@ -25,13 +25,13 @@
// Copy fault_return out of %rcx, because %rcx is used by "rep movsb" later.
movq %rcx, %r10
- // Disable SMAP protection if SMAP is enabled
- STAC
-
// Setup page fault return
leaq .Lfault_copy(%rip), %rax
movq %rax, (%r10)
+ // Disable SMAP protection if SMAP is enabled
+ STAC
+
// Between now and the reset of the fault return, we cannot make a function
// call or manipulate the stack. We need to be able to restore all callee
// registers, without any knowledge of where between these two points we
@@ -46,11 +46,12 @@
mov $ZX_OK, %rax
.Lcleanup_copy:
+ // Re-enable SMAP protection
+ CLAC
+
// Reset fault return
movq $0, (%r10)
- // Re-enable SMAP protection
- CLAC
ret
.Lfault_copy: