diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-11-26 15:18:59 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-11-26 15:18:59 -0500 |
commit | fc13ca191ee2ae5f379e2933cdff523c3b4fffc9 (patch) | |
tree | b62beebc6b8160c57c241c6288cdfe35f9c5e122 | |
parent | 39c1573748166b348117d6bf161ceffce90e734f (diff) | |
parent | df492896e6dfb44fd1154f5402428d8e52705081 (diff) |
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
-rw-r--r-- | arch/x86/kvm/emulate.c | 36 | ||||
-rw-r--r-- | arch/x86/kvm/ioapic.c | 2 | ||||
-rw-r--r-- | arch/x86/kvm/ioapic.h | 4 | ||||
-rw-r--r-- | arch/x86/kvm/irq_comm.c | 13 | ||||
-rw-r--r-- | arch/x86/kvm/lapic.c | 2 |
5 files changed, 28 insertions, 29 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index cbd7b92585bb..a3ce9d260d68 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c | |||
@@ -2105,16 +2105,10 @@ static int em_iret(struct x86_emulate_ctxt *ctxt) | |||
2105 | static int em_jmp_far(struct x86_emulate_ctxt *ctxt) | 2105 | static int em_jmp_far(struct x86_emulate_ctxt *ctxt) |
2106 | { | 2106 | { |
2107 | int rc; | 2107 | int rc; |
2108 | unsigned short sel, old_sel; | 2108 | unsigned short sel; |
2109 | struct desc_struct old_desc, new_desc; | 2109 | struct desc_struct new_desc; |
2110 | const struct x86_emulate_ops *ops = ctxt->ops; | ||
2111 | u8 cpl = ctxt->ops->cpl(ctxt); | 2110 | u8 cpl = ctxt->ops->cpl(ctxt); |
2112 | 2111 | ||
2113 | /* Assignment of RIP may only fail in 64-bit mode */ | ||
2114 | if (ctxt->mode == X86EMUL_MODE_PROT64) | ||
2115 | ops->get_segment(ctxt, &old_sel, &old_desc, NULL, | ||
2116 | VCPU_SREG_CS); | ||
2117 | |||
2118 | memcpy(&sel, ctxt->src.valptr + ctxt->op_bytes, 2); | 2112 | memcpy(&sel, ctxt->src.valptr + ctxt->op_bytes, 2); |
2119 | 2113 | ||
2120 | rc = __load_segment_descriptor(ctxt, sel, VCPU_SREG_CS, cpl, | 2114 | rc = __load_segment_descriptor(ctxt, sel, VCPU_SREG_CS, cpl, |
@@ -2124,12 +2118,10 @@ static int em_jmp_far(struct x86_emulate_ctxt *ctxt) | |||
2124 | return rc; | 2118 | return rc; |
2125 | 2119 | ||
2126 | rc = assign_eip_far(ctxt, ctxt->src.val, &new_desc); | 2120 | rc = assign_eip_far(ctxt, ctxt->src.val, &new_desc); |
2127 | if (rc != X86EMUL_CONTINUE) { | 2121 | /* Error handling is not implemented. */ |
2128 | WARN_ON(ctxt->mode != X86EMUL_MODE_PROT64); | 2122 | if (rc != X86EMUL_CONTINUE) |
2129 | /* assigning eip failed; restore the old cs */ | 2123 | return X86EMUL_UNHANDLEABLE; |
2130 | ops->set_segment(ctxt, old_sel, &old_desc, 0, VCPU_SREG_CS); | 2124 | |
2131 | return rc; | ||
2132 | } | ||
2133 | return rc; | 2125 | return rc; |
2134 | } | 2126 | } |
2135 | 2127 | ||
@@ -2189,14 +2181,8 @@ static int em_ret_far(struct x86_emulate_ctxt *ctxt) | |||
2189 | { | 2181 | { |
2190 | int rc; | 2182 | int rc; |
2191 | unsigned long eip, cs; | 2183 | unsigned long eip, cs; |
2192 | u16 old_cs; | ||
2193 | int cpl = ctxt->ops->cpl(ctxt); | 2184 | int cpl = ctxt->ops->cpl(ctxt); |
2194 | struct desc_struct old_desc, new_desc; | 2185 | struct desc_struct new_desc; |
2195 | const struct x86_emulate_ops *ops = ctxt->ops; | ||
2196 | |||
2197 | if (ctxt->mode == X86EMUL_MODE_PROT64) | ||
2198 | ops->get_segment(ctxt, &old_cs, &old_desc, NULL, | ||
2199 | VCPU_SREG_CS); | ||
2200 | 2186 | ||
2201 | rc = emulate_pop(ctxt, &eip, ctxt->op_bytes); | 2187 | rc = emulate_pop(ctxt, &eip, ctxt->op_bytes); |
2202 | if (rc != X86EMUL_CONTINUE) | 2188 | if (rc != X86EMUL_CONTINUE) |
@@ -2213,10 +2199,10 @@ static int em_ret_far(struct x86_emulate_ctxt *ctxt) | |||
2213 | if (rc != X86EMUL_CONTINUE) | 2199 | if (rc != X86EMUL_CONTINUE) |
2214 | return rc; | 2200 | return rc; |
2215 | rc = assign_eip_far(ctxt, eip, &new_desc); | 2201 | rc = assign_eip_far(ctxt, eip, &new_desc); |
2216 | if (rc != X86EMUL_CONTINUE) { | 2202 | /* Error handling is not implemented. */ |
2217 | WARN_ON(ctxt->mode != X86EMUL_MODE_PROT64); | 2203 | if (rc != X86EMUL_CONTINUE) |
2218 | ops->set_segment(ctxt, old_cs, &old_desc, 0, VCPU_SREG_CS); | 2204 | return X86EMUL_UNHANDLEABLE; |
2219 | } | 2205 | |
2220 | return rc; | 2206 | return rc; |
2221 | } | 2207 | } |
2222 | 2208 | ||
diff --git a/arch/x86/kvm/ioapic.c b/arch/x86/kvm/ioapic.c index 1a22de70f7f7..6e219e5c07d2 100644 --- a/arch/x86/kvm/ioapic.c +++ b/arch/x86/kvm/ioapic.c | |||
@@ -94,7 +94,7 @@ static unsigned long ioapic_read_indirect(struct kvm_ioapic *ioapic, | |||
94 | static void rtc_irq_eoi_tracking_reset(struct kvm_ioapic *ioapic) | 94 | static void rtc_irq_eoi_tracking_reset(struct kvm_ioapic *ioapic) |
95 | { | 95 | { |
96 | ioapic->rtc_status.pending_eoi = 0; | 96 | ioapic->rtc_status.pending_eoi = 0; |
97 | bitmap_zero(ioapic->rtc_status.dest_map.map, KVM_MAX_VCPUS); | 97 | bitmap_zero(ioapic->rtc_status.dest_map.map, KVM_MAX_VCPU_ID); |
98 | } | 98 | } |
99 | 99 | ||
100 | static void kvm_rtc_eoi_tracking_restore_all(struct kvm_ioapic *ioapic); | 100 | static void kvm_rtc_eoi_tracking_restore_all(struct kvm_ioapic *ioapic); |
diff --git a/arch/x86/kvm/ioapic.h b/arch/x86/kvm/ioapic.h index 7d2692a49657..1cc6e54436db 100644 --- a/arch/x86/kvm/ioapic.h +++ b/arch/x86/kvm/ioapic.h | |||
@@ -42,13 +42,13 @@ struct kvm_vcpu; | |||
42 | 42 | ||
43 | struct dest_map { | 43 | struct dest_map { |
44 | /* vcpu bitmap where IRQ has been sent */ | 44 | /* vcpu bitmap where IRQ has been sent */ |
45 | DECLARE_BITMAP(map, KVM_MAX_VCPUS); | 45 | DECLARE_BITMAP(map, KVM_MAX_VCPU_ID); |
46 | 46 | ||
47 | /* | 47 | /* |
48 | * Vector sent to a given vcpu, only valid when | 48 | * Vector sent to a given vcpu, only valid when |
49 | * the vcpu's bit in map is set | 49 | * the vcpu's bit in map is set |
50 | */ | 50 | */ |
51 | u8 vectors[KVM_MAX_VCPUS]; | 51 | u8 vectors[KVM_MAX_VCPU_ID]; |
52 | }; | 52 | }; |
53 | 53 | ||
54 | 54 | ||
diff --git a/arch/x86/kvm/irq_comm.c b/arch/x86/kvm/irq_comm.c index 4da03030d5a7..6c0191615f23 100644 --- a/arch/x86/kvm/irq_comm.c +++ b/arch/x86/kvm/irq_comm.c | |||
@@ -41,6 +41,15 @@ static int kvm_set_pic_irq(struct kvm_kernel_irq_routing_entry *e, | |||
41 | bool line_status) | 41 | bool line_status) |
42 | { | 42 | { |
43 | struct kvm_pic *pic = pic_irqchip(kvm); | 43 | struct kvm_pic *pic = pic_irqchip(kvm); |
44 | |||
45 | /* | ||
46 | * XXX: rejecting pic routes when pic isn't in use would be better, | ||
47 | * but the default routing table is installed while kvm->arch.vpic is | ||
48 | * NULL and KVM_CREATE_IRQCHIP can race with KVM_IRQ_LINE. | ||
49 | */ | ||
50 | if (!pic) | ||
51 | return -1; | ||
52 | |||
44 | return kvm_pic_set_irq(pic, e->irqchip.pin, irq_source_id, level); | 53 | return kvm_pic_set_irq(pic, e->irqchip.pin, irq_source_id, level); |
45 | } | 54 | } |
46 | 55 | ||
@@ -49,6 +58,10 @@ static int kvm_set_ioapic_irq(struct kvm_kernel_irq_routing_entry *e, | |||
49 | bool line_status) | 58 | bool line_status) |
50 | { | 59 | { |
51 | struct kvm_ioapic *ioapic = kvm->arch.vioapic; | 60 | struct kvm_ioapic *ioapic = kvm->arch.vioapic; |
61 | |||
62 | if (!ioapic) | ||
63 | return -1; | ||
64 | |||
52 | return kvm_ioapic_set_irq(ioapic, e->irqchip.pin, irq_source_id, level, | 65 | return kvm_ioapic_set_irq(ioapic, e->irqchip.pin, irq_source_id, level, |
53 | line_status); | 66 | line_status); |
54 | } | 67 | } |
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 23b99f305382..6f69340f9fa3 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c | |||
@@ -138,7 +138,7 @@ static inline bool kvm_apic_map_get_logical_dest(struct kvm_apic_map *map, | |||
138 | *mask = dest_id & 0xff; | 138 | *mask = dest_id & 0xff; |
139 | return true; | 139 | return true; |
140 | case KVM_APIC_MODE_XAPIC_CLUSTER: | 140 | case KVM_APIC_MODE_XAPIC_CLUSTER: |
141 | *cluster = map->xapic_cluster_map[dest_id >> 4]; | 141 | *cluster = map->xapic_cluster_map[(dest_id >> 4) & 0xf]; |
142 | *mask = dest_id & 0xf; | 142 | *mask = dest_id & 0xf; |
143 | return true; | 143 | return true; |
144 | default: | 144 | default: |