Received: by 10.223.176.5 with SMTP id f5csp552949wra; Tue, 30 Jan 2018 15:50:36 -0800 (PST) X-Google-Smtp-Source: AH8x227sm3GJWYjDT4gcqythiuKbvT3MJ0Mh5tE/L0zJCiy+tcbYb71B5Au6FsJgl1Q3rswO5pzX X-Received: by 10.101.77.207 with SMTP id q15mr25522407pgt.163.1517356236204; Tue, 30 Jan 2018 15:50:36 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1517356236; cv=none; d=google.com; s=arc-20160816; b=DdJcxh8+kCZ/TFwNuum04M/G/re5p/D5iyfBy1Zw+nGRePdSjGTA0Wa/G7KRZIYYOA ZfkAVqToXCmMjJv91X+wdIIRQDJhh18QekvJVMTy2vhiBOAJRsoV/21wn0C07cDJeQJ2 fKB9yz+MSYAANENBLymzAEI0Hr0XsJr5aBNoraQQyc0dBiMpO0DyCxsQVAv2W8obO3IZ 7NWWzhlCXMEFoGsdGmTvB/LPIvctEDBphH6614oVboqismHUL44HhiLpkO6fWF5hIe9U WX2tOdpG2sA9wKVfc/R9GniGgO/+RZJ7c8XCzlOQn+5h/192MZxE5Z6chQd42kDhic3l uKYg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-disposition :content-transfer-encoding:mime-version:robot-unsubscribe:robot-id :git-commit-id:subject:to:references:in-reply-to:reply-to:cc :message-id:from:date:arc-authentication-results; bh=yQGXgttMvjvT6e8EU9P5Q7xhgYI9hdKui35V4Dhyk2M=; b=MFY4sNVHoMzEOBq/jxffarouSyhK9Gp0Q0i4a635Y8w3BFnyT5AxHJqCfYfDqOoZUf 12/kGdcWAjjFOrBmDLnZZlRBaHhxhC2sHglxAP31Aevr38raC/uMdbcLP31ABREsft4z bx8cuH2M2EG3ofWMCnqVQkwQ3FZ5KlPEMfoNTsQuwfI7b4XpRXH1GfQVB6es+/+J5ikb Ln6cMxCbpoF30ByeZkVXjliBxF0j10fBc/n319bbG7sAWZ6Sl20F1lCdtVggn9G/fQf+ IIyugYbw1lqQ4LAO7wlZ9173XyX0XUO+vgHS0FigVYKEspd32DPX/qvabVcp1bpK5d4Y Zoeg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id y16si3047798pfl.374.2018.01.30.15.50.21; Tue, 30 Jan 2018 15:50:36 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753451AbeA3Wkx (ORCPT + 99 others); Tue, 30 Jan 2018 17:40:53 -0500 Received: from terminus.zytor.com ([65.50.211.136]:56789 "EHLO terminus.zytor.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753009AbeA3Wkv (ORCPT ); Tue, 30 Jan 2018 17:40:51 -0500 Received: from terminus.zytor.com (localhost [127.0.0.1]) by terminus.zytor.com (8.15.2/8.15.2) with ESMTP id w0UMdjIQ003611; Tue, 30 Jan 2018 14:39:45 -0800 Received: (from tipbot@localhost) by terminus.zytor.com (8.15.2/8.15.2/Submit) id w0UMdj7M003608; Tue, 30 Jan 2018 14:39:45 -0800 Date: Tue, 30 Jan 2018 14:39:45 -0800 X-Authentication-Warning: terminus.zytor.com: tipbot set sender to tipbot@zytor.com using -f From: tip-bot for Tim Chen Message-ID: Cc: tim.c.chen@linux.intel.com, dwmw@amazon.co.uk, hpa@zytor.com, mingo@kernel.org, linux-kernel@vger.kernel.org, tglx@linutronix.de Reply-To: mingo@kernel.org, hpa@zytor.com, tim.c.chen@linux.intel.com, dwmw@amazon.co.uk, linux-kernel@vger.kernel.org, tglx@linutronix.de In-Reply-To: <1517263487-3708-1-git-send-email-dwmw@amazon.co.uk> References: <1517263487-3708-1-git-send-email-dwmw@amazon.co.uk> To: linux-tip-commits@vger.kernel.org Subject: [tip:x86/pti] x86/speculation: Use Indirect Branch Prediction Barrier in context switch Git-Commit-ID: 18bf3c3ea8ece8f03b6fc58508f2dfd23c7711c7 X-Mailer: tip-git-log-daemon Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=UTF-8 Content-Disposition: inline X-Spam-Status: No, score=-2.9 required=5.0 tests=ALL_TRUSTED,BAYES_00 autolearn=ham autolearn_force=no version=3.4.1 X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on terminus.zytor.com Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Commit-ID: 18bf3c3ea8ece8f03b6fc58508f2dfd23c7711c7 Gitweb: https://git.kernel.org/tip/18bf3c3ea8ece8f03b6fc58508f2dfd23c7711c7 Author: Tim Chen AuthorDate: Mon, 29 Jan 2018 22:04:47 +0000 Committer: Thomas Gleixner CommitDate: Tue, 30 Jan 2018 23:09:21 +0100 x86/speculation: Use Indirect Branch Prediction Barrier in context switch Flush indirect branches when switching into a process that marked itself non dumpable. This protects high value processes like gpg better, without having too high performance overhead. If done naïvely, we could switch to a kernel idle thread and then back to the original process, such as: process A -> idle -> process A In such scenario, we do not have to do IBPB here even though the process is non-dumpable, as we are switching back to the same process after a hiatus. To avoid the redundant IBPB, which is expensive, we track the last mm user context ID. The cost is to have an extra u64 mm context id to track the last mm we were using before switching to the init_mm used by idle. Avoiding the extra IBPB is probably worth the extra memory for this common scenario. For those cases where tlb_defer_switch_to_init_mm() returns true (non PCID), lazy tlb will defer switch to init_mm, so we will not be changing the mm for the process A -> idle -> process A switch. So IBPB will be skipped for this case. Thanks to the reviewers and Andy Lutomirski for the suggestion of using ctx_id which got rid of the problem of mm pointer recycling. Signed-off-by: Tim Chen Signed-off-by: David Woodhouse Signed-off-by: Thomas Gleixner Cc: ak@linux.intel.com Cc: karahmed@amazon.de Cc: arjan@linux.intel.com Cc: torvalds@linux-foundation.org Cc: linux@dominikbrodowski.net Cc: peterz@infradead.org Cc: bp@alien8.de Cc: luto@kernel.org Cc: pbonzini@redhat.com Cc: gregkh@linux-foundation.org Link: https://lkml.kernel.org/r/1517263487-3708-1-git-send-email-dwmw@amazon.co.uk --- arch/x86/include/asm/tlbflush.h | 2 ++ arch/x86/mm/tlb.c | 33 ++++++++++++++++++++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h index d33e4a2..2b8f18c 100644 --- a/arch/x86/include/asm/tlbflush.h +++ b/arch/x86/include/asm/tlbflush.h @@ -174,6 +174,8 @@ struct tlb_state { struct mm_struct *loaded_mm; u16 loaded_mm_asid; u16 next_asid; + /* last user mm's ctx id */ + u64 last_ctx_id; /* * We can be in one of several states: diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c index 5bfe61a..012d026 100644 --- a/arch/x86/mm/tlb.c +++ b/arch/x86/mm/tlb.c @@ -6,13 +6,14 @@ #include #include #include +#include #include #include +#include #include #include #include -#include /* * TLB flushing, formerly SMP-only @@ -247,6 +248,27 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next, } else { u16 new_asid; bool need_flush; + u64 last_ctx_id = this_cpu_read(cpu_tlbstate.last_ctx_id); + + /* + * Avoid user/user BTB poisoning by flushing the branch + * predictor when switching between processes. This stops + * one process from doing Spectre-v2 attacks on another. + * + * As an optimization, flush indirect branches only when + * switching into processes that disable dumping. This + * protects high value processes like gpg, without having + * too high performance overhead. IBPB is *expensive*! + * + * This will not flush branches when switching into kernel + * threads. It will also not flush if we switch to idle + * thread and back to the same process. It will flush if we + * switch to a different non-dumpable process. + */ + if (tsk && tsk->mm && + tsk->mm->context.ctx_id != last_ctx_id && + get_dumpable(tsk->mm) != SUID_DUMP_USER) + indirect_branch_prediction_barrier(); if (IS_ENABLED(CONFIG_VMAP_STACK)) { /* @@ -292,6 +314,14 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next, trace_tlb_flush_rcuidle(TLB_FLUSH_ON_TASK_SWITCH, 0); } + /* + * Record last user mm's context id, so we can avoid + * flushing branch buffer with IBPB if we switch back + * to the same user. + */ + if (next != &init_mm) + this_cpu_write(cpu_tlbstate.last_ctx_id, next->context.ctx_id); + this_cpu_write(cpu_tlbstate.loaded_mm, next); this_cpu_write(cpu_tlbstate.loaded_mm_asid, new_asid); } @@ -369,6 +399,7 @@ void initialize_tlbstate_and_flush(void) write_cr3(build_cr3(mm->pgd, 0)); /* Reinitialize tlbstate. */ + this_cpu_write(cpu_tlbstate.last_ctx_id, mm->context.ctx_id); this_cpu_write(cpu_tlbstate.loaded_mm_asid, 0); this_cpu_write(cpu_tlbstate.next_asid, 1); this_cpu_write(cpu_tlbstate.ctxs[0].ctx_id, mm->context.ctx_id);