Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
Pull KVM fixes from Radim Krčmář: "Four fixes for bugs found by syzkaller on x86, all for stable" * tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm: KVM: x86: check for pic and ioapic presence before use KVM: x86: fix out-of-bounds accesses of rtc_eoi map KVM: x86: drop error recovery in em_jmp_far and em_ret_far KVM: x86: fix out-of-bounds access in lapic
This commit is contained in:
@@ -2105,16 +2105,10 @@ static int em_iret(struct x86_emulate_ctxt *ctxt)
|
|||||||
static int em_jmp_far(struct x86_emulate_ctxt *ctxt)
|
static int em_jmp_far(struct x86_emulate_ctxt *ctxt)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
unsigned short sel, old_sel;
|
unsigned short sel;
|
||||||
struct desc_struct old_desc, new_desc;
|
struct desc_struct new_desc;
|
||||||
const struct x86_emulate_ops *ops = ctxt->ops;
|
|
||||||
u8 cpl = ctxt->ops->cpl(ctxt);
|
u8 cpl = ctxt->ops->cpl(ctxt);
|
||||||
|
|
||||||
/* Assignment of RIP may only fail in 64-bit mode */
|
|
||||||
if (ctxt->mode == X86EMUL_MODE_PROT64)
|
|
||||||
ops->get_segment(ctxt, &old_sel, &old_desc, NULL,
|
|
||||||
VCPU_SREG_CS);
|
|
||||||
|
|
||||||
memcpy(&sel, ctxt->src.valptr + ctxt->op_bytes, 2);
|
memcpy(&sel, ctxt->src.valptr + ctxt->op_bytes, 2);
|
||||||
|
|
||||||
rc = __load_segment_descriptor(ctxt, sel, VCPU_SREG_CS, cpl,
|
rc = __load_segment_descriptor(ctxt, sel, VCPU_SREG_CS, cpl,
|
||||||
@@ -2124,12 +2118,10 @@ static int em_jmp_far(struct x86_emulate_ctxt *ctxt)
|
|||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
rc = assign_eip_far(ctxt, ctxt->src.val, &new_desc);
|
rc = assign_eip_far(ctxt, ctxt->src.val, &new_desc);
|
||||||
if (rc != X86EMUL_CONTINUE) {
|
/* Error handling is not implemented. */
|
||||||
WARN_ON(ctxt->mode != X86EMUL_MODE_PROT64);
|
if (rc != X86EMUL_CONTINUE)
|
||||||
/* assigning eip failed; restore the old cs */
|
return X86EMUL_UNHANDLEABLE;
|
||||||
ops->set_segment(ctxt, old_sel, &old_desc, 0, VCPU_SREG_CS);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2189,14 +2181,8 @@ static int em_ret_far(struct x86_emulate_ctxt *ctxt)
|
|||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
unsigned long eip, cs;
|
unsigned long eip, cs;
|
||||||
u16 old_cs;
|
|
||||||
int cpl = ctxt->ops->cpl(ctxt);
|
int cpl = ctxt->ops->cpl(ctxt);
|
||||||
struct desc_struct old_desc, new_desc;
|
struct desc_struct new_desc;
|
||||||
const struct x86_emulate_ops *ops = ctxt->ops;
|
|
||||||
|
|
||||||
if (ctxt->mode == X86EMUL_MODE_PROT64)
|
|
||||||
ops->get_segment(ctxt, &old_cs, &old_desc, NULL,
|
|
||||||
VCPU_SREG_CS);
|
|
||||||
|
|
||||||
rc = emulate_pop(ctxt, &eip, ctxt->op_bytes);
|
rc = emulate_pop(ctxt, &eip, ctxt->op_bytes);
|
||||||
if (rc != X86EMUL_CONTINUE)
|
if (rc != X86EMUL_CONTINUE)
|
||||||
@@ -2213,10 +2199,10 @@ static int em_ret_far(struct x86_emulate_ctxt *ctxt)
|
|||||||
if (rc != X86EMUL_CONTINUE)
|
if (rc != X86EMUL_CONTINUE)
|
||||||
return rc;
|
return rc;
|
||||||
rc = assign_eip_far(ctxt, eip, &new_desc);
|
rc = assign_eip_far(ctxt, eip, &new_desc);
|
||||||
if (rc != X86EMUL_CONTINUE) {
|
/* Error handling is not implemented. */
|
||||||
WARN_ON(ctxt->mode != X86EMUL_MODE_PROT64);
|
if (rc != X86EMUL_CONTINUE)
|
||||||
ops->set_segment(ctxt, old_cs, &old_desc, 0, VCPU_SREG_CS);
|
return X86EMUL_UNHANDLEABLE;
|
||||||
}
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -94,7 +94,7 @@ static unsigned long ioapic_read_indirect(struct kvm_ioapic *ioapic,
|
|||||||
static void rtc_irq_eoi_tracking_reset(struct kvm_ioapic *ioapic)
|
static void rtc_irq_eoi_tracking_reset(struct kvm_ioapic *ioapic)
|
||||||
{
|
{
|
||||||
ioapic->rtc_status.pending_eoi = 0;
|
ioapic->rtc_status.pending_eoi = 0;
|
||||||
bitmap_zero(ioapic->rtc_status.dest_map.map, KVM_MAX_VCPUS);
|
bitmap_zero(ioapic->rtc_status.dest_map.map, KVM_MAX_VCPU_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void kvm_rtc_eoi_tracking_restore_all(struct kvm_ioapic *ioapic);
|
static void kvm_rtc_eoi_tracking_restore_all(struct kvm_ioapic *ioapic);
|
||||||
|
@@ -42,13 +42,13 @@ struct kvm_vcpu;
|
|||||||
|
|
||||||
struct dest_map {
|
struct dest_map {
|
||||||
/* vcpu bitmap where IRQ has been sent */
|
/* vcpu bitmap where IRQ has been sent */
|
||||||
DECLARE_BITMAP(map, KVM_MAX_VCPUS);
|
DECLARE_BITMAP(map, KVM_MAX_VCPU_ID);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Vector sent to a given vcpu, only valid when
|
* Vector sent to a given vcpu, only valid when
|
||||||
* the vcpu's bit in map is set
|
* the vcpu's bit in map is set
|
||||||
*/
|
*/
|
||||||
u8 vectors[KVM_MAX_VCPUS];
|
u8 vectors[KVM_MAX_VCPU_ID];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -41,6 +41,15 @@ static int kvm_set_pic_irq(struct kvm_kernel_irq_routing_entry *e,
|
|||||||
bool line_status)
|
bool line_status)
|
||||||
{
|
{
|
||||||
struct kvm_pic *pic = pic_irqchip(kvm);
|
struct kvm_pic *pic = pic_irqchip(kvm);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX: rejecting pic routes when pic isn't in use would be better,
|
||||||
|
* but the default routing table is installed while kvm->arch.vpic is
|
||||||
|
* NULL and KVM_CREATE_IRQCHIP can race with KVM_IRQ_LINE.
|
||||||
|
*/
|
||||||
|
if (!pic)
|
||||||
|
return -1;
|
||||||
|
|
||||||
return kvm_pic_set_irq(pic, e->irqchip.pin, irq_source_id, level);
|
return kvm_pic_set_irq(pic, e->irqchip.pin, irq_source_id, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,6 +58,10 @@ static int kvm_set_ioapic_irq(struct kvm_kernel_irq_routing_entry *e,
|
|||||||
bool line_status)
|
bool line_status)
|
||||||
{
|
{
|
||||||
struct kvm_ioapic *ioapic = kvm->arch.vioapic;
|
struct kvm_ioapic *ioapic = kvm->arch.vioapic;
|
||||||
|
|
||||||
|
if (!ioapic)
|
||||||
|
return -1;
|
||||||
|
|
||||||
return kvm_ioapic_set_irq(ioapic, e->irqchip.pin, irq_source_id, level,
|
return kvm_ioapic_set_irq(ioapic, e->irqchip.pin, irq_source_id, level,
|
||||||
line_status);
|
line_status);
|
||||||
}
|
}
|
||||||
|
@@ -138,7 +138,7 @@ static inline bool kvm_apic_map_get_logical_dest(struct kvm_apic_map *map,
|
|||||||
*mask = dest_id & 0xff;
|
*mask = dest_id & 0xff;
|
||||||
return true;
|
return true;
|
||||||
case KVM_APIC_MODE_XAPIC_CLUSTER:
|
case KVM_APIC_MODE_XAPIC_CLUSTER:
|
||||||
*cluster = map->xapic_cluster_map[dest_id >> 4];
|
*cluster = map->xapic_cluster_map[(dest_id >> 4) & 0xf];
|
||||||
*mask = dest_id & 0xf;
|
*mask = dest_id & 0xf;
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
|
Reference in New Issue
Block a user