KVM: Fix segment descriptor loading
Add proper error and permission checking. This patch also change task switching code to load segment selectors before segment descriptors, like SDM requires, otherwise permission checking during segment descriptor loading will be incorrect. Cc: stable@kernel.org (2.6.33, 2.6.32) Signed-off-by: Gleb Natapov <gleb@redhat.com> Signed-off-by: Avi Kivity <avi@redhat.com>
This commit is contained in:

committed by
Marcelo Tosatti

parent
6f550484a1
commit
c697518a86
@@ -1309,7 +1309,7 @@ static int emulate_pop_sreg(struct x86_emulate_ctxt *ctxt,
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
|
||||
rc = kvm_load_segment_descriptor(ctxt->vcpu, (u16)selector, 1, seg);
|
||||
rc = kvm_load_segment_descriptor(ctxt->vcpu, (u16)selector, seg);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -1491,7 +1491,7 @@ static int emulate_ret_far(struct x86_emulate_ctxt *ctxt,
|
||||
rc = emulate_pop(ctxt, ops, &cs, c->op_bytes);
|
||||
if (rc)
|
||||
return rc;
|
||||
rc = kvm_load_segment_descriptor(ctxt->vcpu, (u16)cs, 1, VCPU_SREG_CS);
|
||||
rc = kvm_load_segment_descriptor(ctxt->vcpu, (u16)cs, VCPU_SREG_CS);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -2122,12 +2122,11 @@ special_insn:
|
||||
break;
|
||||
case 0x8e: { /* mov seg, r/m16 */
|
||||
uint16_t sel;
|
||||
int type_bits;
|
||||
int err;
|
||||
|
||||
sel = c->src.val;
|
||||
|
||||
if (c->modrm_reg == VCPU_SREG_CS) {
|
||||
if (c->modrm_reg == VCPU_SREG_CS ||
|
||||
c->modrm_reg > VCPU_SREG_GS) {
|
||||
kvm_queue_exception(ctxt->vcpu, UD_VECTOR);
|
||||
goto done;
|
||||
}
|
||||
@@ -2135,18 +2134,7 @@ special_insn:
|
||||
if (c->modrm_reg == VCPU_SREG_SS)
|
||||
toggle_interruptibility(ctxt, X86_SHADOW_INT_MOV_SS);
|
||||
|
||||
if (c->modrm_reg <= 5) {
|
||||
type_bits = (c->modrm_reg == 1) ? 9 : 1;
|
||||
err = kvm_load_segment_descriptor(ctxt->vcpu, sel,
|
||||
type_bits, c->modrm_reg);
|
||||
} else {
|
||||
printk(KERN_INFO "Invalid segreg in modrm byte 0x%02x\n",
|
||||
c->modrm);
|
||||
goto cannot_emulate;
|
||||
}
|
||||
|
||||
if (err < 0)
|
||||
goto cannot_emulate;
|
||||
rc = kvm_load_segment_descriptor(ctxt->vcpu, sel, c->modrm_reg);
|
||||
|
||||
c->dst.type = OP_NONE; /* Disable writeback. */
|
||||
break;
|
||||
@@ -2320,11 +2308,9 @@ special_insn:
|
||||
case 0xe9: /* jmp rel */
|
||||
goto jmp;
|
||||
case 0xea: /* jmp far */
|
||||
if (kvm_load_segment_descriptor(ctxt->vcpu, c->src2.val, 9,
|
||||
VCPU_SREG_CS) < 0) {
|
||||
DPRINTF("jmp far: Failed to load CS descriptor\n");
|
||||
goto cannot_emulate;
|
||||
}
|
||||
if (kvm_load_segment_descriptor(ctxt->vcpu, c->src2.val,
|
||||
VCPU_SREG_CS))
|
||||
goto done;
|
||||
|
||||
c->eip = c->src.val;
|
||||
break;
|
||||
|
Reference in New Issue
Block a user