All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] KVM: emulator: Fix io permission checking for 64bit guest.
@ 2011-03-07 12:55 Gleb Natapov
  2011-03-07 12:55 ` [PATCH 2/2] KVM: emulator: Fix permission checking in io permission bitmap Gleb Natapov
  2011-03-09  9:55 ` [PATCH 1/2] KVM: emulator: Fix io permission checking for 64bit guest Avi Kivity
  0 siblings, 2 replies; 4+ messages in thread
From: Gleb Natapov @ 2011-03-07 12:55 UTC (permalink / raw)
  To: kvm; +Cc: avi, mtosatti

Current implementation truncates upper 32bit of TR base address during IO
permission bitmap check. The patch fixes this.

Signed-off-by: Gleb Natapov <gleb@redhat.com>
---
 arch/x86/include/asm/kvm_emulate.h |    4 +-
 arch/x86/kvm/emulate.c             |   37 +++++++++++++++++++++--------------
 arch/x86/kvm/x86.c                 |   15 ++++++++++---
 3 files changed, 35 insertions(+), 21 deletions(-)

diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h
index 50ebc32..0f52135 100644
--- a/arch/x86/include/asm/kvm_emulate.h
+++ b/arch/x86/include/asm/kvm_emulate.h
@@ -142,9 +142,9 @@ struct x86_emulate_ops {
 	int (*pio_out_emulated)(int size, unsigned short port, const void *val,
 				unsigned int count, struct kvm_vcpu *vcpu);
 
-	bool (*get_cached_descriptor)(struct desc_struct *desc,
+	bool (*get_cached_descriptor)(struct desc_struct *desc, u32 *base3,
 				      int seg, struct kvm_vcpu *vcpu);
-	void (*set_cached_descriptor)(struct desc_struct *desc,
+	void (*set_cached_descriptor)(struct desc_struct *desc, u32 base3,
 				      int seg, struct kvm_vcpu *vcpu);
 	u16 (*get_segment_selector)(int seg, struct kvm_vcpu *vcpu);
 	void (*set_segment_selector)(u16 sel, int seg, struct kvm_vcpu *vcpu);
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index ad46239..b54b586 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -878,7 +878,8 @@ static void get_descriptor_table_ptr(struct x86_emulate_ctxt *ctxt,
 	if (selector & 1 << 2) {
 		struct desc_struct desc;
 		memset (dt, 0, sizeof *dt);
-		if (!ops->get_cached_descriptor(&desc, VCPU_SREG_LDTR, ctxt->vcpu))
+		if (!ops->get_cached_descriptor(&desc, NULL, VCPU_SREG_LDTR,
+						ctxt->vcpu))
 			return;
 
 		dt->size = desc_limit_scaled(&desc); /* what if limit > 65535? */
@@ -930,6 +931,7 @@ static int write_segment_descriptor(struct x86_emulate_ctxt *ctxt,
 	return ret;
 }
 
+/* Does not support long mode */
 static int load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
 				   struct x86_emulate_ops *ops,
 				   u16 selector, int seg)
@@ -1041,7 +1043,7 @@ static int load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
 	}
 load:
 	ops->set_segment_selector(selector, seg, ctxt->vcpu);
-	ops->set_cached_descriptor(&seg_desc, seg, ctxt->vcpu);
+	ops->set_cached_descriptor(&seg_desc, 0, seg, ctxt->vcpu);
 	return X86EMUL_CONTINUE;
 exception:
 	emulate_exception(ctxt, err_vec, err_code, true);
@@ -1561,7 +1563,7 @@ setup_syscalls_segments(struct x86_emulate_ctxt *ctxt,
 			struct desc_struct *ss)
 {
 	memset(cs, 0, sizeof(struct desc_struct));
-	ops->get_cached_descriptor(cs, VCPU_SREG_CS, ctxt->vcpu);
+	ops->get_cached_descriptor(cs, NULL, VCPU_SREG_CS, ctxt->vcpu);
 	memset(ss, 0, sizeof(struct desc_struct));
 
 	cs->l = 0;		/* will be adjusted later */
@@ -1608,9 +1610,9 @@ emulate_syscall(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
 		cs.d = 0;
 		cs.l = 1;
 	}
-	ops->set_cached_descriptor(&cs, VCPU_SREG_CS, ctxt->vcpu);
+	ops->set_cached_descriptor(&cs, 0, VCPU_SREG_CS, ctxt->vcpu);
 	ops->set_segment_selector(cs_sel, VCPU_SREG_CS, ctxt->vcpu);
-	ops->set_cached_descriptor(&ss, VCPU_SREG_SS, ctxt->vcpu);
+	ops->set_cached_descriptor(&ss, 0, VCPU_SREG_SS, ctxt->vcpu);
 	ops->set_segment_selector(ss_sel, VCPU_SREG_SS, ctxt->vcpu);
 
 	c->regs[VCPU_REGS_RCX] = c->eip;
@@ -1680,9 +1682,9 @@ emulate_sysenter(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
 		cs.l = 1;
 	}
 
-	ops->set_cached_descriptor(&cs, VCPU_SREG_CS, ctxt->vcpu);
+	ops->set_cached_descriptor(&cs, 0, VCPU_SREG_CS, ctxt->vcpu);
 	ops->set_segment_selector(cs_sel, VCPU_SREG_CS, ctxt->vcpu);
-	ops->set_cached_descriptor(&ss, VCPU_SREG_SS, ctxt->vcpu);
+	ops->set_cached_descriptor(&ss, 0, VCPU_SREG_SS, ctxt->vcpu);
 	ops->set_segment_selector(ss_sel, VCPU_SREG_SS, ctxt->vcpu);
 
 	ops->get_msr(ctxt->vcpu, MSR_IA32_SYSENTER_EIP, &msr_data);
@@ -1737,9 +1739,9 @@ emulate_sysexit(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
 	cs_sel |= SELECTOR_RPL_MASK;
 	ss_sel |= SELECTOR_RPL_MASK;
 
-	ops->set_cached_descriptor(&cs, VCPU_SREG_CS, ctxt->vcpu);
+	ops->set_cached_descriptor(&cs, 0, VCPU_SREG_CS, ctxt->vcpu);
 	ops->set_segment_selector(cs_sel, VCPU_SREG_CS, ctxt->vcpu);
-	ops->set_cached_descriptor(&ss, VCPU_SREG_SS, ctxt->vcpu);
+	ops->set_cached_descriptor(&ss, 0, VCPU_SREG_SS, ctxt->vcpu);
 	ops->set_segment_selector(ss_sel, VCPU_SREG_SS, ctxt->vcpu);
 
 	c->eip = c->regs[VCPU_REGS_RDX];
@@ -1765,24 +1767,29 @@ static bool emulator_io_port_access_allowed(struct x86_emulate_ctxt *ctxt,
 					    u16 port, u16 len)
 {
 	struct desc_struct tr_seg;
+	u32 base3;
 	int r;
 	u16 io_bitmap_ptr;
 	u8 perm, bit_idx = port & 0x7;
 	unsigned mask = (1 << len) - 1;
+	unsigned long base;
 
-	ops->get_cached_descriptor(&tr_seg, VCPU_SREG_TR, ctxt->vcpu);
+	ops->get_cached_descriptor(&tr_seg, &base3, VCPU_SREG_TR, ctxt->vcpu);
 	if (!tr_seg.p)
 		return false;
 	if (desc_limit_scaled(&tr_seg) < 103)
 		return false;
-	r = ops->read_std(get_desc_base(&tr_seg) + 102, &io_bitmap_ptr, 2,
-			  ctxt->vcpu, NULL);
+	base = get_desc_base(&tr_seg);
+#ifdef CONFIG_X86_64
+	base |= ((u64)base3) << 32;
+#endif
+	r = ops->read_std(base + 102, &io_bitmap_ptr, 2, ctxt->vcpu, NULL);
 	if (r != X86EMUL_CONTINUE)
 		return false;
 	if (io_bitmap_ptr + port/8 > desc_limit_scaled(&tr_seg))
 		return false;
-	r = ops->read_std(get_desc_base(&tr_seg) + io_bitmap_ptr + port/8,
-			  &perm, 1, ctxt->vcpu, NULL);
+	r = ops->read_std(base + io_bitmap_ptr + port/8, &perm, 1, ctxt->vcpu,
+			  NULL);
 	if (r != X86EMUL_CONTINUE)
 		return false;
 	if ((perm >> bit_idx) & mask)
@@ -2127,7 +2134,7 @@ static int emulator_do_task_switch(struct x86_emulate_ctxt *ctxt,
 	}
 
 	ops->set_cr(0,  ops->get_cr(0, ctxt->vcpu) | X86_CR0_TS, ctxt->vcpu);
-	ops->set_cached_descriptor(&next_tss_desc, VCPU_SREG_TR, ctxt->vcpu);
+	ops->set_cached_descriptor(&next_tss_desc, 0, VCPU_SREG_TR, ctxt->vcpu);
 	ops->set_segment_selector(tss_selector, VCPU_SREG_TR, ctxt->vcpu);
 
 	if (has_error_code) {
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 785ae0c..4002cae 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4162,8 +4162,8 @@ static unsigned long emulator_get_cached_segment_base(int seg,
 	return get_segment_base(vcpu, seg);
 }
 
-static bool emulator_get_cached_descriptor(struct desc_struct *desc, int seg,
-					   struct kvm_vcpu *vcpu)
+static bool emulator_get_cached_descriptor(struct desc_struct *desc, u32 *base3,
+					   int seg, struct kvm_vcpu *vcpu)
 {
 	struct kvm_segment var;
 
@@ -4176,6 +4176,10 @@ static bool emulator_get_cached_descriptor(struct desc_struct *desc, int seg,
 		var.limit >>= 12;
 	set_desc_limit(desc, var.limit);
 	set_desc_base(desc, (unsigned long)var.base);
+#ifdef CONFIG_X86_64
+	if (base3)
+		*base3 = var.base >> 32;
+#endif
 	desc->type = var.type;
 	desc->s = var.s;
 	desc->dpl = var.dpl;
@@ -4188,8 +4192,8 @@ static bool emulator_get_cached_descriptor(struct desc_struct *desc, int seg,
 	return true;
 }
 
-static void emulator_set_cached_descriptor(struct desc_struct *desc, int seg,
-					   struct kvm_vcpu *vcpu)
+static void emulator_set_cached_descriptor(struct desc_struct *desc, u32 base3,
+					   int seg, struct kvm_vcpu *vcpu)
 {
 	struct kvm_segment var;
 
@@ -4197,6 +4201,9 @@ static void emulator_set_cached_descriptor(struct desc_struct *desc, int seg,
 	kvm_get_segment(vcpu, &var, seg);
 
 	var.base = get_desc_base(desc);
+#ifdef CONFIG_X86_64
+	var.base |= ((u64)base3) << 32;
+#endif
 	var.limit = get_desc_limit(desc);
 	if (desc->g)
 		var.limit = (var.limit << 12) | 0xfff;
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/2] KVM: emulator: Fix permission checking in io permission bitmap.
  2011-03-07 12:55 [PATCH 1/2] KVM: emulator: Fix io permission checking for 64bit guest Gleb Natapov
@ 2011-03-07 12:55 ` Gleb Natapov
  2011-03-09  9:59   ` Avi Kivity
  2011-03-09  9:55 ` [PATCH 1/2] KVM: emulator: Fix io permission checking for 64bit guest Avi Kivity
  1 sibling, 1 reply; 4+ messages in thread
From: Gleb Natapov @ 2011-03-07 12:55 UTC (permalink / raw)
  To: kvm; +Cc: avi, mtosatti

Currently if io port + len crosses 8bit boundary in io permission bitmap the
check may allow IO that otherwise should not be allowed. The patch fixes that.

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

diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index b54b586..14c5ad5 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -1769,8 +1769,7 @@ static bool emulator_io_port_access_allowed(struct x86_emulate_ctxt *ctxt,
 	struct desc_struct tr_seg;
 	u32 base3;
 	int r;
-	u16 io_bitmap_ptr;
-	u8 perm, bit_idx = port & 0x7;
+	u16 io_bitmap_ptr, perm, bit_idx = port & 0x7;
 	unsigned mask = (1 << len) - 1;
 	unsigned long base;
 
@@ -1788,7 +1787,7 @@ static bool emulator_io_port_access_allowed(struct x86_emulate_ctxt *ctxt,
 		return false;
 	if (io_bitmap_ptr + port/8 > desc_limit_scaled(&tr_seg))
 		return false;
-	r = ops->read_std(base + io_bitmap_ptr + port/8, &perm, 1, ctxt->vcpu,
+	r = ops->read_std(base + io_bitmap_ptr + port/8, &perm, 2, ctxt->vcpu,
 			  NULL);
 	if (r != X86EMUL_CONTINUE)
 		return false;
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH 1/2] KVM: emulator: Fix io permission checking for 64bit guest.
  2011-03-07 12:55 [PATCH 1/2] KVM: emulator: Fix io permission checking for 64bit guest Gleb Natapov
  2011-03-07 12:55 ` [PATCH 2/2] KVM: emulator: Fix permission checking in io permission bitmap Gleb Natapov
@ 2011-03-09  9:55 ` Avi Kivity
  1 sibling, 0 replies; 4+ messages in thread
From: Avi Kivity @ 2011-03-09  9:55 UTC (permalink / raw)
  To: Gleb Natapov; +Cc: kvm, mtosatti

On 03/07/2011 02:55 PM, Gleb Natapov wrote:
> Current implementation truncates upper 32bit of TR base address during IO
> permission bitmap check. The patch fixes this.

Applied, thanks.

-- 
error compiling committee.c: too many arguments to function


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 2/2] KVM: emulator: Fix permission checking in io permission bitmap.
  2011-03-07 12:55 ` [PATCH 2/2] KVM: emulator: Fix permission checking in io permission bitmap Gleb Natapov
@ 2011-03-09  9:59   ` Avi Kivity
  0 siblings, 0 replies; 4+ messages in thread
From: Avi Kivity @ 2011-03-09  9:59 UTC (permalink / raw)
  To: Gleb Natapov; +Cc: kvm, mtosatti

On 03/07/2011 02:55 PM, Gleb Natapov wrote:
> Currently if io port + len crosses 8bit boundary in io permission bitmap the
> check may allow IO that otherwise should not be allowed. The patch fixes that.

Applied, thanks.

-- 
error compiling committee.c: too many arguments to function


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2011-03-09  9:59 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-03-07 12:55 [PATCH 1/2] KVM: emulator: Fix io permission checking for 64bit guest Gleb Natapov
2011-03-07 12:55 ` [PATCH 2/2] KVM: emulator: Fix permission checking in io permission bitmap Gleb Natapov
2011-03-09  9:59   ` Avi Kivity
2011-03-09  9:55 ` [PATCH 1/2] KVM: emulator: Fix io permission checking for 64bit guest Avi Kivity

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.