Avoid speculative indirect calls in kernel
Subsystems (10)
This is a fix for Variant 2 in
https://googleprojectzero.blogspot.com/2018/01/reading-privileged-memory-with-side.html
Any speculative indirect calls in the kernel can be tricked to execute any kernel code, which may allow side channel attacks that can leak arbitrary kernel data.
So we want to avoid speculative indirect calls in the kernel.
There's a special code sequence called a retpoline that can do indirect calls without speculation. We use a new compiler option -mindirect-branch=thunk-extern (gcc patch will be released separately) to recompile the kernel with this new sequence.
We also patch all the assembler code in the kernel to use the new sequence.
The patches were originally from David Woodhouse and Tim Chen, but then reworked and enhanced by me.
No performance numbers at this point. 32bit is only boot tested.
Git tree available ingit://git.kernel.org/pub/scm/linux/kernel/git/ak/linux-misc spec/retpoline-415-2
v1: Initial post.
v2:
Add CONFIG_RETPOLINE to build kernel without it.
Change warning messages.
Hide modpost warning message
PATCH v2 1/12 x86/retpoline: Define retpoline indirect thunk and macros
From: Dave Hansen <[email protected]>
From: David Woodhouse <[email protected]>
retpoline is a special sequence on Intel CPUs to stop speculation for indirect branches.
Provide assembler infrastructure to use retpoline by the compiler and for assembler. We add the out of line trampoline used by the compiler, and NOSPEC_JUMP / NOSPEC_CALL macros for assembler
[Originally from David and Tim, heavily hacked by AK]
v2: Add CONFIG_RETPOLINE option
--- arch/x86/Kconfig | 8 +++++ arch/x86/include/asm/jump-asm.h | 70 +++++++++++++++++++++++++++++++++++++++++ arch/x86/kernel/vmlinux.lds.S | 1 + arch/x86/lib/Makefile | 1 + arch/x86/lib/retpoline.S | 35 +++++++++++++++++++++ 5 files changed, 115 insertions(+) create mode 100644 arch/x86/include/asm/jump-asm.h create mode 100644 arch/x86/lib/retpoline.S
arch/x86/Kconfig +8 -0
@@ -429,6 +429,14 @@ config GOLDFISH def_bool y depends on X86_GOLDFISH +config RETPOLINE + bool "Avoid speculative indirect branches in kernel" + default y + help + Compile kernel with the retpoline compiler options to guard against + kernel to user data leaks by avoiding speculative indirect + branches. Requires a new enough compiler. The kernel may run slower. + config INTEL_RDT bool "Intel Resource Director Technology support" default n
arch/x86/include/asm/jump-asm.h new file +70 -0
70 lines not on this page · raw message
arch/x86/kernel/vmlinux.lds.S +1 -0
@@ -103,6 +103,7 @@ SECTIONS /* bootstrapping code */ HEAD_TEXT . = ALIGN(8); + *(.text.__x86.indirect_thunk) TEXT_TEXT SCHED_TEXT CPUIDLE_TEXT
arch/x86/lib/Makefile +1 -0
@@ -26,6 +26,7 @@ lib-y += memcpy_$(BITS).o lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o lib-$(CONFIG_INSTRUCTION_DECODER) += insn.o inat.o insn-eval.o lib-$(CONFIG_RANDOMIZE_BASE) += kaslr.o +lib-$(CONFIG_RETPOLINE) += retpoline.o obj-y += msr.o msr-reg.o msr-reg-export.o hweight.o
arch/x86/lib/retpoline.S new file +35 -0
@@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * Out of line jump trampoline for calls that disable speculation. + * + * This is a special sequence that prevents the CPU speculating + * for indirect calls. + * + * This can be called by gcc generated code, or with the asm macros + * in asm/jump-asm.h + */ + +#include <linux/linkage.h> +#include <asm/dwarf2.h> +#include <asm/export.h> + + .section .text.__x86.indirect_thunk,"ax" + +ENTRY(__x86.indirect_thunk) + CFI_STARTPROC + call retpoline_call_target +2: + lfence /* stop speculation */ + jmp 2b +retpoline_call_target: +#ifdef CONFIG_64BIT + lea 8(%rsp), %rsp +#else + lea 4(%esp), %esp +#endif + ret + CFI_ENDPROC +ENDPROC(__x86.indirect_thunk) + + EXPORT_SYMBOL(__x86.indirect_thunk)
Signature · 1 line
2.14.3
Re: [PATCH v2 01/12] x86/retpoline: Define retpoline indirect thunk and macros
Quoted 188 lines · Andi Kleen
From: Dave Hansen <[email protected]>
From: David Woodhouse <[email protected]>
retpoline is a special sequence on Intel CPUs to stop speculation for indirect branches.
Provide assembler infrastructure to use retpoline by the compiler and for assembler. We add the out of line trampoline used by the compiler, and
NOSPEC_JUMP/NOSPEC_CALLmacros for assembler[Originally from David and Tim, heavily hacked by AK]
v2: Add
CONFIG_RETPOLINEoptionSigned-off-by David Woodhouse <[email protected]>Signed-off-by Tim Chen <[email protected]>Signed-off-by Andi Kleen <[email protected]>--- arch/x86/Kconfig | 8 +++++ arch/x86/include/asm/jump-asm.h | 70 +++++++++++++++++++++++++++++++++++++++++ arch/x86/kernel/vmlinux.lds.S | 1 + arch/x86/lib/Makefile | 1 + arch/x86/lib/retpoline.S | 35 +++++++++++++++++++++ 5 files changed, 115 insertions(+) create mode 100644 arch/x86/include/asm/jump-asm.h create mode 100644 arch/x86/lib/retpoline.Sarch/x86/Kconfig +8
-0@@ -429,6 +429,14 @@ config GOLDFISH def_bool y depends on X86_GOLDFISH +config RETPOLINE + bool "Avoid speculative indirect branches in kernel" + default y + help + Compile kernel with the retpoline compiler options to guard against + kernel to user data leaks by avoiding speculative indirect + branches. Requires a new enough compiler. The kernel may run slower. + config INTEL_RDT bool "Intel Resource Director Technology support" default narch/x86/include/asm/jump-asm.h new file +70
-0@@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef JUMP_ASM_H +#define JUMP_ASM_H 1 + +#ifdef __ASSEMBLY__ + +#ifdef CONFIG_RETPOLINE + +/* +* Jump to an indirect pointer without speculation. +* +* The out of line __x86.indirect_thunk has special code sequences +* to stop speculation. +*/ + +.macro NOSPEC_JMP target + push \target + jmp __x86.indirect_thunk +.endm + + +/* +* Call an indirect pointer without speculation. +*/ + +.macro NOSPEC_CALL target + jmp 1221f +1222: + push \target + jmp __x86.indirect_thunk +1221: + call 1222b +.endm + +#else /* CONFIG_RETPOLINE */ + +.macro NOSPEC_JMP target + jmp *\target +.endm + +.macro NOSPEC_CALL target + call *\target +.endm + +#endif /* !CONFIG_RETPOLINE */ + +#else /* __ASSEMBLY__ */ + +#ifdef CONFIG_RETPOLINE + +#define NOSPEC_JMP (t) \ + "push " t "; " \ + "jmp __x86.indirect_thunk; " + +#define NOSPEC_CALL (t) \ + " jmp 1221f; " \ + "1222: push " t ";" \ + " jmp __x86.indirect_thunk;" \ + "1221: call 1222b;" + +#else /* CONFIG_RETPOLINE */ + +#define NOSPEC_JMP (t) "jmp *" t "; " +#define NOSPEC_CALL (t) "call *" t "; " + +#endif /* !CONFIG_RETPOLINE */ + +#endif /* !__ASSEMBLY */ + +#endif arch/x86/kernel/vmlinux.lds.S +1
-0@@ -103,6 +103,7 @@ SECTIONS /* bootstrapping code */ HEAD_TEXT . = ALIGN(8); + *(.text.__x86.indirect_thunk) TEXT_TEXT SCHED_TEXT CPUIDLE_TEXTarch/x86/lib/Makefile +1
-0@@ -26,6 +26,7 @@ lib-y += memcpy_$(BITS).o lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o lib-$(CONFIG_INSTRUCTION_DECODER) += insn.o inat.o insn-eval.o lib-$(CONFIG_RANDOMIZE_BASE) += kaslr.o +lib-$(CONFIG_RETPOLINE) += retpoline.o obj-y += msr.o msr-reg.o msr-reg-export.o hweight.oarch/x86/lib/retpoline.S new file +35
-1@@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * Out of line jump trampoline for calls that disable speculation. + * + * This is a special sequence that prevents the CPU speculating + * for indirect calls. + * + * This can be called by gcc generated code, or with the asm macros + * in asm/jump-asm.h + */ + +#include <linux/linkage.h> +#include <asm/dwarf2.h> +#include <asm/export.h> + + .section .text.__x86.indirect_thunk,"ax" + +ENTRY(__x86.indirect_thunk) + CFI_STARTPROC + call retpoline_call_target +2: + lfence /* stop speculation */ + jmp 2b +retpoline_call_target: +#ifdef CONFIG_64BIT + lea 8(%rsp), %rsp +#else + lea 4(%esp), %esp +#endif + ret + CFI_ENDPROC +ENDPROC(__x86.indirect_thunk) + + EXPORT_SYMBOL(__x86.indirect_thunk) --
Quoted 2 lines
2.14.3
Can someone actually explain WTF this mess is trying to accomplish?
--
Brian Gerst
Re: [PATCH v2 01/12] x86/retpoline: Define retpoline indirect thunk and macros
Quoted 14 lines
Quoted 14 lines
arch/x86/lib/retpoline.S new file +14
-0+ENTRY(__x86.indirect_thunk) + CFI_STARTPROC + call retpoline_call_target +2: + lfence /* stop speculation */ + jmp 2b +retpoline_call_target: +#ifdef CONFIG_64BIT + lea 8(%rsp), %rsp +#else + lea 4(%esp), %esp +#endif + ret + CFI_ENDPROC
Quoted 8 lines
Quoted 6 lines
arch/x86/lib/retpoline.S new file +3
-1+ENDPROC(__x86.indirect_thunk) + + EXPORT_SYMBOL(__x86.indirect_thunk) --2.14.3
Can someone actually explain WTF this mess is trying to accomplish?
Think of it as an 'indirect call that doesn't speculate' instruction. There isn't one in the processor but this specific sequence happens to make the micro-architecture do just that as efficiently as possible.
What it's actually doing on the non-speculated path (ie the reachable code) is to call, put the address we want to hit over the existing return address and then return, to the address we want to indirectly go to.
It's faster than doing a far branch or flushing branch predictors and the like.
Alan
PATCH v2 2/12 x86/retpoline/crypto: Convert crypto assembler indirect jumps
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
Convert all indirect jumps in crypto assembler code to use non speculative sequences.
Based on code from David Woodhouse and Tim Chen
--- arch/x86/crypto/aesni-intel_asm.S | 5 +++-- arch/x86/crypto/camellia-aesni-avx-asm_64.S | 3 ++- arch/x86/crypto/camellia-aesni-avx2-asm_64.S | 2 +- arch/x86/crypto/crc32c-pcl-intel-asm_64.S | 3 ++- 4 files changed, 8 insertions(+), 5 deletions(-)
arch/x86/crypto/aesni-intel_asm.S +3 -2
@@ -32,6 +32,7 @@ #include <linux/linkage.h> #include <asm/inst.h> #include <asm/frame.h> +#include <asm/jump-asm.h> /* * The following macros are used to move an (un)aligned 16 byte value to/from
@@ -2884,7 +2885,7 @@ ENTRY(aesni_xts_crypt8) pxor INC, STATE4 movdqu IV, 0x30(OUTP) - call *%r11 + NOSPEC_CALL %r11 movdqu 0x00(OUTP), INC pxor INC, STATE1
@@ -2929,7 +2930,7 @@ ENTRY(aesni_xts_crypt8) _aesni_gf128mul_x_ble() movups IV, (IVP) - call *%r11 + NOSPEC_CALL %r11 movdqu 0x40(OUTP), INC pxor INC, STATE1
arch/x86/crypto/camellia-aesni-avx-asm_64.S +2 -1
@@ -17,6 +17,7 @@ #include <linux/linkage.h> #include <asm/frame.h> +#include <asm/jump-asm.h> #define CAMELLIA_TABLE_BYTE_LEN 272
@@ -1227,7 +1228,7 @@ camellia_xts_crypt_16way: vpxor 14 * 16(%rax), %xmm15, %xmm14; vpxor 15 * 16(%rax), %xmm15, %xmm15; - call *%r9; + NOSPEC_CALL %r9; addq $(16 * 16), %rsp;
arch/x86/crypto/camellia-aesni-avx2-asm_64.S +1 -1
@@ -1343,7 +1343,7 @@ camellia_xts_crypt_32way: vpxor 14 * 32(%rax), %ymm15, %ymm14; vpxor 15 * 32(%rax), %ymm15, %ymm15; - call *%r9; + NOSPEC_CALL %r9; addq $(16 * 32), %rsp;
arch/x86/crypto/crc32c-pcl-intel-asm_64.S +2 -1
@@ -45,6 +45,7 @@ #include <asm/inst.h> #include <linux/linkage.h> +#include <asm/jump-asm.h> ## ISCSI CRC 32 Implementation with crc32 and pclmulqdq Instruction
@@ -172,7 +173,7 @@ continue_block: movzxw (bufp, %rax, 2), len lea crc_array(%rip), bufp lea (bufp, len, 1), bufp - jmp *bufp + NOSPEC_JMP bufp ################################################################ ## 2a) PROCESS FULL BLOCKS:
Signature · 1 line
2.14.3
PATCH v2 3/12 x86/retpoline/entry: Convert entry assembler indirect jumps
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
Convert all indirect jumps in core 32/64bit entry assembler code to use non speculative sequences.
Based on code from David Woodhouse and Tim Chen
--- arch/x86/entry/entry_32.S | 5 +++-- arch/x86/entry/entry_64.S | 12 +++++++----- 2 files changed, 10 insertions(+), 7 deletions(-)
arch/x86/entry/entry_32.S +3 -2
@@ -44,6 +44,7 @@ #include <asm/asm.h> #include <asm/smap.h> #include <asm/frame.h> +#include <asm/jump-asm.h> .section .entry.text, "ax"
@@ -290,7 +291,7 @@ ENTRY(ret_from_fork) /* kernel thread */ 1: movl %edi, %eax - call *%ebx + NOSPEC_CALL %ebx /* * A kernel thread is allowed to return here after successfully * calling do_execve(). Exit to userspace to complete the execve()
@@ -919,7 +920,7 @@ common_exception: movl %ecx, %es TRACE_IRQS_OFF movl %esp, %eax # pt_regs pointer - call *%edi + NOSPEC_CALL %edi jmp ret_from_exception END(common_exception)
arch/x86/entry/entry_64.S +7 -5
@@ -37,6 +37,7 @@ #include <asm/pgtable_types.h> #include <asm/export.h> #include <asm/frame.h> +#include <asm/jump-asm.h> #include <linux/err.h> #include "calling.h"
@@ -191,7 +192,7 @@ ENTRY(entry_SYSCALL_64_trampoline) */ pushq %rdi movq $entry_SYSCALL_64_stage2, %rdi - jmp *%rdi + NOSPEC_JMP %rdi END(entry_SYSCALL_64_trampoline) .popsection
@@ -269,8 +270,9 @@ entry_SYSCALL_64_fastpath: * This call instruction is handled specially in stub_ptregs_64. * It might end up jumping to the slow path. If it jumps, RAX * and all argument registers are clobbered. - */ - call *sys_call_table(, %rax, 8) + */ + movq sys_call_table(, %rax, 8), %rax + NOSPEC_CALL %rax .Lentry_SYSCALL_64_after_fastpath_call: movq %rax, RAX(%rsp)
@@ -442,7 +444,7 @@ ENTRY(stub_ptregs_64) jmp entry_SYSCALL64_slow_path 1: - jmp *%rax /* Called from C */ + NOSPEC_JMP %rax /* Called from C */ END(stub_ptregs_64) .macro ptregs_stub func
@@ -521,7 +523,7 @@ ENTRY(ret_from_fork) 1: /* kernel thread */ movq %r12, %rdi - call *%rbx + NOSPEC_CALL %rbx /* * A kernel thread is allowed to return here after successfully * calling do_execve(). Exit to userspace to complete the execve()
Signature · 1 line
2.14.3
Re: [PATCH v2 03/12] x86/retpoline/entry: Convert entry assembler indirect jumps
Quoted 9 lines · Andi Kleen
arch/x86/entry/entry_64.S +3
-2@@ -269,8 +270,9 @@ entry_SYSCALL_64_fastpath: * This call instruction is handled specially in stub_ptregs_64. * It might end up jumping to the slow path. If it jumps, RAX * and all argument registers are clobbered. - */ - call *sys_call_table(, %rax, 8) + */ + movq sys_call_table(, %rax, 8), %rax + NOSPEC_CALL %rax
Quoted 3 lines
.Lentry_SYSCALL_64_after_fastpath_call:
movq %rax, RAX(%rsp)
Now I *know* you're working from an older version of my patches and haven't just deliberately reverted the CET support (and alternatives?).
I fixed that mis-indentation of the closing */ and Intel were even shipping that version in the latest pre-embargo patch tarball.
Should I post a new series and call it 'v3'? Was there anything specific you changed other than the cosmetics like s/CALL_THUNK/NOSPEC_CALL/ ? And obviously the fact that it stands alone instead of being based on the IBRS microcode support?
PATCH v2 4/12 x86/retpoline/ftrace: Convert ftrace assembler indirect jumps
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
Convert all indirect jumps in ftrace assembler code to use non speculative sequences.
Based on code from David Woodhouse and Tim Chen
--- arch/x86/kernel/ftrace_32.S | 3 ++- arch/x86/kernel/ftrace_64.S | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-)
arch/x86/kernel/ftrace_32.S +2 -1
@@ -8,6 +8,7 @@ #include <asm/segment.h> #include <asm/export.h> #include <asm/ftrace.h> +#include <asm/jump-asm.h> #ifdef CC_USING_FENTRY # define function_hook __fentry__
@@ -241,5 +242,5 @@ return_to_handler: movl %eax, %ecx popl %edx popl %eax - jmp *%ecx + NOSPEC_JMP %ecx #endif
arch/x86/kernel/ftrace_64.S +3 -3
@@ -7,7 +7,7 @@ #include <asm/ptrace.h> #include <asm/ftrace.h> #include <asm/export.h> - +#include <asm/jump-asm.h> .code64 .section .entry.text, "ax"
@@ -286,7 +286,7 @@ trace: * ip and parent ip are used and the list function is called when * function tracing is enabled. */ - call *ftrace_trace_function + NOSPEC_CALL ftrace_trace_function restore_mcount_regs
@@ -329,5 +329,5 @@ GLOBAL(return_to_handler) movq 8(%rsp), %rdx movq (%rsp), %rax addq $24, %rsp - jmp *%rdi + NOSPEC_JMP %rdi #endif
Signature · 1 line
2.14.3
PATCH v2 5/12 x86/retpoline/hyperv: Convert assembler indirect jumps
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
Convert all indirect jumps in hyperv inline asm code to use non speculative sequences.
Based on code from David Woodhouse and Tim Chen
--- arch/x86/include/asm/mshyperv.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
arch/x86/include/asm/mshyperv.h +5 -4
@@ -7,6 +7,7 @@#include <linux/nmi.h> #include <asm/io.h> #include <asm/hyperv.h> +#include <asm/jump-asm.h> /* * The below CPUID leaves are present if VersionAndFeatures.HypervisorPresent
@@ -186,7 +187,7 @@ static inline u64 hv_do_hypercall(u64 control, void *input, void *output)return U64_MAX ; __asm__ __volatile__("mov %4, %%r8\n" -"call *%5" + NOSPEC_CALL("%5") : "=a" (hv_status), ASM_CALL_CONSTRAINT," +c" (control), " +d" (input_address) : "r" (output_address), "m" (hv_hypercall_pg)
@@ -200,7 +201,7 @@ static inline u64 hv_do_hypercall(u64 control, void *input, void *output)if (!hv_hypercall_pg)return U64_MAX ; - __asm__ __volatile__("call *%7" + __asm__ __volatile__(NOSPEC_CALL("%7") : "=A" (hv_status), "+c" (input_address_lo), ASM_CALL_CONSTRAINT : "A" (control),
@@ -227,7 +228,7 @@ static inline u64 hv_do_fast_hypercall8(u16 code, u64 input1)#ifdef CONFIG_X86_64 { - __asm__ __volatile__("call *%4" + __asm__ __volatile__(NOSPEC_CALL("%4") : "=a" (hv_status), ASM_CALL_CONSTRAINT, "+c" (control), "+d" (input1) : "m" (hv_hypercall_pg)
@@ -238,7 +239,7 @@ static inline u64 hv_do_fast_hypercall8(u16 code, u64 input1)u32 input1_hi =upper_32_bits (input1);u32 input1_lo =lower_32_bits (input1); - __asm__ __volatile__ ("call *%5" + __asm__ __volatile__ (NOSPEC_CALL("%5") : "=A"(hv_status),"+c" (input1_lo),ASM_CALL_CONSTRAINT
Signature · 1 line
2.14.3
PATCH v2 6/12 x86/retpoline/crypto: Convert xen assembler indirect jumps
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
Convert all indirect jumps in xen inline assembler code to use non speculative sequences.
Based on code from David Woodhouse and Tim Chen
--- arch/x86/crypto/camellia-aesni-avx2-asm_64.S | 1 + arch/x86/include/asm/xen/hypercall.h | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-)
arch/x86/crypto/camellia-aesni-avx2-asm_64.S +1 -0
@@ -12,6 +12,7 @@ #include <linux/linkage.h> #include <asm/frame.h> +#include <asm/jump-asm.h> #define CAMELLIA_TABLE_BYTE_LEN 272
arch/x86/include/asm/xen/hypercall.h +2 -1
@@ -44,6 +44,7 @@#include <asm/page.h> #include <asm/pgtable.h> #include <asm/smap.h> +#include <asm/jump-asm.h> #include <xen/interface/xen.h> #include <xen/interface/sched.h>
@@ -217,7 +218,7 @@ privcmd_call(unsigned call,__HYPERCALL_5ARG (a1, a2, a3, a4, a5);stac (); - asmvolatile ("call *%[call]" + asm volatile(NOSPEC_CALL("%[call]") : __HYPERCALL_5PARAM : [call] "a" (&hypercall_page[call]) : __HYPERCALL_CLOBBER5);
Signature · 1 line
2.14.3
Re: [PATCH v2 06/12] x86/retpoline/crypto: Convert xen assembler indirect jumps
Quoted 18 lines · Andi Kleen
From: Andi Kleen <[email protected]>
Convert all indirect jumps in xen inline assembler code to use non speculative sequences.
Based on code from David Woodhouse and Tim Chen
Signed-off-by Andi Kleen <[email protected]>--- arch/x86/crypto/camellia-aesni-avx2-asm_64.S | 1 + arch/x86/include/asm/xen/hypercall.h | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-)arch/x86/crypto/camellia-aesni-avx2-asm_64.S +0
-0
arch/x86/crypto/camellia-aesni-avx2-asm_64.S line 15
Quoted 4 lines
arch/x86/crypto/camellia-aesni-avx2-asm_64.S +1
-0@@ -12,6 +12,7 @@ #include <linux/linkage.h> #include <asm/frame.h> +#include <asm/jump-asm.h>
I fail to connect this change to the patch title.
Maybe should be part of the crypto patch?
Quoted 17 lines
arch/x86/crypto/camellia-aesni-avx2-asm_64.S +0
-0#define CAMELLIA_TABLE_BYTE_LEN 272arch/x86/include/asm/xen/hypercall.h +1
-0@@ -44,6 +44,7 @@#include <asm/page.h> #include <asm/pgtable.h> #include <asm/smap.h> +#include <asm/jump-asm.h> #include <xen/interface/xen.h> #include <xen/interface/sched.h>
arch/x86/include/asm/xen/hypercall.h privcmd_call(unsigned call, · line 224
Quoted 8 lines
arch/x86/include/asm/xen/hypercall.h +1
-1@@ -217,7 +218,7 @@ privcmd_call(unsigned call,__HYPERCALL_5ARG (a1, a2, a3, a4, a5);stac (); - asmvolatile ("call *%[call]" + asm volatile(NOSPEC_CALL("%[call]") : __HYPERCALL_5PARAM : [call] "a" (&hypercall_page[call]) : __HYPERCALL_CLOBBER5);
Juergen
Re: [PATCH v2 06/12] x86/retpoline/crypto: Convert xen assembler indirect jumps
Quoted 6 lines
Quoted 6 lines
arch/x86/crypto/camellia-aesni-avx2-asm_64.S +0
-0@@ -12,6 +12,7 @@
Quoted 7 lines
arch/x86/crypto/camellia-aesni-avx2-asm_64.S line 15
Quoted 3 lines
arch/x86/crypto/camellia-aesni-avx2-asm_64.S +1
-0#include <linux/linkage.h> #include <asm/frame.h> +#include <asm/jump-asm.h>I fail to connect this change to the patch title.
Maybe should be part of the crypto patch?
Right I moved the hunk into the wrong patch. Will fix.
-Andi
PATCH v2 7/12 x86/retpoline/checksum32: Convert assembler indirect jumps
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
Convert all indirect jumps in 32bit checksum assembler code to use non speculative sequences.
Based on code from David Woodhouse and Tim Chen
--- arch/x86/lib/checksum_32.S | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
arch/x86/lib/checksum_32.S +3 -2
@@ -29,6 +29,7 @@ #include <asm/errno.h> #include <asm/asm.h> #include <asm/export.h> +#include <asm/jump-asm.h> /* * computes a partial checksum, e.g. for TCP/UDP fragments
@@ -156,7 +157,7 @@ ENTRY(csum_partial) negl %ebx lea 45f(%ebx,%ebx,2), %ebx testl %esi, %esi - jmp *%ebx + NOSPEC_JMP %ebx # Handle 2-byte-aligned regions 20: addw (%esi), %ax
@@ -439,7 +440,7 @@ ENTRY(csum_partial_copy_generic) andl $-32,%edx lea 3f(%ebx,%ebx), %ebx testl %esi, %esi - jmp *%ebx + NOSPEC_JMP %ebx 1: addl $64,%esi addl $64,%edi SRC(movb -32(%edx),%bl) ; SRC(movb (%edx),%bl)
Signature · 1 line
2.14.3
PATCH v2 8/12 x86/retpoline/irq32: Convert assembler indirect jumps
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
Convert all indirect jumps in 32bit irq inline asm code to use non speculative sequences.
--- arch/x86/kernel/irq_32.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
arch/x86/kernel/irq_32.c +3 -2
@@ -20,6 +20,7 @@#include <linux/mm.h> #include <asm/apic.h> +#include <asm/jump-asm.h> #ifdef CONFIG_DEBUG_STACKOVERFLOW
@@ -55,7 +56,7 @@ DEFINE_PER_CPU(struct irq_stack *, softirq_stack);static void call_on_stack (void *func,void *stack) { asmvolatile ("xchgl %%ebx,%%esp \n" - "call *%%edi \n" + NOSPEC_CALL("%%edi") "movl %%ebx,%%esp \n" : "=b" (stack) : "0" (stack),
@@ -95,7 +96,7 @@ static inline int execute_on_irq_stack(int overflow, struct irq_desc *desc)call_on_stack (print_stack_overflow, isp); asmvolatile ("xchgl %%ebx,%%esp \n" - "call *%%edi \n" + NOSPEC_CALL("%%edi") "movl %%ebx,%%esp \n" : "=a" (arg1), "=b" (isp) : "0" (desc), "1" (isp),
Signature · 1 line
2.14.3
PATCH v2 9/12 x86/retpoline: Finally enable retpoline for C code
In reply to Andi KleenFrom: Dave Hansen <[email protected]>
From: David Woodhouse <[email protected]>
Add retpoline compile option in Makefile
Update Makefile with retpoline compile options. This requires a gcc with the retpoline compiler patches enabled.
Print a warning when the compiler doesn't support retpoline
[Originally from David and Tim, but hacked by AK]
v2: Use CONFIG option to enable
--- arch/x86/Makefile | 11 +++++++++++ 1 file changed, 11 insertions(+)
arch/x86/Makefile +11 -0
@@ -230,6 +230,17 @@ KBUILD_CFLAGS += -Wno-sign-compare # KBUILD_CFLAGS += -fno-asynchronous-unwind-tables +# +ifdef CONFIG_RETPOLINE + RETPOLINE_CFLAGS += $(call cc-option,-mindirect-branch=thunk-extern) + ifneq ($(RETPOLINE_CFLAGS),) + KBUILD_CFLAGS += $(RETPOLINE_CFLAGS) -DRETPOLINE + KBUILD_AFLAGS += -DRETPOLINE + else + $(warning Retpoline not supported in compiler. System may be insecure.) + endif +endif + archscripts: scripts_basic $(Q)$(MAKE) $(build)=arch/x86/tools relocs
Signature · 1 line
2.14.3
PATCH v2 10/12 retpoline/taint: Taint kernel for missing retpoline in compiler
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
When the kernel or a module hasn't been compiled with a retpoline aware compiler, print a warning and set a taint flag.
For modules it is checked at compile time, however it cannot check assembler or other non compiled objects used in the module link.
Due to lack of better letter it uses taint option 'Z'
v2: Change warning message
--- Documentation/admin-guide/tainted-kernels.rst | 3 +++ arch/x86/kernel/setup.c | 6 ++++++ include/linux/kernel.h | 4 +++- kernel/module.c | 11 ++++++++++- kernel/panic.c | 1 + scripts/mod/modpost.c | 9 +++++++++ 6 files changed, 32 insertions(+), 2 deletions(-)
Documentation/admin-guide/tainted-kernels.rst +3 -0
@@ -52,6 +52,9 @@ characters, each representing a particular tainted value. 16) ``K`` if the kernel has been live patched. + 17) ``Z`` if the x86 kernel or a module hasn't been compiled with + a retpoline aware compiler and may be vulnerable to data leaks. + The primary reason for the **'Tainted: '** string is to tell kernel debuggers if this is a clean kernel or if anything unusual has occurred. Tainting is permanent: even if an offending module is
arch/x86/kernel/setup.c +6 -0
@@ -1296,6 +1296,12 @@ void __init setup_arch(char **cmdline_p)#endif unwind_init (); + +#ifndef RETPOLINE +add_taint (TAINT_NO_RETPOLINE ,LOCKDEP_STILL_OK ); +pr_warn ("No support for retpoline in kernel compiler\n" ); +pr_warn ("System may be vulnerable to data leaks.\n" ); +#endif }#ifdef CONFIG_X86_32
include/linux/kernel.h +3 -1
@@ -550,7 +550,9 @@ extern enum system_states {#define TAINT_SOFTLOCKUP 14#define TAINT_LIVEPATCH 15#define TAINT_AUX 16 -#define TAINT_FLAGS_COUNT 17 +#define TAINT_NO_RETPOLINE 17 + +#define TAINT_FLAGS_COUNT 18struct taint_flag {char c_true;/* character printed when tainted */
kernel/module.c +10 -1
@@ -3028,7 +3028,16 @@ static int check_modinfo(struct module *mod, struct load_info *info, int flags) mod->name);add_taint_module (mod,TAINT_OOT_MODULE ,LOCKDEP_STILL_OK ); } - +#ifdef RETPOLINE +if (!get_modinfo (info,"retpoline" )) { +if (!test_taint (TAINT_NO_RETPOLINE )) { +pr_warn ("%s: loading module not compiled with retpoline compiler.\n" , + mod->name); +pr_warn ("Kernel may be vulnerable to data leaks.\n" ); + } +add_taint_module (mod,TAINT_NO_RETPOLINE ,LOCKDEP_STILL_OK ); + } +#endif if (get_modinfo (info,"staging" )) {add_taint_module (mod,TAINT_CRAP ,LOCKDEP_STILL_OK ); pr_warn("%s: module is from the staging directory, the quality "
kernel/panic.c +1 -0
@@ -325,6 +325,7 @@ const struct taint_flag taint_flags[TAINT_FLAGS_COUNT] = { { 'L', ' ', false }, /* TAINT_SOFTLOCKUP */ { 'K', ' ', true }, /* TAINT_LIVEPATCH */ { 'X', ' ', true }, /* TAINT_AUX */ + { 'Z', ' ', true }, /* TAINT_NO_RETPOLINE */ };/**
scripts/mod/modpost.c +9 -0
@@ -2165,6 +2165,14 @@ static void add_intree_flag(struct buffer *b, int is_intree)buf_printf (b,"\nMODULE_INFO(intree, \"Y\");\n" ); } +/* Cannot check for assembler */ +static void add_retpoline (struct buffer *b) +{ +buf_printf (b,"\n#ifdef RETPOLINE\n" ); +buf_printf (b,"MODULE_INFO(retpoline, \"Y\");\n" ); +buf_printf (b,"#endif\n" ); +} +static void add_staging_flag (struct buffer *b,const char *name) {static const char *staging_dir ="drivers/staging" ;
@@ -2506,6 +2514,7 @@ int main(int argc, char **argv) err |=check_modname_len (mod);add_header (&buf, mod);add_intree_flag (&buf, !external_module); +add_retpoline (&buf);add_staging_flag (&buf, mod->name); err |=add_versions (&buf, mod);add_depends (&buf, mod, modules);
Signature · 1 line
2.14.3
PATCH v2 11/12 retpoline/objtool: Disable some objtool warnings
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
With the indirect call thunk enabled compiler two objtool warnings are triggered very frequently and make the build very noisy.
I don't see a good way to avoid them, so just disable them for now.
--- tools/objtool/check.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
tools/objtool/check.c +11 -0
@@ -503,8 +503,13 @@ static int add_call_destinations(struct objtool_file *file) insn->call_dest =find_symbol_by_offset (insn->sec, dest_off);if (!insn->call_dest) { +#if 0 +/* Compilers with -mindirect-branch=thunk-extern trigger +* this everywhere on x86. Disable for now. +*/ WARN_FUNC ("can't find call dest symbol at offset 0x%lx" , insn->sec, insn->offset, dest_off); +#endif return -1 ; } }else if (rela->sym->type ==STT_SECTION ) {
@@ -1716,8 +1721,14 @@ static int validate_branch(struct objtool_file *file, struct instruction *first,return 1 ; }else if (func &&has_modified_stack_frame (&state)) { +#if 0 +/* Compilers with -mindirect-branch=thunk-extern trigger +* this everywhere on x86. Disable for now. +*/ +WARN_FUNC ("sibling call from callable instruction with modified stack frame" , sec, insn->offset); +#endif return 1 ; }
Signature · 1 line
2.14.3
Re: [PATCH v2 11/12] retpoline/objtool: Disable some objtool warnings
Quoted 50 lines · Andi Kleen
From: Andi Kleen <[email protected]>
With the indirect call thunk enabled compiler two objtool warnings are triggered very frequently and make the build very noisy.
I don't see a good way to avoid them, so just disable them for now.
Signed-off-by Andi Kleen <[email protected]>--- tools/objtool/check.c | 11 +++++++++++ 1 file changed, 11 insertions(+)tools/objtool/check.c +11
-0@@ -503,8 +503,13 @@ static int add_call_destinations(struct objtool_file *file) insn->call_dest =find_symbol_by_offset (insn->sec, dest_off);if (!insn->call_dest) { +#if 0 +/* Compilers with -mindirect-branch=thunk-extern trigger +* this everywhere on x86. Disable for now. +*/ WARN_FUNC ("can't find call dest symbol at offset 0x%lx" , insn->sec, insn->offset, dest_off); +#endif return -1 ; } }else if (rela->sym->type ==STT_SECTION ) {@@ -1716,8 +1721,14 @@ static int validate_branch(struct objtool_file *file, struct instruction *first,return 1 ; }else if (func &&has_modified_stack_frame (&state)) { +#if 0 +/* Compilers with -mindirect-branch=thunk-extern trigger +* this everywhere on x86. Disable for now. +*/ +WARN_FUNC ("sibling call from callable instruction with modified stack frame" , sec, insn->offset); +#endif return 1 ; }Signature · 1 line
2.14.3
NAK. We can't blindly disable objtool warnings, that will break livepatch and the ORC unwinder. If you share a .o file (or the GCC code) I can look at adding retpoline support.
Signature · 1 line
Josh
Re: [PATCH v2 11/12] retpoline/objtool: Disable some objtool warnings
Quoted 4 lines · Josh Poimboeuf
NAK. We can't blindly disable objtool warnings, that will break livepatch and the ORC unwinder. If you share a .o file (or the GCC code) I can look at adding retpoline support.
I put packages for Fedora 27 at ftp://ftp.infradead.org/pub/retpoline/
Re: [PATCH v2 11/12] retpoline/objtool: Disable some objtool warnings
In reply to Josh PoimboeufQuoted 3 lines
NAK. We can't blindly disable objtool warnings, that will break livepatch and the ORC unwinder. If you share a .o file (or the GCC code) I can look at adding retpoline support.
I don't think we can wait for that. We can disable livepatch and the unwinder for now. They are not essential. Frame pointers should work well enough for unwinding and afaik nobody can use livepatch in mainline anyways.
-Andi
Re: [PATCH v2 11/12] retpoline/objtool: Disable some objtool warnings
Quoted 7 lines · Andi Kleen
Quoted 3 lines
NAK. We can't blindly disable objtool warnings, that will break livepatch and the ORC unwinder. If you share a .o file (or the GCC code) I can look at adding retpoline support.
I don't think we can wait for that. We can disable livepatch and the unwinder for now. They are not essential. Frame pointers should work well enough for unwinding
If you want to make this feature conflict with livepatch and ORC, silencing objtool warnings is not the way to do it.
Quoted 1 line
and afaik nobody can use livepatch in mainline anyways.
Why not? The patch creation tooling is still out-of-tree, but livepatch itself is fully supported in mainline.
Signature · 1 line
Josh
Re: [PATCH v2 11/12] retpoline/objtool: Disable some objtool warnings
Quoted 11 lines · Josh Poimboeuf
Quoted 7 lines · Andi Kleen
Quoted 3 lines
NAK. We can't blindly disable objtool warnings, that will break livepatch and the ORC unwinder. If you share a .o file (or the GCC code) I can look at adding retpoline support.
I don't think we can wait for that. We can disable livepatch and the unwinder for now. They are not essential. Frame pointers should work well enough for unwinding
If you want to make this feature conflict with livepatch and ORC, silencing objtool warnings is not the way to do it.
I don't see why it would conflict with the unwinder anyways?
It doesn't change the long term stack state, so it should be invisible to the unwinder (unless you crash in the thunk, which is very unlikely)
I actually got some unwinder backtraces during development and they seemed to work.
Quoted 5 lines
Quoted 2 lines
and afaik nobody can use livepatch in mainline anyways.
Why not? The patch creation tooling is still out-of-tree, but livepatch itself is fully supported in mainline.
Ok.
Still doesn't seem critical at this point if it's some out of tree thing.
-Andi
Re: [PATCH v2 11/12] retpoline/objtool: Disable some objtool warnings
Quoted 13 lines · Andi Kleen
Quoted 11 lines · Josh Poimboeuf
Quoted 7 lines · Andi Kleen
Quoted 3 lines
NAK. We can't blindly disable objtool warnings, that will break livepatch and the ORC unwinder. If you share a .o file (or the GCC code) I can look at adding retpoline support.
I don't think we can wait for that. We can disable livepatch and the unwinder for now. They are not essential. Frame pointers should work well enough for unwinding
If you want to make this feature conflict with livepatch and ORC, silencing objtool warnings is not the way to do it.
Quoted 7 lines
I don't see why it would conflict with the unwinder anyways?
It doesn't change the long term stack state, so it should be invisible to the unwinder (unless you crash in the thunk, which is very unlikely)
I actually got some unwinder backtraces during development and they seemed to work.
Those objtool warnings are places where ORC annotations are either missing or wrong.
At the very least, this needs to conflict with HAVE_RELIABLE_STACKTRACE and HAVE_STACK_VALIDATION until objtool can understand the new code. Currently ORC relies on HAVE_STACK_VALIDATION, so CONFIG_UNWINDER_ORC would need to be disabled as well.
Quoted 9 lines
Quoted 4 lines
Quoted 1 line
and afaik nobody can use livepatch in mainline anyways.
Why not? The patch creation tooling is still out-of-tree, but livepatch itself is fully supported in mainline.
Ok.
Still doesn't seem critical at this point if it's some out of tree thing.
There are many livepatch users out there who would disagree. The out-of-tree bits aren't in kernel space. If your patches are ready before objtool supports them, then fine, make them conflict with objtool. But please don't introduce silent breakage.
Either way we'll need to figure out a way to get objtool support ASAP.
Signature · 1 line
Josh
Re: [PATCH v2 11/12] retpoline/objtool: Disable some objtool warnings
Quoted 1 line · Josh Poimboeuf
Either way we'll need to figure out a way to get objtool support ASAP.
BTW, I got dwmw2's GCC patches but I'm about to disappear for a few days so it'll probably be next week before I get a chance to look at this.
Signature · 1 line
Josh
PATCH v2 12/12 retpoline: Attempt to quiten objtool warning for unreachable code
In reply to Andi KleenFrom: Andi Kleen <[email protected]>
The speculative jump trampoline has to contain unreachable code. objtool keeps complaining
arch/x86/lib/retpoline.o: warning: objtool: __x86.indirect_thunk()+0x8: unreachable instruction
I tried to fix it here by adding ASM_UNREACHABLE annotation (after supporting them for pure assembler), but it still complains. Seems like a objtool bug?
So it doesn't actually fix the warning oyet.
Of course it's just a warning so the kernel will still work fine.
Perhaps Josh can figure it out
--- arch/x86/lib/retpoline.S | 3 +++ include/linux/compiler.h | 10 +++++++++- 2 files changed, 12 insertions(+), 1 deletion(-)
arch/x86/lib/retpoline.S +3 -0
@@ -11,6 +11,7 @@ */ #include <linux/linkage.h> +#include <linux/compiler.h> #include <asm/dwarf2.h> #include <asm/export.h>
@@ -21,7 +22,9 @@ ENTRY(__x86.indirect_thunk) call retpoline_call_target 2: lfence /* stop speculation */ + ASM_UNREACHABLE jmp 2b + ASM_UNREACHABLE retpoline_call_target: #ifdef CONFIG_64BIT lea 8(%rsp), %rsp
include/linux/compiler.h +9 -1
@@ -269,7 +269,15 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s#endif /* __KERNEL__ */ -#endif /* __ASSEMBLY__ */ +#else /* __ASSEMBLY__ */ + +#define ASM_UNREACHABLE \ + 999: \ + .pushsection .discard.unreachable; \ + .long 999b - .; \ + .popsection + +#endif /* !__ASSEMBLY__ */ /* Compile time object size, -1 for unknown */ #ifndef __compiletime_object_size
Signature · 1 line
2.14.3
Hi!
Quoted 6 lines
This is a fix for Variant 2 in
https://googleprojectzero.blogspot.com/2018/01/reading-privileged-memory-with-side.htmlAny speculative indirect calls in the kernel can be tricked to execute any kernel code, which may allow side channel attacks that can leak arbitrary kernel data.
Ok.
Quoted 6 lines
So we want to avoid speculative indirect calls in the kernel.
There's a special code sequence called a retpoline that can do indirect calls without speculation. We use a new compiler option -mindirect-branch=thunk-extern (gcc patch will be released separately) to recompile the kernel with this new sequence.
So... this "retpoline" code is quite tricky; I guess it does the right on recent Intel CPUs. Does it also do the right thing on all the AMD, Cyrix, ... variants?
Is it neccessary on all the CPUs? I guess 486 does not need this?
Pavel
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Quoted 18 lines · On Thu, 4 Jan 2018 12:49:17 +0100 Pavel Machek <[email protected]> wrote:
Hi!
Quoted 6 lines
This is a fix for Variant 2 in
https://googleprojectzero.blogspot.com/2018/01/reading-privileged-memory-with-side.htmlAny speculative indirect calls in the kernel can be tricked to execute any kernel code, which may allow side channel attacks that can leak arbitrary kernel data.
Ok.
Quoted 6 lines
So we want to avoid speculative indirect calls in the kernel.
There's a special code sequence called a retpoline that can do indirect calls without speculation. We use a new compiler option -mindirect-branch=thunk-extern (gcc patch will be released separately) to recompile the kernel with this new sequence.
Quoted 5 lines
So... this "retpoline" code is quite tricky; I guess it does the right on recent Intel CPUs. Does it also do the right thing on all the AMD, Cyrix, ... variants?
Is it neccessary on all the CPUs? I guess 486 does not need this?
It's architecturally valid x86 code so it should work on any x86-32 processor.
You are correct older processors and some of the newer ones don't need it. AMD and VIA I don't know about but for Intel we can probably avoid it on older Atom, on Quark, and the really old CPUs nobody actually runs any more.
That's all an optimization once we have correctness.
Alan
Quoted 27 lines · Alan Cox
Quoted 18 lines · On Thu, 4 Jan 2018 12:49:17 +0100 Pavel Machek <[email protected]> wrote:
Hi!
Quoted 6 lines
This is a fix for Variant 2 in
https://googleprojectzero.blogspot.com/2018/01/reading-privileged-memory-with-side.htmlAny speculative indirect calls in the kernel can be tricked to execute any kernel code, which may allow side channel attacks that can leak arbitrary kernel data.
Ok.
Quoted 6 lines
So we want to avoid speculative indirect calls in the kernel.
There's a special code sequence called a retpoline that can do indirect calls without speculation. We use a new compiler option -mindirect-branch=thunk-extern (gcc patch will be released separately) to recompile the kernel with this new sequence.
Quoted 5 lines
So... this "retpoline" code is quite tricky; I guess it does the right on recent Intel CPUs. Does it also do the right thing on all the AMD, Cyrix, ... variants?
Is it neccessary on all the CPUs? I guess 486 does not need this?
Quoted 7 lines
It's architecturally valid x86 code so it should work on any x86-32 processor.
You are correct older processors and some of the newer ones don't need it. AMD and VIA I don't know about but for Intel we can probably avoid it on older Atom, on Quark, and the really old CPUs nobody actually runs any more.
Ok. I guess I'd like to see comment in file explaining that.
Quoted 1 line
That's all an optimization once we have correctness.
Well, correctness first sounds as a good idea. OTOH for Spectre problem, seems like a fix would be microcode update to flush branch predictor caches on priviledge and context switches. That should make it impractical to exploit for all the systems, not just latest Linux, compiled by lastest Gcc, right?
Pavel
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html