From: David Woodhouse <dwmw2@infradead.org>
To: David Woodhouse <dwmw@amazon.co.uk>, Andi Kleen <ak@linux.intel.com>
Cc: Paul Turner <pjt@google.com>, LKML <linux-kernel@vger.kernel.org>,
Linus Torvalds <torvalds@linux-foundation.org>,
Greg Kroah-Hartman <gregkh@linux-foundation.org>,
Tim Chen <tim.c.chen@linux.intel.com>,
Dave Hansen <dave.hansen@intel.com>,
tglx@linutronix.de, Kees Cook <keescook@google.com>,
Rik van Riel <riel@redhat.com>,
Peter Zijlstra <peterz@infradead.org>,
Andy Lutomirski <luto@amacapital.net>,
Jiri Kosina <jikos@kernel.org>,
gnomes@lxorguk.ukuu.org.uk
Subject: [PATCH v6 11/10] x86/retpoline: Avoid return buffer underflows on context switch
Date: Mon, 08 Jan 2018 23:44:11 +0000 [thread overview]
Message-ID: <1515455051.15588.7.camel@infradead.org> (raw)
In-Reply-To: <1515363085-4219-1-git-send-email-dwmw@amazon.co.uk>
This patch further hardens retpoline.
CPUs have return buffers which store the return address for
RET to predict function returns. Some CPUs (Skylake, some Broadwells)
can fall back to indirect branch prediction on return buffer underflow.
With retpoline we want to avoid uncontrolled indirect branches,
which could be poisoned by ring 3, so we need to avoid uncontrolled
return buffer underflows in the kernel.
This can happen when we're context switching from a shallower to a
deeper kernel stack. The deeper kernel stack would eventually underflow
the return buffer, which again would fall back to the indirect branch predictor.
To guard against this fill the return buffer with controlled
content during context switch. This prevents any underflows.
We always fill the buffer with 30 entries: 32 minus 2 for at
least one call from entry_{64,32}.S to C code and another into
the function doing the filling.
That's pessimistic because we likely did more controlled kernel calls.
So in principle we could do less. However it's hard to maintain such an
invariant, and it may be broken with more aggressive compilers.
So err on the side of safety and always fill 30.
[dwmw2: Fix comments about nop between calls,
Move #ifdef CONFIG_RETPOLINE to call sites not macro]
Signed-off-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
---
arch/x86/entry/entry_32.S | 17 +++++++++++++++++
arch/x86/entry/entry_64.S | 17 +++++++++++++++++
arch/x86/include/asm/nospec-branch.h | 30 ++++++++++++++++++++++++++++++
3 files changed, 64 insertions(+)
diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S
index cf9ef33d299b..b6b83b9d3a0b 100644
--- a/arch/x86/entry/entry_32.S
+++ b/arch/x86/entry/entry_32.S
@@ -250,6 +250,23 @@ ENTRY(__switch_to_asm)
popl %ebx
popl %ebp
+#ifdef CONFIG_RETPOLINE
+ /*
+ * When we switch from a shallower to a deeper call stack
+ * the call stack will underflow in the kernel in the next task.
+ * This could cause the CPU to fall back to indirect branch
+ * prediction, which may be poisoned.
+ *
+ * To guard against that always fill the return stack with
+ * known values.
+ *
+ * We do this in assembler because it needs to be before
+ * any calls on the new stack, and this can be difficult to
+ * ensure in a complex C function like __switch_to.
+ */
+ ALTERNATIVE "jmp __switch_to", "", X86_FEATURE_RETPOLINE
+ FILL_RETURN_BUFFER
+#endif
jmp __switch_to
END(__switch_to_asm)
diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S
index 9bce6ed03353..1622e07c5ae8 100644
--- a/arch/x86/entry/entry_64.S
+++ b/arch/x86/entry/entry_64.S
@@ -495,6 +495,23 @@ ENTRY(__switch_to_asm)
popq %rbx
popq %rbp
+#ifdef CONFIG_RETPOLINE
+ /*
+ * When we switch from a shallower to a deeper call stack
+ * the call stack will underflow in the kernel in the next task.
+ * This could cause the CPU to fall back to indirect branch
+ * prediction, which may be poisoned.
+ *
+ * To guard against that always fill the return stack with
+ * known values.
+ *
+ * We do this in assembler because it needs to be before
+ * any calls on the new stack, and this can be difficult to
+ * ensure in a complex C function like __switch_to.
+ */
+ ALTERNATIVE "jmp __switch_to", "", X86_FEATURE_RETPOLINE
+ FILL_RETURN_BUFFER
+#endif
jmp __switch_to
END(__switch_to_asm)
diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h
index b8c8eeacb4be..3022b1a4de17 100644
--- a/arch/x86/include/asm/nospec-branch.h
+++ b/arch/x86/include/asm/nospec-branch.h
@@ -53,6 +53,36 @@
#endif
.endm
+/*
+ * We use 32-N: 32 is the max return buffer size, but there should
+ * have been at a minimum two controlled calls already: one into the
+ * kernel from entry*.S and another into the function containing this
+ * macro. So N=2, thus 30.
+ */
+#define NUM_BRANCHES_TO_FILL 30
+
+/*
+ * Fill the CPU return stack buffer to prevent indirect branch
+ * prediction on underflow. We need a 'nop' after each call so it
+ * isn't interpreted by the CPU as a simple 'push %eip', which would
+ * be handled specially and not put anything in the RSB.
+ *
+ * Required in various cases for retpoline and IBRS-based mitigations
+ * for Spectre variant 2 vulnerability.
+ */
+.macro FILL_RETURN_BUFFER
+ .rept NUM_BRANCHES_TO_FILL
+ call 1221f
+ nop
+1221:
+ .endr
+#ifdef CONFIG_64BIT
+ addq $8*NUM_BRANCHES_TO_FILL, %rsp
+#else
+ addl $4*NUM_BRANCHES_TO_FILL, %esp
+#endif
+.endm
+
#else /* __ASSEMBLY__ */
#if defined(CONFIG_X86_64) && defined(RETPOLINE)
--
2.14.3
next prev parent reply other threads:[~2018-01-08 23:44 UTC|newest]
Thread overview: 66+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-01-07 22:11 [PATCH v6 00/10] Retpoline: Avoid speculative indirect calls in kernel David Woodhouse
2018-01-07 22:11 ` [PATCH v6 01/10] x86/retpoline: Add initial retpoline support David Woodhouse
2018-01-08 10:45 ` Peter Zijlstra
2018-01-08 10:53 ` David Woodhouse
2018-01-08 11:03 ` Peter Zijlstra
2018-01-08 12:45 ` David Woodhouse
2018-01-08 13:42 ` Josh Poimboeuf
2018-01-08 13:46 ` Thomas Gleixner
2018-01-08 13:53 ` Josh Poimboeuf
2018-01-08 14:26 ` David Woodhouse
2018-01-08 21:20 ` Josh Poimboeuf
2018-01-09 12:36 ` Peter Zijlstra
2018-01-09 13:35 ` Thomas Gleixner
2018-01-09 13:40 ` Woodhouse, David
2018-01-07 22:11 ` [PATCH v6 02/10] x86/retpoline/crypto: Convert crypto assembler indirect jumps David Woodhouse
2018-01-08 13:49 ` Josh Poimboeuf
2018-01-07 22:11 ` [PATCH v6 03/10] x86/retpoline/entry: Convert entry " David Woodhouse
2018-01-07 22:11 ` [PATCH v6 04/10] x86/retpoline/ftrace: Convert ftrace " David Woodhouse
2018-01-07 22:11 ` [PATCH v6 05/10] x86/retpoline/hyperv: Convert " David Woodhouse
2018-01-07 22:11 ` [PATCH v6 06/10] x86/retpoline/xen: Convert Xen hypercall " David Woodhouse
2018-01-07 22:11 ` [PATCH v6 07/10] x86/retpoline/checksum32: Convert assembler " David Woodhouse
2018-01-07 22:11 ` [PATCH v6 08/10] x86/retpoline/irq32: " David Woodhouse
2018-01-07 22:11 ` [PATCH v6 09/10] x86/retpoline: Add boot time option to disable retpoline David Woodhouse
2018-01-07 22:11 ` [PATCH v6 10/10] x86/retpoline: Exclude objtool with retpoline David Woodhouse
2018-01-08 10:25 ` Thomas Gleixner
2018-01-08 10:34 ` Woodhouse, David
2018-01-08 13:20 ` Josh Poimboeuf
2018-01-07 22:22 ` [PATCH v6 00/10] Retpoline: Avoid speculative indirect calls in kernel Linus Torvalds
2018-01-08 10:01 ` Thomas Gleixner
2018-01-08 17:54 ` Ingo Molnar
2018-01-08 21:10 ` Thomas Gleixner
2018-01-08 10:34 ` Paul Turner
2018-01-08 10:38 ` Jiri Kosina
2018-01-08 10:45 ` Paul Turner
2018-01-08 10:42 ` Paul Turner
2018-01-08 11:16 ` Andrew Cooper
2018-01-08 11:25 ` Paul Turner
2018-01-08 16:13 ` Alexei Starovoitov
2018-01-10 15:20 ` Woodhouse, David
2018-01-10 15:31 ` Dr. David Alan Gilbert
2018-01-08 10:45 ` David Woodhouse
2018-01-08 10:53 ` Paul Turner
2018-01-08 12:49 ` David Woodhouse
2018-01-08 23:44 ` David Woodhouse [this message]
2018-01-08 23:56 ` [PATCH v6 11/10] x86/retpoline: Avoid return buffer underflows on context switch Linus Torvalds
2018-01-08 23:58 ` Woodhouse, David
2018-01-09 0:35 ` Linus Torvalds
2018-01-09 0:42 ` David Woodhouse
2018-01-09 0:48 ` Linus Torvalds
2018-01-09 0:55 ` David Woodhouse
2018-01-09 0:44 ` Andi Kleen
2018-01-09 0:58 ` Linus Torvalds
2018-01-09 1:15 ` Andrew Cooper
2018-01-09 3:27 ` Andy Lutomirski
2018-01-09 13:04 ` David Woodhouse
2018-01-09 13:10 ` Peter Zijlstra
2018-01-09 17:53 ` Kees Cook
2018-01-09 18:09 ` Linus Torvalds
2018-02-16 8:58 ` Pavel Machek
2018-01-09 1:16 ` Andi Kleen
2018-01-09 1:21 ` [PATCH v6 11/10] x86/retpoline: Avoid return buffer underflows on context switch II Andi Kleen
2018-01-09 1:23 ` Woodhouse, David
2018-01-09 1:49 ` Andi Kleen
2018-01-09 1:53 ` Paul Turner
2018-01-09 1:18 ` [PATCH v6 11/10] x86/retpoline: Avoid return buffer underflows on context switch Woodhouse, David
2018-01-09 0:06 ` Andi Kleen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1515455051.15588.7.camel@infradead.org \
--to=dwmw2@infradead.org \
--cc=ak@linux.intel.com \
--cc=dave.hansen@intel.com \
--cc=dwmw@amazon.co.uk \
--cc=gnomes@lxorguk.ukuu.org.uk \
--cc=gregkh@linux-foundation.org \
--cc=jikos@kernel.org \
--cc=keescook@google.com \
--cc=linux-kernel@vger.kernel.org \
--cc=luto@amacapital.net \
--cc=peterz@infradead.org \
--cc=pjt@google.com \
--cc=riel@redhat.com \
--cc=tglx@linutronix.de \
--cc=tim.c.chen@linux.intel.com \
--cc=torvalds@linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®