[kernel] r22030 - in dists/sid/linux/debian: . patches patches/bugfix/x86

Ben Hutchings benh at moszumanska.debian.org
Tue Nov 4 00:19:39 UTC 2014


Author: benh
Date: Tue Nov  4 00:19:39 2014
New Revision: 22030

Log:
[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.

Added:
   dists/sid/linux/debian/patches/bugfix/x86/kvm-x86-fix-far-jump-to-non-canonical-check.patch
Modified:
   dists/sid/linux/debian/changelog
   dists/sid/linux/debian/patches/bugfix/x86/KVM-x86-Emulator-fixes-for-eip-canonical-checks-on-n.patch
   dists/sid/linux/debian/patches/bugfix/x86/KVM-x86-Handle-errors-when-RIP-is-set-during-far-jum.patch
   dists/sid/linux/debian/patches/series

Modified: dists/sid/linux/debian/changelog
==============================================================================
--- dists/sid/linux/debian/changelog	Tue Nov  4 00:06:12 2014	(r22029)
+++ dists/sid/linux/debian/changelog	Tue Nov  4 00:19:39 2014	(r22030)
@@ -142,6 +142,7 @@
   * [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)

Modified: dists/sid/linux/debian/patches/bugfix/x86/KVM-x86-Emulator-fixes-for-eip-canonical-checks-on-n.patch
==============================================================================
--- dists/sid/linux/debian/patches/bugfix/x86/KVM-x86-Emulator-fixes-for-eip-canonical-checks-on-n.patch	Tue Nov  4 00:06:12 2014	(r22029)
+++ dists/sid/linux/debian/patches/bugfix/x86/KVM-x86-Emulator-fixes-for-eip-canonical-checks-on-n.patch	Tue Nov  4 00:19:39 2014	(r22030)
@@ -62,7 +62,7 @@
  }
  
  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 @@
  		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 @@
  }
  
  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 @@
  	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 @@
  	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 @@
  		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 @@
  
  	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 @@
  	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 @@
  	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 @@
  }
  
  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 @@
  		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 @@
  		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))

Modified: dists/sid/linux/debian/patches/bugfix/x86/KVM-x86-Handle-errors-when-RIP-is-set-during-far-jum.patch
==============================================================================
--- dists/sid/linux/debian/patches/bugfix/x86/KVM-x86-Handle-errors-when-RIP-is-set-during-far-jum.patch	Tue Nov  4 00:06:12 2014	(r22029)
+++ dists/sid/linux/debian/patches/bugfix/x86/KVM-x86-Handle-errors-when-RIP-is-set-during-far-jum.patch	Tue Nov  4 00:19:39 2014	(r22030)
@@ -22,7 +22,7 @@
 
 --- 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 @@
  {
  	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 @@
  	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 @@
  }
  
  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 @@
  }
  
  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 @@
  	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 @@
  	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 @@
  	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 @@
  	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;

Added: dists/sid/linux/debian/patches/bugfix/x86/kvm-x86-fix-far-jump-to-non-canonical-check.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/sid/linux/debian/patches/bugfix/x86/kvm-x86-fix-far-jump-to-non-canonical-check.patch	Tue Nov  4 00:19:39 2014	(r22030)
@@ -0,0 +1,58 @@
+From: Nadav Amit <namit at 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 at oracle.com>
+Signed-off-by: Nadav Amit <namit at cs.technion.ac.il>
+[Add #ifdef CONFIG_X86_64 to avoid complaints of undefined behavior. - Paolo]
+Signed-off-by: Paolo Bonzini <pbonzini at 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;

Modified: dists/sid/linux/debian/patches/series
==============================================================================
--- dists/sid/linux/debian/patches/series	Tue Nov  4 00:06:12 2014	(r22029)
+++ dists/sid/linux/debian/patches/series	Tue Nov  4 00:19:39 2014	(r22030)
@@ -412,8 +412,9 @@
 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



More information about the Kernel-svn-changes mailing list