]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
x86/nospec: Simplify alternative_msr_write()
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 1 May 2018 13:55:51 +0000 (15:55 +0200)
committerStefan Bader <stefan.bader@canonical.com>
Mon, 14 May 2018 10:05:41 +0000 (12:05 +0200)
The macro is not type safe and I did look for why that "g" constraint for
the asm doesn't work: it's because the asm is more fundamentally wrong.

It does

        movl %[val], %%eax

but "val" isn't a 32-bit value, so then gcc will pass it in a register,
and generate code like

        movl %rsi, %eax

and gas will complain about a nonsensical 'mov' instruction (it's moving a
64-bit register to a 32-bit one).

Passing it through memory will just hide the real bug - gcc still thinks
the memory location is 64-bit, but the "movl" will only load the first 32
bits and it all happens to work because x86 is little-endian.

Convert it to a type safe inline function with a little trick which hands
the feature into the ALTERNATIVE macro.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Ingo Molnar <mingo@kernel.org>
CVE-2018-3639 (x86)

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
arch/x86/include/asm/nospec-branch.h

index 91df6b9e2bd2964a39d8cadcb7ec6d6dce0b4cfc..ad0a04671e3643fa26164879b26ed0ce75b1bd4d 100644 (file)
@@ -181,15 +181,16 @@ static inline void vmexit_fill_RSB(void)
 #endif
 }
 
-#define alternative_msr_write(_msr, _val, _feature)            \
-       asm volatile(ALTERNATIVE("",                            \
-                                "movl %[msr], %%ecx\n\t"       \
-                                "movl %[val], %%eax\n\t"       \
-                                "movl $0, %%edx\n\t"           \
-                                "wrmsr",                       \
-                                _feature)                      \
-                    : : [msr] "i" (_msr), [val] "i" (_val)     \
-                    : "eax", "ecx", "edx", "memory")
+static __always_inline
+void alternative_msr_write(unsigned int msr, u64 val, unsigned int feature)
+{
+       asm volatile(ALTERNATIVE("", "wrmsr", %c[feature])
+               : : "c" (msr),
+                   "a" (val),
+                   "d" (val >> 32),
+                   [feature] "i" (feature)
+               : "memory");
+}
 
 #endif /* __ASSEMBLY__ */
 #endif /* __NOSPEC_BRANCH_H__ */