Home
Reading
Searching
Subscribe
Sponsors
Statistics
Posting
Contact
Spam
Lists
Links
About
Hosting
Filtering
Features Download
Marketing
Archives
FAQ
Blog
 
Gmane

From: Linux Kernel Mailing List <linux-kernel <at> vger.kernel.org>
Subject: KVM: x86: SYSENTER emulation is broken
Newsgroups: gmane.linux.kernel.commits.head
Date: Friday 23rd January 2015 22:04:20 UTC (over 3 years ago)
Gitweb:     http://git.kernel.org/linus/;a=commit;h=f3747379accba8e95d70cec0eae0582c8c182050
Commit:     f3747379accba8e95d70cec0eae0582c8c182050
Parent:     63ea0a49ae0b145b91ff2b070c01b66fc75854b9
Refname:    refs/heads/master
Author:     Nadav Amit 
AuthorDate: Thu Jan 1 23:11:11 2015 +0200
Committer:  Paolo Bonzini 
CommitDate: Fri Jan 23 13:57:15 2015 +0100

    KVM: x86: SYSENTER emulation is broken
    
    SYSENTER emulation is broken in several ways:
    1. It misses the case of 16-bit code segments completely
(CVE-2015-0239).
    2. MSR_IA32_SYSENTER_CS is checked in 64-bit mode incorrectly (bits 0
and 1 can
       still be set without causing #GP).
    3. MSR_IA32_SYSENTER_EIP and MSR_IA32_SYSENTER_ESP are not masked in
       legacy-mode.
    4. There is some unneeded code.
    
    Fix it.
    
    Cc: [email protected]
    Signed-off-by: Nadav Amit 
    Signed-off-by: Paolo Bonzini 
---
 arch/x86/kvm/emulate.c | 27 ++++++++-------------------
 1 file changed, 8 insertions(+), 19 deletions(-)

diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 817c6ca..de12c1d 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -2348,7 +2348,7 @@ static int em_sysenter(struct x86_emulate_ctxt *ctxt)
 	 * Not recognized on AMD in compat mode (but is recognized in legacy
 	 * mode).
 	 */
-	if ((ctxt->mode == X86EMUL_MODE_PROT32) && (efer & EFER_LMA)
+	if ((ctxt->mode != X86EMUL_MODE_PROT64) && (efer & EFER_LMA)
 	    && !vendor_intel(ctxt))
 		return emulate_ud(ctxt);
 
@@ -2359,25 +2359,13 @@ static int em_sysenter(struct x86_emulate_ctxt
*ctxt)
 	setup_syscalls_segments(ctxt, &cs, &ss);
 
 	ops->get_msr(ctxt, MSR_IA32_SYSENTER_CS, &msr_data);
-	switch (ctxt->mode) {
-	case X86EMUL_MODE_PROT32:
-		if ((msr_data & 0xfffc) == 0x0)
-			return emulate_gp(ctxt, 0);
-		break;
-	case X86EMUL_MODE_PROT64:
-		if (msr_data == 0x0)
-			return emulate_gp(ctxt, 0);
-		break;
-	default:
-		break;
-	}
+	if ((msr_data & 0xfffc) == 0x0)
+		return emulate_gp(ctxt, 0);
 
 	ctxt->eflags &= ~(EFLG_VM | EFLG_IF);
-	cs_sel = (u16)msr_data;
-	cs_sel &= ~SELECTOR_RPL_MASK;
+	cs_sel = (u16)msr_data & ~SELECTOR_RPL_MASK;
 	ss_sel = cs_sel + 8;
-	ss_sel &= ~SELECTOR_RPL_MASK;
-	if (ctxt->mode == X86EMUL_MODE_PROT64 || (efer & EFER_LMA)) {
+	if (efer & EFER_LMA) {
 		cs.d = 0;
 		cs.l = 1;
 	}
@@ -2386,10 +2374,11 @@ static int em_sysenter(struct x86_emulate_ctxt
*ctxt)
 	ops->set_segment(ctxt, ss_sel, &ss, 0, VCPU_SREG_SS);
 
 	ops->get_msr(ctxt, MSR_IA32_SYSENTER_EIP, &msr_data);
-	ctxt->_eip = msr_data;
+	ctxt->_eip = (efer & EFER_LMA) ? msr_data : (u32)msr_data;
 
 	ops->get_msr(ctxt, MSR_IA32_SYSENTER_ESP, &msr_data);
-	*reg_write(ctxt, VCPU_REGS_RSP) = msr_data;
+	*reg_write(ctxt, VCPU_REGS_RSP) = (efer & EFER_LMA) ? msr_data :
+							      (u32)msr_data;
 
 	return X86EMUL_CONTINUE;
 }
--
To unsubscribe from this list: send the line "unsubscribe git-commits-head"
in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
 
CD: 163ms