| 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:01 -0500 |
| Subject: ARM: spectre-v1: use get_user() for __get_user() |
| 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-24-dave.long@linaro.org> |
| |
| From: Russell King <rmk+kernel@armlinux.org.uk> |
| |
| Commit b1cd0a14806321721aae45f5446ed83a3647c914 upstream. |
| |
| Fixing __get_user() for spectre variant 1 is not sane: we would have to |
| add address space bounds checking in order to validate that the location |
| should be accessed, and then zero the address if found to be invalid. |
| |
| Since __get_user() is supposed to avoid the bounds check, and this is |
| exactly what get_user() does, there's no point having two different |
| implementations that are doing the same thing. So, when the Spectre |
| workarounds are required, make __get_user() an alias of get_user(). |
| |
| 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/uaccess.h | 17 +++++++++++------ |
| 1 file changed, 11 insertions(+), 6 deletions(-) |
| |
| --- a/arch/arm/include/asm/uaccess.h |
| +++ b/arch/arm/include/asm/uaccess.h |
| @@ -280,6 +280,16 @@ static inline void set_fs(mm_segment_t f |
| #define user_addr_max() \ |
| (segment_eq(get_fs(), KERNEL_DS) ? ~0UL : get_fs()) |
| |
| +#ifdef CONFIG_CPU_SPECTRE |
| +/* |
| + * When mitigating Spectre variant 1, it is not worth fixing the non- |
| + * verifying accessors, because we need to add verification of the |
| + * address space there. Force these to use the standard get_user() |
| + * version instead. |
| + */ |
| +#define __get_user(x, ptr) get_user(x, ptr) |
| +#else |
| + |
| /* |
| * The "__xxx" versions of the user access functions do not verify the |
| * address space - it must have been done previously with a separate |
| @@ -296,12 +306,6 @@ static inline void set_fs(mm_segment_t f |
| __gu_err; \ |
| }) |
| |
| -#define __get_user_error(x, ptr, err) \ |
| -({ \ |
| - __get_user_err((x), (ptr), err); \ |
| - (void) 0; \ |
| -}) |
| - |
| #define __get_user_err(x, ptr, err) \ |
| do { \ |
| unsigned long __gu_addr = (unsigned long)(ptr); \ |
| @@ -361,6 +365,7 @@ do { \ |
| |
| #define __get_user_asm_word(x, addr, err) \ |
| __get_user_asm(x, addr, err, ldr) |
| +#endif |
| |
| |
| #define __put_user_switch(x, ptr, __err, __fn) \ |