Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 3160499aacb81f6735941eb4c372d87a > files > 333

kvm-83-164.el5_5.30.src.rpm

From 003483ecab5258fbbf6593983dfde0b7ef59dcdb Mon Sep 17 00:00:00 2001
From: Gleb Natapov <gleb@redhat.com>
Date: Mon, 1 Feb 2010 17:14:58 +0200
Subject: [PATCH 7/7] Check CPL level during privilege instruction emulation.

Add CPL checking in case emulator is tricked into emulating
privilege instruction.

Message-Id: <1265037298-12612-8-git-send-email-gleb@redhat.com>
CVE: CVE-2010-0306
Bugzilla: 560698
Acked-by: Marcelo Tosatti <mtosatti@redhat.com>
Acked-by: Juan Quintela <quintela@redhat.com>
Acked-by: Chris Wright <chrisw@redhat.com>

Signed-off-by: Gleb Natapov <gleb@redhat.com>
---
 arch/x86/kvm/x86_emulate.c |  137 ++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 137 insertions(+), 0 deletions(-)

diff --git a/arch/x86/kvm/x86_emulate.c b/arch/x86/kvm/x86_emulate.c
index 69caed0..9e7d5ca 100644
--- a/arch/x86/kvm/x86_emulate.c
+++ b/arch/x86/kvm/x86_emulate.c
@@ -1900,6 +1900,14 @@ special_insn:
 		}
 		break;
 	case 0xf4:              /* hlt */
+		if (c->lock_prefix) {
+			kvm_queue_exception(ctxt->vcpu, UD_VECTOR);
+			goto done;
+		}
+		if (kvm_x86_ops->get_cpl(ctxt->vcpu)) {
+			kvm_inject_gp(ctxt->vcpu, 0);
+			goto done;
+		}
 		ctxt->vcpu->arch.halt_request = 1;
 		break;
 	case 0xf5:	/* cmc */
@@ -1975,6 +1983,11 @@ twobyte_insn:
 			if (c->modrm_mod != 3 || c->modrm_rm != 1)
 				goto cannot_emulate;
 
+			if (kvm_x86_ops->get_cpl(ctxt->vcpu)) {
+				kvm_inject_gp(ctxt->vcpu, 0);
+				goto done;
+			}
+
 			rc = kvm_fix_hypercall(ctxt->vcpu);
 			if (rc)
 				goto done;
@@ -1985,6 +1998,16 @@ twobyte_insn:
 			c->dst.type = OP_NONE;
 			break;
 		case 2: /* lgdt */
+			if (c->lock_prefix) {
+				kvm_queue_exception(ctxt->vcpu, UD_VECTOR);
+				goto done;
+			}
+
+			if (kvm_x86_ops->get_cpl(ctxt->vcpu)) {
+				kvm_inject_gp(ctxt->vcpu, 0);
+				goto done;
+			}
+
 			rc = read_descriptor(ctxt, ops, c->src.ptr,
 					     &size, &address, c->op_bytes);
 			if (rc)
@@ -1995,11 +2018,26 @@ twobyte_insn:
 			break;
 		case 3: /* lidt/vmmcall */
 			if (c->modrm_mod == 3 && c->modrm_rm == 1) {
+				if (kvm_x86_ops->get_cpl(ctxt->vcpu)) {
+					kvm_inject_gp(ctxt->vcpu, 0);
+					goto done;
+				}
+
 				rc = kvm_fix_hypercall(ctxt->vcpu);
 				if (rc)
 					goto done;
 				kvm_emulate_hypercall(ctxt->vcpu);
 			} else {
+				if (c->lock_prefix) {
+					kvm_queue_exception(ctxt->vcpu, UD_VECTOR);
+					goto done;
+				}
+
+				if (kvm_x86_ops->get_cpl(ctxt->vcpu)) {
+					kvm_inject_gp(ctxt->vcpu, 0);
+					goto done;
+				}
+
 				rc = read_descriptor(ctxt, ops, c->src.ptr,
 						     &size, &address,
 						     c->op_bytes);
@@ -2015,11 +2053,26 @@ twobyte_insn:
 			c->dst.val = realmode_get_cr(ctxt->vcpu, 0);
 			break;
 		case 6: /* lmsw */
+			if (kvm_x86_ops->get_cpl(ctxt->vcpu)) {
+				kvm_inject_gp(ctxt->vcpu, 0);
+				goto done;
+			}
+
 			realmode_lmsw(ctxt->vcpu, (u16)c->src.val,
 				      &ctxt->eflags);
 			c->dst.type = OP_NONE;
 			break;
 		case 7: /* invlpg*/
+			if (c->lock_prefix) {
+				kvm_queue_exception(ctxt->vcpu, UD_VECTOR);
+				goto done;
+			}
+
+			if (kvm_x86_ops->get_cpl(ctxt->vcpu)) {
+				kvm_inject_gp(ctxt->vcpu, 0);
+				goto done;
+			}
+
 			emulate_invlpg(ctxt->vcpu, memop);
 			/* Disable writeback. */
 			c->dst.type = OP_NONE;
@@ -2029,23 +2082,67 @@ twobyte_insn:
 		}
 		break;
 	case 0x06:
