| From foo@baz Wed Nov 21 19:20:53 CET 2018 |
| From: David Long <dave.long@linaro.org> |
| Date: Wed, 7 Nov 2018 11:44:02 -0500 |
| Subject: ARM: spectre-v1: mitigate user accesses |
| To: stable@vger.kernel.org, Russell King - ARM Linux <linux@armlinux.org.uk>, Florian Fainelli <f.fainelli@gmail.com>, Tony Lindgren <tony@atomide.com>, Marc Zyngier <marc.zyngier@arm.com>, Mark Rutland <mark.rutland@arm.com> |
| Cc: Greg KH <gregkh@linuxfoundation.org>, Mark Brown <broonie@kernel.org> |
| Message-ID: <20181107164402.9380-25-dave.long@linaro.org> |
| |
| From: Russell King <rmk+kernel@armlinux.org.uk> |
| |
| Commit a3c0f84765bb429ba0fd23de1c57b5e1591c9389 upstream. |
| |
| 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> |
| Signed-off-by: David A. Long <dave.long@linaro.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| arch/arm/include/asm/assembler.h | 4 ++++ |
| arch/arm/lib/copy_from_user.S | 9 +++++++++ |
| 2 files changed, 13 insertions(+) |
| |
| --- a/arch/arm/include/asm/assembler.h |
| +++ b/arch/arm/include/asm/assembler.h |
| @@ -458,6 +458,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 |
| |
| --- a/arch/arm/lib/copy_from_user.S |
| +++ b/arch/arm/lib/copy_from_user.S |
| @@ -90,6 +90,15 @@ |
| .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" |
| |