From patchwork Thu Jun 7 14:36:57 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yu-cheng Yu X-Patchwork-Id: 10452263 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 6716560146 for ; Thu, 7 Jun 2018 14:40:52 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4A9422960F for ; Thu, 7 Jun 2018 14:40:52 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 47A30295F7; Thu, 7 Jun 2018 14:40:52 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00, MAILING_LIST_MULTI, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 64D82295D5 for ; Thu, 7 Jun 2018 14:40:46 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id BE09A6B026A; Thu, 7 Jun 2018 10:40:42 -0400 (EDT) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id B8BD76B026B; Thu, 7 Jun 2018 10:40:42 -0400 (EDT) X-Original-To: int-list-linux-mm@kvack.org X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id A2AF36B026C; Thu, 7 Jun 2018 10:40:42 -0400 (EDT) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from mail-pf0-f199.google.com (mail-pf0-f199.google.com [209.85.192.199]) by kanga.kvack.org (Postfix) with ESMTP id 5F90F6B026A for ; Thu, 7 Jun 2018 10:40:42 -0400 (EDT) Received: by mail-pf0-f199.google.com with SMTP id z9-v6so4623153pfe.23 for ; Thu, 07 Jun 2018 07:40:42 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-original-authentication-results:x-gm-message-state:from:to:cc :subject:date:message-id:in-reply-to:references; bh=XRms6x6XTekyArqfYmDjv9Hy7o2CfMasSQUEUsqgqEY=; b=PQPEzI5687ug+i3oBX7/rbXYh3dzh0+rVOznWG5Y1Kv9u1Fif97lbEbW+QoSS+lHiG NBnfZlcvY3W13aBrCeWDTaxYMNx5Y4fw5c0OCEM/2HdMg5g84g6kqDMtr0ZsSVoT7rCt eDko3Uc5I+r3MDquc+pz5oqWKSKrzmLGwqAGj15fVngdBPzsgmjt+3CjLxrM7hODdsAI K0+oHPM27Z172gUMYRl9cqFBuVuoXVJk/53pArK4wWZ6qJUTMna7AfSUiE/xuzmi0R5A 6w3plV/zuAF7MWvSpz1APFZRLMNvtW1WknAtB8FUQsaR8Hvsvmen3XvG71AGp5KgH+a2 vnGw== X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of yu-cheng.yu@intel.com designates 134.134.136.126 as permitted sender) smtp.mailfrom=yu-cheng.yu@intel.com; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com X-Gm-Message-State: APt69E2m3vJEun31xDziw09b4pt4Mf2HuZZT5+euAeg1mvXIzPpCNXAD tZOrvP1vuH0J/1+SEDtjSKspREAxtgqLO4cSwdYNhNyqVVFnezPQ0SaCBiCjup4X6yVJd3HYFqA OhUffMGKzBEmvRosNlGphgMWSNnJfy56RqQr4kMN0tuqfyXHygTlxJ82RDc/IsC/XAg== X-Received: by 2002:a62:e005:: with SMTP id f5-v6mr2075377pfh.88.1528382442048; Thu, 07 Jun 2018 07:40:42 -0700 (PDT) X-Google-Smtp-Source: ADUXVKL8R18oTIck6ALc+GBM0Arr8MAVzIN55wrfqdJqzG1dVBMK97WiruIZ/S3HkKsPJCBGM8wH X-Received: by 2002:a62:e005:: with SMTP id f5-v6mr2075326pfh.88.1528382441126; Thu, 07 Jun 2018 07:40:41 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1528382441; cv=none; d=google.com; s=arc-20160816; b=D2YCAyKflEvPHOPabQdEjDqqfHt+B6Svda3LS2RoZyG5RqOhDUMeme2guQ7Wlo8yew zxZ2SJRI+QZTaYbo8rxsobkJGPBJKmOfzvS7WQ6gimJg30nyQB+30rypa8MqYnNC1vag 629HWDc1d9jttc71tQEIiEB8+gM0l3uNAenncACZQACwcsyfHMPTqlPZt71ygDNAZO5X ZfLpDnosynpCYSA+5TD+iKSMs8umfFosX9r3mkyTALeG46weY/vYd5JY3Whsr5cn7mqQ 6T5kOBim1FQcFuQC4keV60+Iid2eIQe0lsHjLvWdesYDhY+6AzsK8Eo2qz73kc8oWx2o 1JXQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=references:in-reply-to:message-id:date:subject:cc:to:from :arc-authentication-results; bh=XRms6x6XTekyArqfYmDjv9Hy7o2CfMasSQUEUsqgqEY=; b=FlmOnaNno4YzruBQMAS8/OXhRNB8dGVtR9nccwOJeRjbUTL9/0NX3/q9FHGeEn63tU BMToj5tpii8CQR6Z95IdVU2b7PzIzKhG2DkawdDuHJ71q3CEIpE2Jw59kdvImPKuczM8 dgp1ZEoLXBiqmIYx6TdUzOgfWvcEpDHPrxuGFUtNk6mnbcbD4QGUh3hpOmVDr8hUZll/ B5gZ1xXrUogDmWeq6Tisx4jh92X7+mv418cF5HEvNrj4lrBdhj3JgmFt4uAu0v6gsFF/ WpuyaczrDSt/qe3JQZkhZQ4JvQiyJj5lz4aMRy3HqgFo1+pCuWC+gme/EJ5RFTAhgJhl u1eQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of yu-cheng.yu@intel.com designates 134.134.136.126 as permitted sender) smtp.mailfrom=yu-cheng.yu@intel.com; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: from mga18.intel.com (mga18.intel.com. [134.134.136.126]) by mx.google.com with ESMTPS id b60-v6si54342625plc.270.2018.06.07.07.40.40 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 07 Jun 2018 07:40:41 -0700 (PDT) Received-SPF: pass (google.com: domain of yu-cheng.yu@intel.com designates 134.134.136.126 as permitted sender) client-ip=134.134.136.126; Authentication-Results: mx.google.com; spf=pass (google.com: domain of yu-cheng.yu@intel.com designates 134.134.136.126 as permitted sender) smtp.mailfrom=yu-cheng.yu@intel.com; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga008.jf.intel.com ([10.7.209.65]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 07 Jun 2018 07:40:31 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.49,486,1520924400"; d="scan'208";a="47542286" Received: from 2b52.sc.intel.com ([143.183.136.51]) by orsmga008.jf.intel.com with ESMTP; 07 Jun 2018 07:40:31 -0700 From: Yu-cheng Yu To: linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-mm@kvack.org, linux-arch@vger.kernel.org, x86@kernel.org, "H. Peter Anvin" , Thomas Gleixner , Ingo Molnar , "H.J. Lu" , Vedvyas Shanbhogue , "Ravi V. Shankar" , Dave Hansen , Andy Lutomirski , Jonathan Corbet , Oleg Nesterov , Arnd Bergmann , Mike Kravetz Cc: Yu-cheng Yu Subject: [PATCH 1/9] x86/cet: Control protection exception handler Date: Thu, 7 Jun 2018 07:36:57 -0700 Message-Id: <20180607143705.3531-2-yu-cheng.yu@intel.com> X-Mailer: git-send-email 2.15.1 In-Reply-To: <20180607143705.3531-1-yu-cheng.yu@intel.com> References: <20180607143705.3531-1-yu-cheng.yu@intel.com> X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: X-Virus-Scanned: ClamAV using ClamSMTP A control protection exception is triggered when a control flow transfer attempt violated shadow stack or indirect branch tracking constraints. For example, the return address for a RET instruction differs from the safe copy on the shadow stack; or a JMP instruction arrives at a non- ENDBR instruction. The control protection exception handler works in a similar way as the general protection fault handler. Signed-off-by: Yu-cheng Yu --- arch/x86/entry/entry_32.S | 5 ++++ arch/x86/entry/entry_64.S | 2 +- arch/x86/include/asm/traps.h | 3 +++ arch/x86/kernel/idt.c | 1 + arch/x86/kernel/traps.c | 61 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 71 insertions(+), 1 deletion(-) diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S index bef8e2b202a8..14b63ef0d7d8 100644 --- a/arch/x86/entry/entry_32.S +++ b/arch/x86/entry/entry_32.S @@ -1070,6 +1070,11 @@ ENTRY(general_protection) jmp common_exception END(general_protection) +ENTRY(control_protection) + pushl $do_control_protection + jmp common_exception +END(control_protection) + #ifdef CONFIG_KVM_GUEST ENTRY(async_page_fault) ASM_CLAC diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S index 3166b9674429..5230f705d229 100644 --- a/arch/x86/entry/entry_64.S +++ b/arch/x86/entry/entry_64.S @@ -999,7 +999,7 @@ idtentry spurious_interrupt_bug do_spurious_interrupt_bug has_error_code=0 idtentry coprocessor_error do_coprocessor_error has_error_code=0 idtentry alignment_check do_alignment_check has_error_code=1 idtentry simd_coprocessor_error do_simd_coprocessor_error has_error_code=0 - +idtentry control_protection do_control_protection has_error_code=1 /* * Reload gs selector with exception handling diff --git a/arch/x86/include/asm/traps.h b/arch/x86/include/asm/traps.h index 3de69330e6c5..5196050ff3d5 100644 --- a/arch/x86/include/asm/traps.h +++ b/arch/x86/include/asm/traps.h @@ -26,6 +26,7 @@ asmlinkage void invalid_TSS(void); asmlinkage void segment_not_present(void); asmlinkage void stack_segment(void); asmlinkage void general_protection(void); +asmlinkage void control_protection(void); asmlinkage void page_fault(void); asmlinkage void async_page_fault(void); asmlinkage void spurious_interrupt_bug(void); @@ -77,6 +78,7 @@ dotraplinkage void do_stack_segment(struct pt_regs *, long); dotraplinkage void do_double_fault(struct pt_regs *, long); #endif dotraplinkage void do_general_protection(struct pt_regs *, long); +dotraplinkage void do_control_protection(struct pt_regs *, long); dotraplinkage void do_page_fault(struct pt_regs *, unsigned long); dotraplinkage void do_spurious_interrupt_bug(struct pt_regs *, long); dotraplinkage void do_coprocessor_error(struct pt_regs *, long); @@ -142,6 +144,7 @@ enum { X86_TRAP_AC, /* 17, Alignment Check */ X86_TRAP_MC, /* 18, Machine Check */ X86_TRAP_XF, /* 19, SIMD Floating-Point Exception */ + X86_TRAP_CP = 21, /* 21 Control Protection Fault */ X86_TRAP_IRET = 32, /* 32, IRET Exception */ }; diff --git a/arch/x86/kernel/idt.c b/arch/x86/kernel/idt.c index 2c3a1b4294eb..d00493709cec 100644 --- a/arch/x86/kernel/idt.c +++ b/arch/x86/kernel/idt.c @@ -85,6 +85,7 @@ static const __initconst struct idt_data def_idts[] = { INTG(X86_TRAP_MF, coprocessor_error), INTG(X86_TRAP_AC, alignment_check), INTG(X86_TRAP_XF, simd_coprocessor_error), + INTG(X86_TRAP_CP, control_protection), #ifdef CONFIG_X86_32 TSKG(X86_TRAP_DF, GDT_ENTRY_DOUBLEFAULT_TSS), diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 03f3d7695dac..4e8769a19aaf 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -577,6 +577,67 @@ do_general_protection(struct pt_regs *regs, long error_code) } NOKPROBE_SYMBOL(do_general_protection); +static const char *control_protection_err[] = +{ + "near-ret", + "far-ret/iret", + "endbranch", + "rstorssp", + "setssbsy", + "unknown", +}; + +/* + * When a control protection exception occurs, send a signal + * to the responsible application. Currently, control + * protection is only enabled for the user mode. This + * exception should not come from the kernel mode. + */ +dotraplinkage void +do_control_protection(struct pt_regs *regs, long error_code) +{ + struct task_struct *tsk; + + RCU_LOCKDEP_WARN(!rcu_is_watching(), "entry code didn't wake RCU"); + cond_local_irq_enable(regs); + + tsk = current; + if (!cpu_feature_enabled(X86_FEATURE_SHSTK) && + !cpu_feature_enabled(X86_FEATURE_IBT)) { + goto exit; + } + + if (!user_mode(regs)) { + tsk->thread.error_code = error_code; + tsk->thread.trap_nr = X86_TRAP_CP; + if (notify_die(DIE_TRAP, "control protection fault", regs, + error_code, X86_TRAP_CP, SIGSEGV) != NOTIFY_STOP) + die("control protection fault", regs, error_code); + return; + } + + tsk->thread.error_code = error_code; + tsk->thread.trap_nr = X86_TRAP_CP; + + if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) && + printk_ratelimit()) { + unsigned int max_idx, err_idx; + + max_idx = ARRAY_SIZE(control_protection_err) - 1; + err_idx = min((unsigned int)error_code - 1, max_idx); + pr_info("%s[%d] control protection ip:%lx sp:%lx error:%lx(%s)", + tsk->comm, task_pid_nr(tsk), + regs->ip, regs->sp, error_code, + control_protection_err[err_idx]); + print_vma_addr(" in ", regs->ip); + pr_cont("\n"); + } + +exit: + force_sig_info(SIGSEGV, SEND_SIG_PRIV, tsk); +} +NOKPROBE_SYMBOL(do_control_protection); + dotraplinkage void notrace do_int3(struct pt_regs *regs, long error_code) { #ifdef CONFIG_DYNAMIC_FTRACE