public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Avi Kivity <avi@redhat.com>
To: linux-kernel@vger.kernel.org
Cc: kvm@vger.kernel.org, Mohammed Gamal <m.gamal005@gmail.com>
Subject: [PATCH 09/39] KVM: VMX: Add Guest State Validity Checks
Date: Thu, 25 Sep 2008 14:54:41 +0300	[thread overview]
Message-ID: <1222343711-12508-10-git-send-email-avi@redhat.com> (raw)
In-Reply-To: <1222343711-12508-1-git-send-email-avi@redhat.com>

From: Mohammed Gamal <m.gamal005@gmail.com>

This patch adds functions to check whether guest state is VMX compliant.

Signed-off-by: Mohammed Gamal <m.gamal005@gmail.com>
Signed-off-by: Avi Kivity <avi@qumranet.com>
---
 arch/x86/kvm/vmx.c |  180 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 180 insertions(+), 0 deletions(-)

diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 81db7d4..e889b76 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -1721,6 +1721,186 @@ static void vmx_set_gdt(struct kvm_vcpu *vcpu, struct descriptor_table *dt)
 	vmcs_writel(GUEST_GDTR_BASE, dt->base);
 }
 
+static bool rmode_segment_valid(struct kvm_vcpu *vcpu, int seg)
+{
+	struct kvm_segment var;
+	u32 ar;
+
+	vmx_get_segment(vcpu, &var, seg);
+	ar = vmx_segment_access_rights(&var);
+
+	if (var.base != (var.selector << 4))
+		return false;
+	if (var.limit != 0xffff)
+		return false;
+	if (ar != 0xf3)
+		return false;
+
+	return true;
+}
+
+static bool code_segment_valid(struct kvm_vcpu *vcpu)
+{
+	struct kvm_segment cs;
+	unsigned int cs_rpl;
+
+	vmx_get_segment(vcpu, &cs, VCPU_SREG_CS);
+	cs_rpl = cs.selector & SELECTOR_RPL_MASK;
+
+	if (~cs.type & (AR_TYPE_CODE_MASK|AR_TYPE_ACCESSES_MASK))
+		return false;
+	if (!cs.s)
+		return false;
+	if (!(~cs.type & (AR_TYPE_CODE_MASK|AR_TYPE_WRITEABLE_MASK))) {
+		if (cs.dpl > cs_rpl)
+			return false;
+	} else if (cs.type & AR_TYPE_CODE_MASK) {
+		if (cs.dpl != cs_rpl)
+			return false;
+	}
+	if (!cs.present)
+		return false;
+
+	/* TODO: Add Reserved field check, this'll require a new member in the kvm_segment_field structure */
+	return true;
+}
+
+static bool stack_segment_valid(struct kvm_vcpu *vcpu)
+{
+	struct kvm_segment ss;
+	unsigned int ss_rpl;
+
+	vmx_get_segment(vcpu, &ss, VCPU_SREG_SS);
+	ss_rpl = ss.selector & SELECTOR_RPL_MASK;
+
+	if ((ss.type != 3) || (ss.type != 7))
+		return false;
+	if (!ss.s)
+		return false;
+	if (ss.dpl != ss_rpl) /* DPL != RPL */
+		return false;
+	if (!ss.present)
+		return false;
+
+	return true;
+}
+
+static bool data_segment_valid(struct kvm_vcpu *vcpu, int seg)
+{
+	struct kvm_segment var;
+	unsigned int rpl;
+
+	vmx_get_segment(vcpu, &var, seg);
+	rpl = var.selector & SELECTOR_RPL_MASK;
+
+	if (!var.s)
+		return false;
+	if (!var.present)
+		return false;
+	if (~var.type & (AR_TYPE_CODE_MASK|AR_TYPE_WRITEABLE_MASK)) {
+		if (var.dpl < rpl) /* DPL < RPL */
+			return false;
+	}
+
+	/* TODO: Add other members to kvm_segment_field to allow checking for other access
+	 * rights flags
+	 */
+	return true;
+}
+
+static bool tr_valid(struct kvm_vcpu *vcpu)
+{
+	struct kvm_segment tr;
+
+	vmx_get_segment(vcpu, &tr, VCPU_SREG_TR);
+
+	if (tr.selector & SELECTOR_TI_MASK)	/* TI = 1 */
+		return false;
+	if ((tr.type != 3) || (tr.type != 11)) /* TODO: Check if guest is in IA32e mode */
+		return false;
+	if (!tr.present)
+		return false;
+
+	return true;
+}
+
+static bool ldtr_valid(struct kvm_vcpu *vcpu)
+{
+	struct kvm_segment ldtr;
+
+	vmx_get_segment(vcpu, &ldtr, VCPU_SREG_LDTR);
+
+	if (ldtr.selector & SELECTOR_TI_MASK)	/* TI = 1 */
+		return false;
+	if (ldtr.type != 2)
+		return false;
+	if (!ldtr.present)
+		return false;
+
+	return true;
+}
+
+static bool cs_ss_rpl_check(struct kvm_vcpu *vcpu)
+{
+	struct kvm_segment cs, ss;
+
+	vmx_get_segment(vcpu, &cs, VCPU_SREG_CS);
+	vmx_get_segment(vcpu, &ss, VCPU_SREG_SS);
+
+	return ((cs.selector & SELECTOR_RPL_MASK) ==
+		 (ss.selector & SELECTOR_RPL_MASK));
+}
+
+/*
+ * Check if guest state is valid. Returns true if valid, false if
+ * not.
+ * We assume that registers are always usable
+ */
+static bool guest_state_valid(struct kvm_vcpu *vcpu)
+{
+	/* real mode guest state checks */
+	if (!(vcpu->arch.cr0 & X86_CR0_PE)) {
+		if (!rmode_segment_valid(vcpu, VCPU_SREG_CS))
+			return false;
+		if (!rmode_segment_valid(vcpu, VCPU_SREG_SS))
+			return false;
+		if (!rmode_segment_valid(vcpu, VCPU_SREG_DS))
+			return false;
+		if (!rmode_segment_valid(vcpu, VCPU_SREG_ES))
+			return false;
+		if (!rmode_segment_valid(vcpu, VCPU_SREG_FS))
+			return false;
+		if (!rmode_segment_valid(vcpu, VCPU_SREG_GS))
+			return false;
+	} else {
+	/* protected mode guest state checks */
+		if (!cs_ss_rpl_check(vcpu))
+			return false;
+		if (!code_segment_valid(vcpu))
+			return false;
+		if (!stack_segment_valid(vcpu))
+			return false;
+		if (!data_segment_valid(vcpu, VCPU_SREG_DS))
+			return false;
+		if (!data_segment_valid(vcpu, VCPU_SREG_ES))
+			return false;
+		if (!data_segment_valid(vcpu, VCPU_SREG_FS))
+			return false;
+		if (!data_segment_valid(vcpu, VCPU_SREG_GS))
+			return false;
+		if (!tr_valid(vcpu))
+			return false;
+		if (!ldtr_valid(vcpu))
+			return false;
+	}
+	/* TODO:
+	 * - Add checks on RIP
+	 * - Add checks on RFLAGS
+	 */
+
+	return true;
+}
+
 static int init_rmode_tss(struct kvm *kvm)
 {
 	gfn_t fn = rmode_tss_base(kvm) >> PAGE_SHIFT;
-- 
1.6.0.1


  parent reply	other threads:[~2008-09-25 11:58 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-09-25 11:54 [PATCH 00/39] KVM Updates for 2.6.28 merge window (part 2 of 3) Avi Kivity
2008-09-25 11:54 ` [PATCH 01/39] KVM: VMX: Clean up magic number 0x66 in init_rmode_tss Avi Kivity
2008-09-25 11:54 ` [PATCH 02/39] KVM: remove unused field from the assigned dev struct Avi Kivity
2008-09-25 11:54 ` [PATCH 03/39] KVM: set debug registers after "schedulable" section Avi Kivity
2008-09-25 11:54 ` [PATCH 04/39] KVM: VMX: Use interrupt queue for !irqchip_in_kernel Avi Kivity
2008-09-25 11:54 ` [PATCH 05/39] KVM: Simplify exception entries by using __ASM_SIZE and _ASM_PTR Avi Kivity
2008-09-25 11:54 ` [PATCH 06/39] KVM: fix i8259 reset irq acking Avi Kivity
2008-09-25 11:54 ` [PATCH 07/39] KVM: Handle spurious acks for PIT interrupts Avi Kivity
2008-09-25 11:54 ` [PATCH 08/39] KVM: Device assignment: Check for privileges before assigning irq Avi Kivity
2008-09-25 11:54 ` Avi Kivity [this message]
2008-09-25 11:54 ` [PATCH 10/39] KVM: VMX: Add module parameter and emulation flag Avi Kivity
2008-09-25 11:54 ` [PATCH 11/39] KVM: VMX: Add invalid guest state handler Avi Kivity
2008-09-25 11:54 ` [PATCH 12/39] KVM: VMX: Modify mode switching and vmentry functions Avi Kivity
2008-09-25 11:54 ` [PATCH 13/39] KVM: SVM: Fix typo Avi Kivity
2008-09-25 11:54 ` [PATCH 14/39] KVM: Use kvm_set_irq to inject interrupts Avi Kivity
2008-09-25 11:54 ` [PATCH 15/39] KVM: make irq ack notifier functions static Avi Kivity
2008-09-25 11:54 ` [PATCH 16/39] KVM: ia64: add a dummy irq ack notification Avi Kivity
2008-09-25 11:54 ` [PATCH 17/39] KVM: VMX: Change cs reset state to be a data segment Avi Kivity
2008-09-25 11:54 ` [PATCH 18/39] KVM: VMX: Change segment dpl at reset to 3 Avi Kivity
2008-09-25 11:54 ` [PATCH 19/39] KVM: Load real mode segments correctly Avi Kivity
2008-09-25 11:54 ` [PATCH 20/39] KVM: x86 emulator: remove duplicate SrcImm Avi Kivity
2008-09-25 11:54 ` [PATCH 21/39] KVM: x86 emulator: remove bad ByteOp specifier from NEG descriptor Avi Kivity
2008-09-25 11:54 ` [PATCH 22/39] KVM: MMU: Move SHADOW_PT_INDEX to mmu.c Avi Kivity
2008-09-25 11:54 ` [PATCH 23/39] KVM: MMU: Unify direct map 4K and large page paths Avi Kivity
2008-09-25 11:54 ` [PATCH 24/39] KVM: ia64: Enable virtio driver for ia64 in Kconfig Avi Kivity
2008-09-25 11:54 ` [PATCH 25/39] KVM: MMU: Infer shadow root level in direct_map() Avi Kivity
2008-09-25 11:54 ` [PATCH 26/39] KVM: MMU: Add generic shadow walker Avi Kivity
2008-09-25 11:54 ` [PATCH 27/39] KVM: MMU: Convert direct maps to use the " Avi Kivity
2008-09-25 11:55 ` [PATCH 28/39] KVM: MMU: Convert the paging mode shadow walk to use the generic walker Avi Kivity
2008-09-25 11:55 ` [PATCH 29/39] KVM: Allocate guest memory as MAP_PRIVATE, not MAP_SHARED Avi Kivity
2008-09-25 11:55 ` [PATCH 30/39] KVM: Don't call get_user_pages(.force = 1) Avi Kivity
2008-09-25 11:55 ` [PATCH 31/39] KVM: x86 emulator: Add mov r, imm instructions (opcodes 0xb0-0xbf) Avi Kivity
2008-09-25 11:55 ` [PATCH 32/39] KVM: MMU: Account for npt/ept/realmode page faults Avi Kivity
2008-09-25 11:55 ` [PATCH 33/39] KVM: MMU: Add locking around kvm_mmu_slot_remove_write_access() Avi Kivity
2008-09-25 11:55 ` [PATCH 34/39] KVM: MMU: Flush tlbs after clearing write permission when accessing dirty log Avi Kivity
2008-09-25 11:55 ` [PATCH 35/39] KVM: MMU: Fix setting the accessed bit on non-speculative sptes Avi Kivity
2008-09-25 11:55 ` [PATCH 36/39] KVM: SVM: No need to unprotect memory during event injection when using npt Avi Kivity
2008-09-25 11:55 ` [PATCH 37/39] KVM: add MC5_MISC msr read support Avi Kivity
2008-09-25 11:55 ` [PATCH 38/39] KVM: s390: Make facility bits future-proof Avi Kivity
2008-09-25 11:55 ` [PATCH 39/39] KVM: s390: change help text of guest Kconfig Avi Kivity

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1222343711-12508-10-git-send-email-avi@redhat.com \
    --to=avi@redhat.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=m.gamal005@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox