linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: David Woodhouse <dwmw@amazon.co.uk>
To: 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, x86@kernel.org
Subject: [PATCH v7 11/11] x86/retpoline: Avoid return buffer underflows on context switch
Date: Tue,  9 Jan 2018 14:43:17 +0000	[thread overview]
Message-ID: <1515508997-6154-12-git-send-email-dwmw@amazon.co.uk> (raw)
In-Reply-To: <1515508997-6154-1-git-send-email-dwmw@amazon.co.uk>

From: Andi Kleen <ak@linux.intel.com>

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.

retpoline is supposed to prevent uncontrolled indirect branch speculation,
which could be poisoned by ring 3, so it needs to prevent uncontrolled
return buffer underflows in the kernel as well.

This can happen when a context switch from a shallower to a deeper kernel
stack happens.  The deeper kernel stack would eventually underflow the
return buffer, which again would make the CPU 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.

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
fill.

That's pessimistic because there are likely more controlled kernel calls
before this happens, but it depends on compiler optimizations and other
factors so avoid speculative optimization, error on the side of safety and
always fill 30 entries.

[dwmw2: Fix comments about nop between calls, Move #ifdef CONFIG_RETPOLINE
	to call sites not macro. Use Google's original RSB stuffing.]

[tglx: Massaged changelog ]

Signed-off-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
Cc: gnomes@lxorguk.ukuu.org.uk
Cc: Rik van Riel <riel@redhat.com>
Cc: Tim Chen <tim.c.chen@linux.intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Paul Turner <pjt@google.com>
Cc: Jiri Kosina <jikos@kernel.org>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Dave Hansen <dave.hansen@intel.com>
Cc: Kees Cook <keescook@google.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Greg Kroah-Hartman <gregkh@linux-foundation.org>
---
 arch/x86/entry/entry_32.S            | 17 ++++++++++++++
 arch/x86/entry/entry_64.S            | 17 ++++++++++++++
 arch/x86/include/asm/nospec-branch.h | 44 ++++++++++++++++++++++++++++++++++++
 3 files changed, 78 insertions(+)

diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S
index a1f28a5..d2ef7f32 100644
--- a/arch/x86/entry/entry_32.S
+++ b/arch/x86/entry/entry_32.S
@@ -244,6 +244,23 @@ ENTRY(__switch_to_asm)
 	movl	%ebx, PER_CPU_VAR(stack_canary)+stack_canary_offset
 #endif
 
+#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 "", "FILL_RETURN_BUFFER %ebx", X86_FEATURE_RETPOLINE
+#endif
+
 	/* restore callee-saved registers */
 	popl	%esi
 	popl	%edi
diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S
index 59874bc..58dbf7a 100644
--- a/arch/x86/entry/entry_64.S
+++ b/arch/x86/entry/entry_64.S
@@ -487,6 +487,23 @@ ENTRY(__switch_to_asm)
 	movq	%rbx, PER_CPU_VAR(irq_stack_union)+stack_canary_offset
 #endif
 
+#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 "", "FILL_RETURN_BUFFER %r12", X86_FEATURE_RETPOLINE
+#endif
+
 	/* restore callee-saved registers */
 	popq	%r15
 	popq	%r14
diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h
index a86e845..4f80ec8 100644
--- a/arch/x86/include/asm/nospec-branch.h
+++ b/arch/x86/include/asm/nospec-branch.h
@@ -64,6 +64,50 @@
 #endif
 .endm
 
+/*
+ * 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.
+
+ * A 'nop' after each call is required so it isn't interpreted by the CPU
+ * as a simple 'push %eip', which would be handled specially and would 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 reg:req
+	mov	$NUM_BRANCHES_TO_FILL/2, \reg
+	.align	16
+.Ldo_call1_\@:
+	call	.Ldo_call2_\@
+.Ltrap1_\@:
+	pause
+	jmp	.Ltrap1_\@
+	.align	16
+.Ldo_call2_\@:
+	call	.Ldo_loop_\@
+.Ltrap2_\@:
+	pause
+	jmp	.Ltrap2_\@
+	.align	16
+.Ldo_loop_\@:
+	dec	\reg
+	jnz	.Ldo_call1_\@
+#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.7.4

  parent reply	other threads:[~2018-01-09 14:44 UTC|newest]

Thread overview: 64+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-01-09 14:43 [PATCH v7 00/11] Retpoline: Avoid speculative indirect calls in kernel David Woodhouse
2018-01-09 14:43 ` [PATCH v7 01/11] x86/retpoline: Add initial retpoline support David Woodhouse
2018-01-09 15:55   ` [tip:x86/pti] " tip-bot for David Woodhouse
2018-01-10 17:34   ` tip-bot for David Woodhouse
2018-01-10 18:13   ` tip-bot for David Woodhouse
2018-01-10 18:40   ` tip-bot for David Woodhouse
2018-01-09 14:43 ` [PATCH v7 02/11] x86/retpoline: Temporarily disable objtool when CONFIG_RETPOLINE=y David Woodhouse
2018-01-09 15:56   ` [tip:x86/pti] " tip-bot for Andi Kleen
2018-01-10  5:58   ` [PATCH v7 02/11] " Josh Poimboeuf
2018-01-10 10:12     ` Peter Zijlstra
2018-01-10 17:34   ` [tip:x86/pti] " tip-bot for Andi Kleen
2018-01-10 18:13   ` tip-bot for Andi Kleen
2018-01-10 18:40   ` tip-bot for Andi Kleen
2018-01-09 14:43 ` [PATCH v7 03/11] x86/spectre: Add boot time option to select Spectre v2 mitigation David Woodhouse
2018-01-09 15:56   ` [tip:x86/pti] " tip-bot for David Woodhouse
2018-01-10 17:35   ` tip-bot for David Woodhouse
2018-01-10 18:03     ` Tom Lendacky
2018-01-10 18:06       ` Thomas Gleixner
2018-01-10 18:10         ` Thomas Gleixner
2018-01-10 18:14   ` tip-bot for David Woodhouse
2018-01-10 18:33     ` Tom Lendacky
2018-01-10 18:35       ` Thomas Gleixner
2018-01-10 18:41   ` tip-bot for David Woodhouse
2018-01-09 14:43 ` [PATCH v7 04/11] x86/retpoline/crypto: Convert crypto assembler indirect jumps David Woodhouse
2018-01-09 15:56   ` [tip:x86/pti] " tip-bot for David Woodhouse
2018-01-10 17:35   ` tip-bot for David Woodhouse
2018-01-10 18:14   ` tip-bot for David Woodhouse
2018-01-10 18:41   ` tip-bot for David Woodhouse
2018-01-09 14:43 ` [PATCH v7 05/11] x86/retpoline/entry: Convert entry " David Woodhouse
2018-01-09 15:57   ` [tip:x86/pti] " tip-bot for David Woodhouse
2018-01-10  3:54   ` [v7, 05/11] " Andrei Vagin
2018-01-10  4:30     ` Andi Kleen
2018-01-10  4:39       ` Dave Hansen
2018-01-10  5:23         ` Andrei Vagin
2018-01-10 17:36   ` [tip:x86/pti] " tip-bot for David Woodhouse
2018-01-10 18:15   ` tip-bot for David Woodhouse
2018-01-10 18:41   ` tip-bot for David Woodhouse
2018-01-09 14:43 ` [PATCH v7 06/11] x86/retpoline/ftrace: Convert ftrace " David Woodhouse
2018-01-09 15:57   ` [tip:x86/pti] " tip-bot for David Woodhouse
2018-01-10 17:36   ` tip-bot for David Woodhouse
2018-01-10 18:15   ` tip-bot for David Woodhouse
2018-01-10 18:42   ` tip-bot for David Woodhouse
2018-01-09 14:43 ` [PATCH v7 07/11] x86/retpoline/hyperv: Convert " David Woodhouse
2018-01-09 15:58   ` [tip:x86/pti] " tip-bot for David Woodhouse
2018-01-10 17:37   ` tip-bot for David Woodhouse
2018-01-10 18:15   ` tip-bot for David Woodhouse
2018-01-10 18:42   ` tip-bot for David Woodhouse
2018-01-09 14:43 ` [PATCH v7 08/11] x86/retpoline/xen: Convert Xen hypercall " David Woodhouse
2018-01-09 15:58   ` [tip:x86/pti] " tip-bot for David Woodhouse
2018-01-10 17:37   ` tip-bot for David Woodhouse
2018-01-10 18:16   ` tip-bot for David Woodhouse
2018-01-10 18:43   ` tip-bot for David Woodhouse
2018-01-09 14:43 ` [PATCH v7 09/11] x86/retpoline/checksum32: Convert assembler " David Woodhouse
2018-01-09 15:58   ` [tip:x86/pti] " tip-bot for David Woodhouse
2018-01-10 17:37   ` tip-bot for David Woodhouse
2018-01-10 18:16   ` tip-bot for David Woodhouse
2018-01-10 18:43   ` tip-bot for David Woodhouse
2018-01-09 14:43 ` [PATCH v7 10/11] x86/retpoline/irq32: " David Woodhouse
2018-01-09 15:59   ` [tip:x86/pti] " tip-bot for Andi Kleen
2018-01-10 17:38   ` tip-bot for Andi Kleen
2018-01-10 18:17   ` tip-bot for Andi Kleen
2018-01-10 18:43   ` tip-bot for Andi Kleen
2018-01-09 14:43 ` David Woodhouse [this message]
2018-01-09 15:59   ` [tip:x86/pti] x86/retpoline: Avoid return buffer underflows on context switch tip-bot for 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=1515508997-6154-12-git-send-email-dwmw@amazon.co.uk \
    --to=dwmw@amazon.co.uk \
    --cc=ak@linux.intel.com \
    --cc=dave.hansen@intel.com \
    --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 \
    --cc=x86@kernel.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;
as well as URLs for NNTP newsgroup(s).