From patchwork Mon Feb 6 14:57:44 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sergey Dyasli X-Patchwork-Id: 9558175 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 CAD2360413 for ; Mon, 6 Feb 2017 15:00:25 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B9FF527F9A for ; Mon, 6 Feb 2017 15:00:25 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AF04927FB0; Mon, 6 Feb 2017 15:00:25 +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=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 558CF27F9A for ; Mon, 6 Feb 2017 15:00:25 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cakk0-00083l-Ry; Mon, 06 Feb 2017 14:58:04 +0000 Received: from mail6.bemta6.messagelabs.com ([193.109.254.103]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cakjz-00082q-8G for xen-devel@lists.xen.org; Mon, 06 Feb 2017 14:58:03 +0000 Received: from [85.158.143.35] by server-10.bemta-6.messagelabs.com id 2A/1F-13192-AFE88985; Mon, 06 Feb 2017 14:58:02 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFmpjkeJIrShJLcpLzFFi42JxWrohUvdX34w IgwnrmSyWfFzM4sDocXT3b6YAxijWzLyk/IoE1oxr93tYC37LVczbsYepgfGURBcjJ4eEgL/E w3cn2EBsNgE9iY2zXzGB2CICshKru+awdzFycTALHGGUmLrqCDtIQljAUuJo/0ZmEJtFQEXi3 dQdjCA2r4CtxNxTj1ghhspJXNr2BayGU8BOYmHDcrChQkA1b6b8ZISwVSVev9jFAtErKHFy5h Mwm1lAQuLgixfMExh5ZyFJzUKSWsDItIpRozi1qCy1SNfQWC+pKDM9oyQ3MTNH19DATC83tbg 4MT01JzGpWC85P3cTIzB8GIBgB+OXZQGHGCU5mJREeQ09pkYI8SXlp1RmJBZnxBeV5qQWH2KU 4eBQkuC17p0RISRYlJqeWpGWmQMMZJi0BAePkgjvwR6gNG9xQWJucWY6ROoUo6KUOO8mkD4Bk ERGaR5cGyx6LjHKSgnzMgIdIsRTkFqUm1mCKv+KUZyDUUmYNwFkCk9mXgnc9FdAi5mAFm+7Mg 1kcUkiQkqqgTH3V/UF/8UJ6wMWPVDQXPLXPrPZ+P3Oz89ZmjlZ9RNWXOMuZDJ4bP80d5FIW/T zGfbHW5+etrzOemKSyAmW0wt0XZiVDB59mrvu1vVGA8+wNT/4wo4c+vPz5YXVJSfSlRaklW7x ahDq+vdptnDWnqCs+a+ezkiuOnKntWWnyq7g0qoz9qyrbrYpsRRnJBpqMRcVJwIAQG08YZkCA AA= X-Env-Sender: prvs=203acdd53=sergey.dyasli@citrix.com X-Msg-Ref: server-12.tower-21.messagelabs.com!1486393079!56327287!2 X-Originating-IP: [66.165.176.89] X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni44OSA9PiAyMDMwMDc=\n, received_headers: No Received headers X-StarScan-Received: X-StarScan-Version: 9.1.1; banners=-,-,- X-VirusChecked: Checked Received: (qmail 60174 invoked from network); 6 Feb 2017 14:58:01 -0000 Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89) by server-12.tower-21.messagelabs.com with RC4-SHA encrypted SMTP; 6 Feb 2017 14:58:01 -0000 X-IronPort-AV: E=Sophos;i="5.33,342,1477958400"; d="scan'208";a="404675684" From: Sergey Dyasli To: Date: Mon, 6 Feb 2017 14:57:44 +0000 Message-ID: <20170206145747.13885-2-sergey.dyasli@citrix.com> X-Mailer: git-send-email 2.9.3 In-Reply-To: <20170206145747.13885-1-sergey.dyasli@citrix.com> References: <20170206145747.13885-1-sergey.dyasli@citrix.com> MIME-Version: 1.0 Cc: Andrew Cooper , Kevin Tian , Jan Beulich , Jun Nakajima , Sergey Dyasli Subject: [Xen-devel] [PATCH v2 1/4] x86/vmx: introduce vmwrite_safe() X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP Any fail during the original __vmwrite() leads to BUG() which can be easily exploited from a guest in the nested vmx mode. The new function returns error code depending on the outcome: VMsucceed: 0 VMfailValid: VM Instruction Error Number VMfailInvalid: a new VMX_INSN_FAIL_INVALID A new macro GAS_VMX_OP is introduced in order to improve the readability of asm. Existing ASM_FLAG_OUT macro is reused and copied into asm_defns.h Signed-off-by: Sergey Dyasli Acked-by: Kevin Tian --- xen/arch/x86/hvm/vmx/vvmx.c | 3 ++- xen/include/asm-x86/asm_defns.h | 6 ++++++ xen/include/asm-x86/hvm/vmx/vmcs.h | 1 + xen/include/asm-x86/hvm/vmx/vmx.h | 29 +++++++++++++++++++++++++++++ 4 files changed, 38 insertions(+), 1 deletion(-) diff --git a/xen/arch/x86/hvm/vmx/vvmx.c b/xen/arch/x86/hvm/vmx/vvmx.c index 9caebe5..105a3c0 100644 --- a/xen/arch/x86/hvm/vmx/vvmx.c +++ b/xen/arch/x86/hvm/vmx/vvmx.c @@ -483,7 +483,8 @@ static void vmfail_invalid(struct cpu_user_regs *regs) static void vmfail(struct cpu_user_regs *regs, enum vmx_insn_errno errno) { - if ( vcpu_nestedhvm(current).nv_vvmcxaddr != INVALID_PADDR ) + if ( vcpu_nestedhvm(current).nv_vvmcxaddr != INVALID_PADDR && + errno != VMX_INSN_FAIL_INVALID ) vmfail_valid(regs, errno); else vmfail_invalid(regs); diff --git a/xen/include/asm-x86/asm_defns.h b/xen/include/asm-x86/asm_defns.h index f1c6fa1..220ae2e 100644 --- a/xen/include/asm-x86/asm_defns.h +++ b/xen/include/asm-x86/asm_defns.h @@ -413,4 +413,10 @@ static always_inline void stac(void) #define REX64_PREFIX "rex64/" #endif +#ifdef __GCC_ASM_FLAG_OUTPUTS__ +# define ASM_FLAG_OUT(yes, no) yes +#else +# define ASM_FLAG_OUT(yes, no) no +#endif + #endif /* __X86_ASM_DEFNS_H__ */ diff --git a/xen/include/asm-x86/hvm/vmx/vmcs.h b/xen/include/asm-x86/hvm/vmx/vmcs.h index d71de04..8d43efd 100644 --- a/xen/include/asm-x86/hvm/vmx/vmcs.h +++ b/xen/include/asm-x86/hvm/vmx/vmcs.h @@ -526,6 +526,7 @@ enum vmx_insn_errno VMX_INSN_VMPTRLD_INVALID_PHYADDR = 9, VMX_INSN_UNSUPPORTED_VMCS_COMPONENT = 12, VMX_INSN_VMXON_IN_VMX_ROOT = 15, + VMX_INSN_FAIL_INVALID = ~0, }; void vmx_disable_intercept_for_msr(struct vcpu *v, u32 msr, int type); diff --git a/xen/include/asm-x86/hvm/vmx/vmx.h b/xen/include/asm-x86/hvm/vmx/vmx.h index 4bf4d50..d40d6a5 100644 --- a/xen/include/asm-x86/hvm/vmx/vmx.h +++ b/xen/include/asm-x86/hvm/vmx/vmx.h @@ -306,6 +306,12 @@ extern uint8_t posted_intr_vector; #define INVVPID_ALL_CONTEXT 2 #define INVVPID_SINGLE_CONTEXT_RETAINING_GLOBAL 3 +#ifdef HAVE_GAS_VMX +# define GAS_VMX_OP(yes, no) yes +#else +# define GAS_VMX_OP(yes, no) no +#endif + static always_inline void __vmptrld(u64 addr) { asm volatile ( @@ -423,6 +429,29 @@ static inline bool_t __vmread_safe(unsigned long field, unsigned long *value) return okay; } +static always_inline unsigned long vmwrite_safe(unsigned long field, + unsigned long value) +{ + unsigned long ret = 0; + bool fail_invalid, fail_valid; + + asm volatile ( GAS_VMX_OP("vmwrite %[value], %[field]\n\t", + VMWRITE_OPCODE MODRM_EAX_ECX) + ASM_FLAG_OUT(, "setc %[invalid]\n\t") + ASM_FLAG_OUT(, "setz %[valid]\n\t") + : ASM_FLAG_OUT("=@ccc", [invalid] "=rm") (fail_invalid), + ASM_FLAG_OUT("=@ccz", [valid] "=rm") (fail_valid) + : [field] GAS_VMX_OP("r", "a") (field), + [value] GAS_VMX_OP("rm", "c") (value)); + + if ( unlikely(fail_invalid) ) + ret = VMX_INSN_FAIL_INVALID; + else if ( unlikely(fail_valid) ) + __vmread(VM_INSTRUCTION_ERROR, &ret); + + return ret; +} + static always_inline void __invept(unsigned long type, u64 eptp, u64 gpa) { struct {