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
next prev 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