[x86] KVM: Fix far-jump to non-canonical check

Fixes bug in the original fix for CVE-2014-3647.
Also fix ordering of the previous patches.

svn path=/dists/sid/linux/; revision=22030
This commit is contained in:
Ben Hutchings 2014-11-04 00:19:39 +00:00
parent 78038d0e59
commit 28bdc83f8a
5 changed files with 84 additions and 24 deletions

1
debian/changelog vendored
View File

@ -142,6 +142,7 @@ linux (3.16.7-1) UNRELEASED; urgency=medium
* [x86] KVM: Emulator fixes for eip canonical checks on near branches
(CVE-2014-3647)
* [x86] KVM: Handle errors when RIP is set during far jumps (CVE-2014-3647)
* [x86] KVM: Fix far-jump to non-canonical check
* net: sctp: fix skb_over_panic when receiving malformed ASCONF chunks
(CVE-2014-3673)
* net: sctp: fix panic on duplicate ASCONF chunks (CVE-2014-3687)

View File

@ -62,7 +62,7 @@ Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
}
static u16 get_segment_selector(struct x86_emulate_ctxt *ctxt, unsigned seg)
@@ -2004,13 +2014,15 @@ static int em_grp45(struct x86_emulate_c
@@ -1986,13 +1996,15 @@ static int em_grp45(struct x86_emulate_c
case 2: /* call near abs */ {
long int old_eip;
old_eip = ctxt->_eip;
@ -80,7 +80,7 @@ Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
break;
case 5: /* jmp far */
rc = em_jmp_far(ctxt);
@@ -2042,10 +2054,14 @@ static int em_cmpxchg8b(struct x86_emula
@@ -2024,10 +2036,14 @@ static int em_cmpxchg8b(struct x86_emula
static int em_ret(struct x86_emulate_ctxt *ctxt)
{
@ -99,7 +99,7 @@ Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
}
static int em_ret_far(struct x86_emulate_ctxt *ctxt)
@@ -2336,7 +2352,7 @@ static int em_sysexit(struct x86_emulate
@@ -2305,7 +2321,7 @@ static int em_sysexit(struct x86_emulate
{
const struct x86_emulate_ops *ops = ctxt->ops;
struct desc_struct cs, ss;
@ -108,7 +108,7 @@ Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
int usermode;
u16 cs_sel = 0, ss_sel = 0;
@@ -2352,6 +2368,9 @@ static int em_sysexit(struct x86_emulate
@@ -2321,6 +2337,9 @@ static int em_sysexit(struct x86_emulate
else
usermode = X86EMUL_MODE_PROT32;
@ -118,7 +118,7 @@ Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
cs.dpl = 3;
ss.dpl = 3;
ops->get_msr(ctxt, MSR_IA32_SYSENTER_CS, &msr_data);
@@ -2369,6 +2388,9 @@ static int em_sysexit(struct x86_emulate
@@ -2338,6 +2357,9 @@ static int em_sysexit(struct x86_emulate
ss_sel = cs_sel + 8;
cs.d = 0;
cs.l = 1;
@ -128,7 +128,7 @@ Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
break;
}
cs_sel |= SELECTOR_RPL_MASK;
@@ -2377,8 +2399,8 @@ static int em_sysexit(struct x86_emulate
@@ -2346,8 +2368,8 @@ static int em_sysexit(struct x86_emulate
ops->set_segment(ctxt, cs_sel, &cs, 0, VCPU_SREG_CS);
ops->set_segment(ctxt, ss_sel, &ss, 0, VCPU_SREG_SS);
@ -139,7 +139,7 @@ Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
return X86EMUL_CONTINUE;
}
@@ -2931,10 +2953,13 @@ static int em_aad(struct x86_emulate_ctx
@@ -2888,10 +2910,13 @@ static int em_aad(struct x86_emulate_ctx
static int em_call(struct x86_emulate_ctxt *ctxt)
{
@ -154,7 +154,7 @@ Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
return em_push(ctxt);
}
@@ -2981,11 +3006,12 @@ fail:
@@ -2923,11 +2948,12 @@ static int em_call_far(struct x86_emulat
static int em_ret_near_imm(struct x86_emulate_ctxt *ctxt)
{
int rc;
@ -171,7 +171,7 @@ Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
if (rc != X86EMUL_CONTINUE)
return rc;
rsp_increment(ctxt, ctxt->src.val);
@@ -3315,20 +3341,24 @@ static int em_lmsw(struct x86_emulate_ct
@@ -3257,20 +3283,24 @@ static int em_lmsw(struct x86_emulate_ct
static int em_loop(struct x86_emulate_ctxt *ctxt)
{
@ -200,7 +200,7 @@ Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
}
static int em_in(struct x86_emulate_ctxt *ctxt)
@@ -4729,7 +4759,7 @@ special_insn:
@@ -4671,7 +4701,7 @@ special_insn:
break;
case 0x70 ... 0x7f: /* jcc (short) */
if (test_cc(ctxt->b, ctxt->eflags))
@ -209,7 +209,7 @@ Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
break;
case 0x8d: /* lea r16/r32, m */
ctxt->dst.val = ctxt->src.addr.mem.ea;
@@ -4758,7 +4788,7 @@ special_insn:
@@ -4700,7 +4730,7 @@ special_insn:
break;
case 0xe9: /* jmp rel */
case 0xeb: /* jmp rel short */
@ -218,7 +218,7 @@ Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
ctxt->dst.type = OP_NONE; /* Disable writeback. */
break;
case 0xf4: /* hlt */
@@ -4878,7 +4908,7 @@ twobyte_insn:
@@ -4820,7 +4850,7 @@ twobyte_insn:
break;
case 0x80 ... 0x8f: /* jnz rel, etc*/
if (test_cc(ctxt->b, ctxt->eflags))

View File

@ -22,7 +22,7 @@ Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -1429,7 +1429,9 @@ static int write_segment_descriptor(stru
@@ -1439,7 +1439,9 @@ static int write_segment_descriptor(stru
/* Does not support long mode */
static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
@ -33,7 +33,7 @@ Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
{
struct desc_struct seg_desc, old_desc;
u8 dpl, rpl;
@@ -1558,6 +1560,8 @@ static int __load_segment_descriptor(str
@@ -1568,6 +1570,8 @@ static int __load_segment_descriptor(str
}
load:
ctxt->ops->set_segment(ctxt, selector, &seg_desc, 0, seg);
@ -42,7 +42,7 @@ Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
return X86EMUL_CONTINUE;
exception:
emulate_exception(ctxt, err_vec, err_code, true);
@@ -1568,7 +1572,7 @@ static int load_segment_descriptor(struc
@@ -1578,7 +1582,7 @@ static int load_segment_descriptor(struc
u16 selector, int seg)
{
u8 cpl = ctxt->ops->cpl(ctxt);
@ -51,7 +51,7 @@ Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
}
static void write_register_operand(struct operand *op)
@@ -1965,17 +1969,31 @@ static int em_iret(struct x86_emulate_ct
@@ -1975,17 +1979,31 @@ static int em_iret(struct x86_emulate_ct
static int em_jmp_far(struct x86_emulate_ctxt *ctxt)
{
int rc;
@ -88,7 +88,7 @@ Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
}
static int em_grp45(struct x86_emulate_ctxt *ctxt)
@@ -2033,21 +2051,34 @@ static int em_ret(struct x86_emulate_ctx
@@ -2049,21 +2067,34 @@ static int em_ret(struct x86_emulate_ctx
static int em_ret_far(struct x86_emulate_ctxt *ctxt)
{
int rc;
@ -98,12 +98,12 @@ Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
int cpl = ctxt->ops->cpl(ctxt);
+ struct desc_struct old_desc, new_desc;
+ const struct x86_emulate_ops *ops = ctxt->ops;
- rc = emulate_pop(ctxt, &ctxt->_eip, ctxt->op_bytes);
+
+ if (ctxt->mode == X86EMUL_MODE_PROT64)
+ ops->get_segment(ctxt, &old_cs, &old_desc, NULL,
+ VCPU_SREG_CS);
+
- rc = emulate_pop(ctxt, &ctxt->_eip, ctxt->op_bytes);
+ rc = emulate_pop(ctxt, &eip, ctxt->op_bytes);
if (rc != X86EMUL_CONTINUE)
return rc;
@ -128,7 +128,7 @@ Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
return rc;
}
@@ -2465,19 +2496,24 @@ static int load_state_from_tss16(struct
@@ -2487,19 +2518,24 @@ static int load_state_from_tss16(struct
* Now load segment descriptors. If fault happens at this stage
* it is handled in a context of new task
*/
@ -158,7 +158,7 @@ Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
if (ret != X86EMUL_CONTINUE)
return ret;
@@ -2602,25 +2638,32 @@ static int load_state_from_tss32(struct
@@ -2624,25 +2660,32 @@ static int load_state_from_tss32(struct
* Now load segment descriptors. If fault happenes at this stage
* it is handled in a context of new task
*/
@ -198,7 +198,7 @@ Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
if (ret != X86EMUL_CONTINUE)
return ret;
@@ -2900,24 +2943,39 @@ static int em_call_far(struct x86_emulat
@@ -2925,24 +2968,39 @@ static int em_call_far(struct x86_emulat
u16 sel, old_cs;
ulong old_eip;
int rc;

View File

@ -0,0 +1,58 @@
From: Nadav Amit <namit@cs.technion.ac.il>
Date: Tue, 28 Oct 2014 00:03:43 +0200
Subject: KVM: x86: Fix far-jump to non-canonical check
Origin: https://git.kernel.org/linus/7e46dddd6f6cd5dbf3c7bd04a7e75d19475ac9f2
Commit d1442d85cc30 ("KVM: x86: Handle errors when RIP is set during far
jumps") introduced a bug that caused the fix to be incomplete. Due to
incorrect evaluation, far jump to segment with L bit cleared (i.e., 32-bit
segment) and RIP with any of the high bits set (i.e, RIP[63:32] != 0) set may
not trigger #GP. As we know, this imposes a security problem.
In addition, the condition for two warnings was incorrect.
Fixes: d1442d85cc30ea75f7d399474ca738e0bc96f715
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Nadav Amit <namit@cs.technion.ac.il>
[Add #ifdef CONFIG_X86_64 to avoid complaints of undefined behavior. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
arch/x86/kvm/emulate.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -582,12 +582,14 @@ static inline int assign_eip_far(struct
case 4:
ctxt->_eip = (u32)dst;
break;
+#ifdef CONFIG_X86_64
case 8:
if ((cs_l && is_noncanonical_address(dst)) ||
- (!cs_l && (dst & ~(u32)-1)))
+ (!cs_l && (dst >> 32) != 0))
return emulate_gp(ctxt, 0);
ctxt->_eip = dst;
break;
+#endif
default:
WARN(1, "unsupported eip assignment size\n");
}
@@ -1998,7 +2000,7 @@ static int em_jmp_far(struct x86_emulate
rc = assign_eip_far(ctxt, ctxt->src.val, new_desc.l);
if (rc != X86EMUL_CONTINUE) {
- WARN_ON(!ctxt->mode != X86EMUL_MODE_PROT64);
+ WARN_ON(ctxt->mode != X86EMUL_MODE_PROT64);
/* assigning eip failed; restore the old cs */
ops->set_segment(ctxt, old_sel, &old_desc, 0, VCPU_SREG_CS);
return rc;
@@ -2092,7 +2094,7 @@ static int em_ret_far(struct x86_emulate
return rc;
rc = assign_eip_far(ctxt, eip, new_desc.l);
if (rc != X86EMUL_CONTINUE) {
- WARN_ON(!ctxt->mode != X86EMUL_MODE_PROT64);
+ WARN_ON(ctxt->mode != X86EMUL_MODE_PROT64);
ops->set_segment(ctxt, old_cs, &old_desc, 0, VCPU_SREG_CS);
}
return rc;

View File

@ -412,8 +412,9 @@ bugfix/x86/KVM-x86-Prevent-host-from-panicking-on-shared-MSR-wr.patch
bugfix/x86/KVM-x86-Improve-thread-safety-in-pit.patch
bugfix/x86/KVM-x86-Fix-wrong-masking-on-relative-jump-call.patch
bugfix/x86/kvm-vmx-handle-invvpid-vm-exit-gracefully.patch
bugfix/x86/KVM-x86-Handle-errors-when-RIP-is-set-during-far-jum.patch
bugfix/x86/KVM-x86-Emulator-fixes-for-eip-canonical-checks-on-n.patch
bugfix/x86/KVM-x86-Handle-errors-when-RIP-is-set-during-far-jum.patch
bugfix/x86/kvm-x86-fix-far-jump-to-non-canonical-check.patch
bugfix/all/net-sctp-fix-skb_over_panic-when-receiving-malformed.patch
bugfix/all/net-sctp-fix-panic-on-duplicate-ASCONF-chunks.patch
bugfix/all/net-sctp-fix-remote-memory-pressure-from-excessive-q.patch