ARM: spectre-v1: mitigate user accesses
authorRussell King <rmk+kernel@armlinux.org.uk>
Mon, 14 May 2018 08:40:24 +0000 (09:40 +0100)
committerRussell King <rmk+kernel@armlinux.org.uk>
Thu, 2 Aug 2018 16:41:38 +0000 (17:41 +0100)
Spectre variant 1 attacks are about this sequence of pseudo-code:

index = load(user-manipulated pointer);
access(base + index * stride);

In order for the cache side-channel to work, the access() must me made
to memory which userspace can detect whether cache lines have been
loaded.  On 32-bit ARM, this must be either user accessible memory, or
a kernel mapping of that same user accessible memory.

The problem occurs when the load() speculatively loads privileged data,
and the subsequent access() is made to user accessible memory.

Any load() which makes use of a user-maniplated pointer is a potential
problem if the data it has loaded is used in a subsequent access.  This
also applies for the access() if the data loaded by that access is used
by a subsequent access.

Harden the get_user() accessors against Spectre attacks by forcing out
of bounds addresses to a NULL pointer.  This prevents get_user() being
used as the load() step above.  As a side effect, put_user() will also
be affected even though it isn't implicated.

Also harden copy_from_user() by redoing the bounds check within the
arm_copy_from_user() code, and NULLing the pointer if out of bounds.

Acked-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
arch/arm/include/asm/assembler.h
arch/arm/lib/copy_from_user.S

index ef1386b1af9b0fe0cca3816ca3022a2fbaaf3d8b..f0515f60cff51f11cceb937c10986788649ab446 100644 (file)
@@ -460,6 +460,10 @@ THUMB(     orr     \reg , \reg , #PSR_T_BIT        )
        adds    \tmp, \addr, #\size - 1
        sbcccs  \tmp, \tmp, \limit
        bcs     \bad
+#ifdef CONFIG_CPU_SPECTRE
+       movcs   \addr, #0
+       csdb
+#endif
 #endif
        .endm
 
index 7a4b060490012dd29f8a6d9fb8e24dfa58896bd1..a826df3d3814bfef44d6e6f71b38c8131d9fe25b 100644 (file)
        .text
 
 ENTRY(arm_copy_from_user)
+#ifdef CONFIG_CPU_SPECTRE
+       get_thread_info r3
+       ldr     r3, [r3, #TI_ADDR_LIMIT]
+       adds    ip, r1, r2      @ ip=addr+size
+       sub     r3, r3, #1      @ addr_limit - 1
+       cmpcc   ip, r3          @ if (addr+size > addr_limit - 1)
+       movcs   r1, #0          @ addr = NULL
+       csdb
+#endif
 
 #include "copy_template.S"