]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
x86/fpu: Return proper error codes from user access functions
authorThomas Gleixner <tglx@linutronix.de>
Wed, 23 Jun 2021 12:02:30 +0000 (14:02 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 20 Jul 2021 14:10:47 +0000 (16:10 +0200)
[ Upstream commit aee8c67a4faa40a8df4e79316dbfc92d123989c1 ]

When *RSTOR from user memory raises an exception, there is no way to
differentiate them. That's bad because it forces the slow path even when
the failure was not a fault. If the operation raised eg. #GP then going
through the slow path is pointless.

Use _ASM_EXTABLE_FAULT() which stores the trap number and let the exception
fixup return the negated trap number as error.

This allows to separate the fast path and let it handle faults directly and
avoid the slow path for all other exceptions.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Borislav Petkov <bp@suse.de>
Link: https://lkml.kernel.org/r/20210623121457.601480369@linutronix.de
Signed-off-by: Sasha Levin <sashal@kernel.org>
arch/x86/include/asm/fpu/internal.h

index 9f135e5b9cf5157ad50f201f6d3a04c5f6052f41..a9d1dd82d82081bc1d160b5a86b67b6f847ec79e 100644 (file)
@@ -102,6 +102,7 @@ static inline void fpstate_init_fxstate(struct fxregs_state *fx)
 }
 extern void fpstate_sanitize_xstate(struct fpu *fpu);
 
+/* Returns 0 or the negated trap number, which results in -EFAULT for #PF */
 #define user_insn(insn, output, input...)                              \
 ({                                                                     \
        int err;                                                        \
@@ -109,14 +110,14 @@ extern void fpstate_sanitize_xstate(struct fpu *fpu);
        might_fault();                                                  \
                                                                        \
        asm volatile(ASM_STAC "\n"                                      \
-                    "1:" #insn "\n\t"                                  \
+                    "1: " #insn "\n"                                   \
                     "2: " ASM_CLAC "\n"                                \
                     ".section .fixup,\"ax\"\n"                         \
-                    "3:  movl $-1,%[err]\n"                            \
+                    "3:  negl %%eax\n"                                 \
                     "    jmp  2b\n"                                    \
                     ".previous\n"                                      \
-                    _ASM_EXTABLE(1b, 3b)                               \
-                    : [err] "=r" (err), output                         \
+                    _ASM_EXTABLE_FAULT(1b, 3b)                         \
+                    : [err] "=a" (err), output                         \
                     : "0"(0), input);                                  \
        err;                                                            \
 })
@@ -210,16 +211,20 @@ static inline void copy_fxregs_to_kernel(struct fpu *fpu)
 #define XRSTOR         ".byte " REX_PREFIX "0x0f,0xae,0x2f"
 #define XRSTORS                ".byte " REX_PREFIX "0x0f,0xc7,0x1f"
 
+/*
+ * After this @err contains 0 on success or the negated trap number when
+ * the operation raises an exception. For faults this results in -EFAULT.
+ */
 #define XSTATE_OP(op, st, lmask, hmask, err)                           \
        asm volatile("1:" op "\n\t"                                     \
                     "xor %[err], %[err]\n"                             \
                     "2:\n\t"                                           \
                     ".pushsection .fixup,\"ax\"\n\t"                   \
-                    "3: movl $-2,%[err]\n\t"                           \
+                    "3: negl %%eax\n\t"                                \
                     "jmp 2b\n\t"                                       \
                     ".popsection\n\t"                                  \
-                    _ASM_EXTABLE(1b, 3b)                               \
-                    : [err] "=r" (err)                                 \
+                    _ASM_EXTABLE_FAULT(1b, 3b)                         \
+                    : [err] "=a" (err)                                 \
                     : "D" (st), "m" (*st), "a" (lmask), "d" (hmask)    \
                     : "memory")