+		if (c->lock_prefix) {
+			if (ctxt->mode == X86EMUL_MODE_REAL ||
+			    !(ctxt->vcpu->arch.cr0 & X86_CR0_PE))
+				kvm_queue_exception(ctxt->vcpu, UD_VECTOR);
+			else
+				kvm_inject_gp(ctxt->vcpu, 0);
+			goto done;
+		}
+
+		if (kvm_x86_ops->get_cpl(ctxt->vcpu)) {
+			kvm_inject_gp(ctxt->vcpu, 0);
+			goto done;
+		}
+
 		emulate_clts(ctxt->vcpu);
 		c->dst.type = OP_NONE;
 		break;
 	case 0x08:		/* invd */
 	case 0x09:		/* wbinvd */
+		if (c->lock_prefix) {
+			kvm_queue_exception(ctxt->vcpu, UD_VECTOR);
+			goto done;
+		}
+
+		if (kvm_x86_ops->get_cpl(ctxt->vcpu)) {
+			kvm_inject_gp(ctxt->vcpu, 0);
+			goto done;
+		}
 	case 0x0d:		/* GrpP (prefetch) */
 	case 0x18:		/* Grp16 (prefetch/nop) */
 		c->dst.type = OP_NONE;
 		break;
 	case 0x20: /* mov cr, reg */
+		if (c->lock_prefix) {
+			kvm_queue_exception(ctxt->vcpu, UD_VECTOR);
+			goto done;
+		}
+
+		if (kvm_x86_ops->get_cpl(ctxt->vcpu)) {
+			kvm_inject_gp(ctxt->vcpu, 0);
+			goto done;
+		}
+
 		if (c->modrm_mod != 3)
 			goto cannot_emulate;
+
 		c->regs[c->modrm_rm] =
 				realmode_get_cr(ctxt->vcpu, c->modrm_reg);
 		c->dst.type = OP_NONE;	/* no writeback */
 		break;
 	case 0x21: /* mov from dr to reg */
+		if (c->lock_prefix) {
+			kvm_queue_exception(ctxt->vcpu, UD_VECTOR);
+			goto done;
+		}
+
+		if (kvm_x86_ops->get_cpl(ctxt->vcpu)) {
+			kvm_inject_gp(ctxt->vcpu, 0);
+			goto done;
+		}
+
 		if (c->modrm_mod != 3)
 			goto cannot_emulate;
 		rc = emulator_get_dr(ctxt, c->modrm_reg, &c->regs[c->modrm_rm]);
@@ -2054,6 +2151,16 @@ twobyte_insn:
 		c->dst.type = OP_NONE;	/* no writeback */
 		break;
 	case 0x22: /* mov reg, cr */
+		if (c->lock_prefix) {
+			kvm_queue_exception(ctxt->vcpu, UD_VECTOR);
+			goto done;
+		}
+
+		if (kvm_x86_ops->get_cpl(ctxt->vcpu)) {
+			kvm_inject_gp(ctxt->vcpu, 0);
+			goto done;
+		}
+
 		if (c->modrm_mod != 3)
 			goto cannot_emulate;
 		realmode_set_cr(ctxt->vcpu,
@@ -2061,6 +2168,16 @@ twobyte_insn:
 		c->dst.type = OP_NONE;
 		break;
 	case 0x23: /* mov from reg to dr */
+		if (c->lock_prefix) {
+			kvm_queue_exception(ctxt->vcpu, UD_VECTOR);
+			goto done;
+		}
+
+		if (kvm_x86_ops->get_cpl(ctxt->vcpu)) {
+			kvm_inject_gp(ctxt->vcpu, 0);
+			goto done;
+		}
+
 		if (c->modrm_mod != 3)
 			goto cannot_emulate;
 		rc = emulator_set_dr(ctxt, c->modrm_reg,
@@ -2071,6 +2188,16 @@ twobyte_insn:
 		break;
 	case 0x30:
 		/* wrmsr */
+		if (c->lock_prefix) {
+			kvm_queue_exception(ctxt->vcpu, UD_VECTOR);
+			goto done;
+		}
+
+		if (kvm_x86_ops->get_cpl(ctxt->vcpu)) {
+			kvm_inject_gp(ctxt->vcpu, 0);
+			goto done;
+		}
+
 		msr_data = (u32)c->regs[VCPU_REGS_RAX]
 			| ((u64)c->regs[VCPU_REGS_RDX] << 32);
 		rc = kvm_set_msr(ctxt->vcpu, c->regs[VCPU_REGS_RCX], msr_data);
@@ -2083,6 +2210,16 @@ twobyte_insn:
 		break;
 	case 0x32:
 		/* rdmsr */
+		if (c->lock_prefix) {
+			kvm_queue_exception(ctxt->vcpu, UD_VECTOR);
+			goto done;
+		}
+
+		if (kvm_x86_ops->get_cpl(ctxt->vcpu)) {
+			kvm_inject_gp(ctxt->vcpu, 0);
+			goto done;
+		}
+
 		rc = kvm_get_msr(ctxt->vcpu, c->regs[VCPU_REGS_RCX], &msr_data);
 		if (rc) {
 			kvm_inject_gp(ctxt->vcpu, 0);
-- 
1.6.3.rc4.29.g8146