Received: by 2002:ac0:a5a6:0:0:0:0:0 with SMTP id m35-v6csp36180imm; Thu, 30 Aug 2018 07:46:46 -0700 (PDT) X-Google-Smtp-Source: ANB0VdZ/3+Qfm/5dmUQHK65SoU/22qZCy46ykyAsm2Y36qVJnHiizNkWUgBqFVb+JtSDpVwdzPbT X-Received: by 2002:a62:411a:: with SMTP id o26-v6mr10917458pfa.111.1535640406625; Thu, 30 Aug 2018 07:46:46 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1535640406; cv=none; d=google.com; s=arc-20160816; b=PVPvBScny9A2pYGJJD+HYOyJzDNrknvZu1cvgTh55rkZiY+nk5lrjpzJVBLi5oqXaP XIYwNwR8UaTG71yeDljFZGqNpVwn87fOW4tu2Nmmzw3EBsD1Wby6eGJFKP8vHSBFSIKf UImwRmBgEAR0VjyeE74nxY5njDGgDtscT2KAqOH16EdAFeFVysoF92nOD3pW2RwvkjJ2 VibOu3pDUHrBG6FbDX6xPTfHxTJtjI6G0kMD1HC/Svjy8+BmGM25mWnHuzv0Fi8akz2Q eUA3kcPWe+HcJVKRi7O2bJnteEmKkgWlcmC0682ejrgzDIruBmUqj/f0jMH5gbjjWpQS 7ERg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:arc-authentication-results; bh=+qTPVKzf+lhK4h/nXP6cgw6G1mAsYcJ5dN3/fmhpEfs=; b=DhLy19Nnj0gIlV3wrQaG5eW9kUPEc5WR33I7h/7CKyKYLhm7AK31yMcKpptS+zqfUO Mot0ZVme/xolpcGCGmoWJSmUksEnwlyedq54iXIAWV3lHvzCtHfd/rHQrDiJmNKNpHtf To1DrHhbILNBY3UxEznbfngds09rxgxQomR4Y1792GlINlYkXa/66orvwAWxldflKez4 Gtf7mKP6I4Z209kV/xFHCpSj2A7QvuutFlkFpMu4w8qmmJI6fYlo1pcXAOmJT30oqQlL XZXWW/w48frcBW9h0l9rl7tT0RiUuSAdZHc+GwUITtGVMKl3iqXMBAOShDA++wvjT1Eo amCw== 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; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 65-v6si6829941pld.451.2018.08.30.07.46.32; Thu, 30 Aug 2018 07:46:46 -0700 (PDT) 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; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729662AbeH3SqV (ORCPT + 99 others); Thu, 30 Aug 2018 14:46:21 -0400 Received: from mga01.intel.com ([192.55.52.88]:38430 "EHLO mga01.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729627AbeH3SqU (ORCPT ); Thu, 30 Aug 2018 14:46:20 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga101.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 30 Aug 2018 07:43:44 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.53,307,1531810800"; d="scan'208";a="67186727" Received: from 2b52.sc.intel.com ([143.183.136.52]) by fmsmga008.fm.intel.com with ESMTP; 30 Aug 2018 07:43:42 -0700 From: Yu-cheng Yu To: x86@kernel.org, "H. Peter Anvin" , Thomas Gleixner , Ingo Molnar , linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-mm@kvack.org, linux-arch@vger.kernel.org, linux-api@vger.kernel.org, Arnd Bergmann , Andy Lutomirski , Balbir Singh , Cyrill Gorcunov , Dave Hansen , Florian Weimer , "H.J. Lu" , Jann Horn , Jonathan Corbet , Kees Cook , Mike Kravetz , Nadav Amit , Oleg Nesterov , Pavel Machek , Peter Zijlstra , "Ravi V. Shankar" , Vedvyas Shanbhogue Cc: Yu-cheng Yu Subject: [RFC PATCH v3 19/24] x86/cet/shstk: Introduce WRUSS instruction Date: Thu, 30 Aug 2018 07:38:59 -0700 Message-Id: <20180830143904.3168-20-yu-cheng.yu@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180830143904.3168-1-yu-cheng.yu@intel.com> References: <20180830143904.3168-1-yu-cheng.yu@intel.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org WRUSS is a new kernel-mode instruction but writes directly to user shadow stack memory. This is used to construct a return address on the shadow stack for the signal handler. This instruction can fault if the user shadow stack is invalid shadow stack memory. In that case, the kernel does fixup. Signed-off-by: Yu-cheng Yu --- arch/x86/include/asm/special_insns.h | 37 ++++++++++++++++++++++++++++ arch/x86/mm/extable.c | 11 +++++++++ arch/x86/mm/fault.c | 9 +++++++ 3 files changed, 57 insertions(+) diff --git a/arch/x86/include/asm/special_insns.h b/arch/x86/include/asm/special_insns.h index 317fc59b512c..9f609e802c5c 100644 --- a/arch/x86/include/asm/special_insns.h +++ b/arch/x86/include/asm/special_insns.h @@ -237,6 +237,43 @@ static inline void clwb(volatile void *__p) : [pax] "a" (p)); } +#ifdef CONFIG_X86_INTEL_CET + +#if defined(CONFIG_IA32_EMULATION) || defined(CONFIG_X86_X32) +static inline int write_user_shstk_32(unsigned long addr, unsigned int val) +{ + int err = 0; + + asm volatile("1: wrussd %1, (%0)\n" + "2:\n" + _ASM_EXTABLE_HANDLE(1b, 2b, ex_handler_wruss) + : + : "r" (addr), "r" (val)); + + return err; +} +#else +static inline int write_user_shstk_32(unsigned long addr, unsigned int val) +{ + BUG(); + return 0; +} +#endif + +static inline int write_user_shstk_64(unsigned long addr, unsigned long val) +{ + int err = 0; + + asm volatile("1: wrussq %1, (%0)\n" + "2:\n" + _ASM_EXTABLE_HANDLE(1b, 2b, ex_handler_wruss) + : + : "r" (addr), "r" (val)); + + return err; +} +#endif /* CONFIG_X86_INTEL_CET */ + #define nop() asm volatile ("nop") diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c index 45f5d6cf65ae..e06ff851b671 100644 --- a/arch/x86/mm/extable.c +++ b/arch/x86/mm/extable.c @@ -157,6 +157,17 @@ __visible bool ex_handler_clear_fs(const struct exception_table_entry *fixup, } EXPORT_SYMBOL(ex_handler_clear_fs); +#ifdef CONFIG_X86_INTEL_CET +__visible bool ex_handler_wruss(const struct exception_table_entry *fixup, + struct pt_regs *regs, int trapnr) +{ + regs->ip = ex_fixup_addr(fixup); + regs->ax = -1; + return true; +} +EXPORT_SYMBOL(ex_handler_wruss); +#endif + __visible bool ex_has_fault_handler(unsigned long ip) { const struct exception_table_entry *e; diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 3842353fb4a3..10dbb5c9aaef 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -1305,6 +1305,15 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code, error_code |= X86_PF_USER; flags |= FAULT_FLAG_USER; } else { + /* + * WRUSS is a kernel instrcution and but writes + * to user shadow stack. When a fault occurs, + * both X86_PF_USER and X86_PF_SHSTK are set. + * Clear X86_PF_USER here. + */ + if ((error_code & (X86_PF_USER | X86_PF_SHSTK)) == + (X86_PF_USER | X86_PF_SHSTK)) + error_code &= ~X86_PF_USER; if (regs->flags & X86_EFLAGS_IF) local_irq_enable(); } -- 2.17.1