aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm
diff options
context:
space:
mode:
authorNadav Amit <namit@cs.technion.ac.il>2014-09-18 15:39:38 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2014-10-24 07:21:16 -0400
commit234f3ce485d54017f15cf5e0699cff4100121601 (patch)
tree62918ccdcac761cf86db931110482b089c905abb /arch/x86/kvm
parent05c83ec9b73c8124555b706f6af777b10adf0862 (diff)
KVM: x86: Emulator fixes for eip canonical checks on near branches
Before changing rip (during jmp, call, ret, etc.) the target should be asserted to be canonical one, as real CPUs do. During sysret, both target rsp and rip should be canonical. If any of these values is noncanonical, a #GP exception should occur. The exception to this rule are syscall and sysenter instructions in which the assigned rip is checked during the assignment to the relevant MSRs. This patch fixes the emulator to behave as real CPUs do for near branches. Far branches are handled by the next patch. This fixes CVE-2014-3647. Cc: stable@vger.kernel.org Signed-off-by: Nadav Amit <namit@cs.technion.ac.il> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'arch/x86/kvm')
-rw-r--r--arch/x86/kvm/emulate.c78
1 files changed, 54 insertions, 24 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 047698974799..a1b9139169f6 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -564,7 +564,8 @@ static int emulate_nm(struct x86_emulate_ctxt *ctxt)
564 return emulate_exception(ctxt, NM_VECTOR, 0, false); 564 return emulate_exception(ctxt, NM_VECTOR, 0, false);
565} 565}
566 566
567static inline void assign_eip_near(struct x86_emulate_ctxt *ctxt, ulong dst) 567static inline int assign_eip_far(struct x86_emulate_ctxt *ctxt, ulong dst,
568 int cs_l)
568{ 569{
569 switch (ctxt->op_bytes) { 570 switch (ctxt->op_bytes) {
570 case 2: 571 case 2:
@@ -574,16 +575,25 @@ static inline void assign_eip_near(struct x86_emulate_ctxt *ctxt, ulong dst)
574 ctxt->_eip = (u32)dst; 575 ctxt->_eip = (u32)dst;
575 break; 576 break;
576 case 8: 577 case 8:
578 if ((cs_l && is_noncanonical_address(dst)) ||
579 (!cs_l && (dst & ~(u32)-1)))
580 return emulate_gp(ctxt, 0);
577 ctxt->_eip = dst; 581 ctxt->_eip = dst;
578 break; 582 break;
579 default: 583 default:
580 WARN(1, "unsupported eip assignment size\n"); 584 WARN(1, "unsupported eip assignment size\n");
581 } 585 }
586 return X86EMUL_CONTINUE;
587}
588
589static inline int assign_eip_near(struct x86_emulate_ctxt *ctxt, ulong dst)
590{
591 return assign_eip_far(ctxt, dst, ctxt->mode == X86EMUL_MODE_PROT64);
582} 592}
583 593
584static inline void jmp_rel(struct x86_emulate_ctxt *ctxt, int rel) 594static inline int jmp_rel(struct x86_emulate_ctxt *ctxt, int rel)
585{ 595{
586 assign_eip_near(ctxt, ctxt->_eip + rel); 596 return assign_eip_near(ctxt, ctxt->_eip + rel);
587} 597}
588 598
589static u16 get_segment_selector(struct x86_emulate_ctxt *ctxt, unsigned seg) 599static u16 get_segment_selector(struct x86_emulate_ctxt *ctxt, unsigned seg)
@@ -1998,13 +2008,15 @@ static int em_grp45(struct x86_emulate_ctxt *ctxt)
1998 case 2: /* call near abs */ { 2008 case 2: /* call near abs */ {
1999 long int old_eip; 2009 long int old_eip;
2000 old_eip = ctxt->_eip; 2010 old_eip = ctxt->_eip;
2001 ctxt->_eip = ctxt->src.val; 2011 rc = assign_eip_near(ctxt, ctxt->src.val);
2012 if (rc != X86EMUL_CONTINUE)
2013 break;
2002 ctxt->src.val = old_eip; 2014 ctxt->src.val = old_eip;
2003 rc = em_push(ctxt); 2015 rc = em_push(ctxt);
2004 break; 2016 break;
2005 } 2017 }
2006 case 4: /* jmp abs */ 2018 case 4: /* jmp abs */
2007 ctxt->_eip = ctxt->src.val; 2019 rc = assign_eip_near(ctxt, ctxt->src.val);
2008 break; 2020 break;
2009 case 5: /* jmp far */ 2021 case 5: /* jmp far */
2010 rc = em_jmp_far(ctxt); 2022 rc = em_jmp_far(ctxt);
@@ -2039,10 +2051,14 @@ static int em_cmpxchg8b(struct x86_emulate_ctxt *ctxt)
2039 2051
2040static int em_ret(struct x86_emulate_ctxt *ctxt) 2052static int em_ret(struct x86_emulate_ctxt *ctxt)
2041{ 2053{
2042 ctxt->dst.type = OP_REG; 2054 int rc;
2043 ctxt->dst.addr.reg = &ctxt->_eip; 2055 unsigned long eip;
2044 ctxt->dst.bytes = ctxt->op_bytes; 2056
2045 return em_pop(ctxt); 2057 rc = emulate_pop(ctxt, &eip, ctxt->op_bytes);
2058 if (rc != X86EMUL_CONTINUE)
2059 return rc;
2060
2061 return assign_eip_near(ctxt, eip);
2046} 2062}
2047 2063
2048static int em_ret_far(struct x86_emulate_ctxt *ctxt) 2064static int em_ret_far(struct x86_emulate_ctxt *ctxt)
@@ -2323,7 +2339,7 @@ static int em_sysexit(struct x86_emulate_ctxt *ctxt)
2323{ 2339{
2324 const struct x86_emulate_ops *ops = ctxt->ops; 2340 const struct x86_emulate_ops *ops = ctxt->ops;
2325 struct desc_struct cs, ss; 2341 struct desc_struct cs, ss;
2326 u64 msr_data; 2342 u64 msr_data, rcx, rdx;
2327 int usermode; 2343 int usermode;
2328 u16 cs_sel = 0, ss_sel = 0; 2344 u16 cs_sel = 0, ss_sel = 0;
2329 2345
@@ -2339,6 +2355,9 @@ static int em_sysexit(struct x86_emulate_ctxt *ctxt)
2339 else 2355 else
2340 usermode = X86EMUL_MODE_PROT32; 2356 usermode = X86EMUL_MODE_PROT32;
2341 2357
2358 rcx = reg_read(ctxt, VCPU_REGS_RCX);
2359 rdx = reg_read(ctxt, VCPU_REGS_RDX);
2360
2342 cs.dpl = 3; 2361 cs.dpl = 3;
2343 ss.dpl = 3; 2362 ss.dpl = 3;
2344 ops->get_msr(ctxt, MSR_IA32_SYSENTER_CS, &msr_data); 2363 ops->get_msr(ctxt, MSR_IA32_SYSENTER_CS, &msr_data);
@@ -2356,6 +2375,9 @@ static int em_sysexit(struct x86_emulate_ctxt *ctxt)
2356 ss_sel = cs_sel + 8; 2375 ss_sel = cs_sel + 8;
2357 cs.d = 0; 2376 cs.d = 0;
2358 cs.l = 1; 2377 cs.l = 1;
2378 if (is_noncanonical_address(rcx) ||
2379 is_noncanonical_address(rdx))
2380 return emulate_gp(ctxt, 0);
2359 break; 2381 break;
2360 } 2382 }
2361 cs_sel |= SELECTOR_RPL_MASK; 2383 cs_sel |= SELECTOR_RPL_MASK;
@@ -2364,8 +2386,8 @@ static int em_sysexit(struct x86_emulate_ctxt *ctxt)
2364 ops->set_segment(ctxt, cs_sel, &cs, 0, VCPU_SREG_CS); 2386 ops->set_segment(ctxt, cs_sel, &cs, 0, VCPU_SREG_CS);
2365 ops->set_segment(ctxt, ss_sel, &ss, 0, VCPU_SREG_SS); 2387 ops->set_segment(ctxt, ss_sel, &ss, 0, VCPU_SREG_SS);
2366 2388
2367 ctxt->_eip = reg_read(ctxt, VCPU_REGS_RDX); 2389 ctxt->_eip = rdx;
2368 *reg_write(ctxt, VCPU_REGS_RSP) = reg_read(ctxt, VCPU_REGS_RCX); 2390 *reg_write(ctxt, VCPU_REGS_RSP) = rcx;
2369 2391
2370 return X86EMUL_CONTINUE; 2392 return X86EMUL_CONTINUE;
2371} 2393}
@@ -2905,10 +2927,13 @@ static int em_aad(struct x86_emulate_ctxt *ctxt)
2905 2927
2906static int em_call(struct x86_emulate_ctxt *ctxt) 2928static int em_call(struct x86_emulate_ctxt *ctxt)
2907{ 2929{
2930 int rc;
2908 long rel = ctxt->src.val; 2931 long rel = ctxt->src.val;
2909 2932
2910 ctxt->src.val = (unsigned long)ctxt->_eip; 2933 ctxt->src.val = (unsigned long)ctxt->_eip;
2911 jmp_rel(ctxt, rel); 2934 rc = jmp_rel(ctxt, rel);
2935 if (rc != X86EMUL_CONTINUE)
2936 return rc;
2912 return em_push(ctxt); 2937 return em_push(ctxt);
2913} 2938}
2914 2939
@@ -2940,11 +2965,12 @@ static int em_call_far(struct x86_emulate_ctxt *ctxt)
2940static int em_ret_near_imm(struct x86_emulate_ctxt *ctxt) 2965static int em_ret_near_imm(struct x86_emulate_ctxt *ctxt)
2941{ 2966{
2942 int rc; 2967 int rc;
2968 unsigned long eip;
2943 2969
2944 ctxt->dst.type = OP_REG; 2970 rc = emulate_pop(ctxt, &eip, ctxt->op_bytes);
2945 ctxt->dst.addr.reg = &ctxt->_eip; 2971 if (rc != X86EMUL_CONTINUE)
2946 ctxt->dst.bytes = ctxt->op_bytes; 2972 return rc;
2947 rc = emulate_pop(ctxt, &ctxt->dst.val, ctxt->op_bytes); 2973 rc = assign_eip_near(ctxt, eip);
2948 if (rc != X86EMUL_CONTINUE) 2974 if (rc != X86EMUL_CONTINUE)
2949 return rc; 2975 return rc;
2950 rsp_increment(ctxt, ctxt->src.val); 2976 rsp_increment(ctxt, ctxt->src.val);
@@ -3271,20 +3297,24 @@ static int em_lmsw(struct x86_emulate_ctxt *ctxt)
3271 3297
3272static int em_loop(struct x86_emulate_ctxt *ctxt) 3298static int em_loop(struct x86_emulate_ctxt *ctxt)
3273{ 3299{
3300 int rc = X86EMUL_CONTINUE;
3301
3274 register_address_increment(ctxt, reg_rmw(ctxt, VCPU_REGS_RCX), -1); 3302 register_address_increment(ctxt, reg_rmw(ctxt, VCPU_REGS_RCX), -1);
3275 if ((address_mask(ctxt, reg_read(ctxt, VCPU_REGS_RCX)) != 0) && 3303 if ((address_mask(ctxt, reg_read(ctxt, VCPU_REGS_RCX)) != 0) &&
3276 (ctxt->b == 0xe2 || test_cc(ctxt->b ^ 0x5, ctxt->eflags))) 3304 (ctxt->b == 0xe2 || test_cc(ctxt->b ^ 0x5, ctxt->eflags)))
3277 jmp_rel(ctxt, ctxt->src.val); 3305 rc = jmp_rel(ctxt, ctxt->src.val);
3278 3306
3279 return X86EMUL_CONTINUE; 3307 return rc;
3280} 3308}
3281 3309
3282static int em_jcxz(struct x86_emulate_ctxt *ctxt) 3310static int em_jcxz(struct x86_emulate_ctxt *ctxt)
3283{ 3311{
3312 int rc = X86EMUL_CONTINUE;
3313
3284 if (address_mask(ctxt, reg_read(ctxt, VCPU_REGS_RCX)) == 0) 3314 if (address_mask(ctxt, reg_read(ctxt, VCPU_REGS_RCX)) == 0)
3285 jmp_rel(ctxt, ctxt->src.val); 3315 rc = jmp_rel(ctxt, ctxt->src.val);
3286 3316
3287 return X86EMUL_CONTINUE; 3317 return rc;
3288} 3318}
3289 3319
3290static int em_in(struct x86_emulate_ctxt *ctxt) 3320static int em_in(struct x86_emulate_ctxt *ctxt)
@@ -4743,7 +4773,7 @@ special_insn:
4743 break; 4773 break;
4744 case 0x70 ... 0x7f: /* jcc (short) */ 4774 case 0x70 ... 0x7f: /* jcc (short) */
4745 if (test_cc(ctxt->b, ctxt->eflags)) 4775 if (test_cc(ctxt->b, ctxt->eflags))
4746 jmp_rel(ctxt, ctxt->src.val); 4776 rc = jmp_rel(ctxt, ctxt->src.val);
4747 break; 4777 break;
4748 case 0x8d: /* lea r16/r32, m */ 4778 case 0x8d: /* lea r16/r32, m */
4749 ctxt->dst.val = ctxt->src.addr.mem.ea; 4779 ctxt->dst.val = ctxt->src.addr.mem.ea;
@@ -4773,7 +4803,7 @@ special_insn:
4773 break; 4803 break;
4774 case 0xe9: /* jmp rel */ 4804 case 0xe9: /* jmp rel */
4775 case 0xeb: /* jmp rel short */ 4805 case 0xeb: /* jmp rel short */
4776 jmp_rel(ctxt, ctxt->src.val); 4806 rc = jmp_rel(ctxt, ctxt->src.val);
4777 ctxt->dst.type = OP_NONE; /* Disable writeback. */ 4807 ctxt->dst.type = OP_NONE; /* Disable writeback. */
4778 break; 4808 break;
4779 case 0xf4: /* hlt */ 4809 case 0xf4: /* hlt */
@@ -4898,7 +4928,7 @@ twobyte_insn:
4898 break; 4928 break;
4899 case 0x80 ... 0x8f: /* jnz rel, etc*/ 4929 case 0x80 ... 0x8f: /* jnz rel, etc*/
4900 if (test_cc(ctxt->b, ctxt->eflags)) 4930 if (test_cc(ctxt->b, ctxt->eflags))
4901 jmp_rel(ctxt, ctxt->src.val); 4931 rc = jmp_rel(ctxt, ctxt->src.val);
4902 break; 4932 break;
4903 case 0x90 ... 0x9f: /* setcc r/m8 */ 4933 case 0x90 ... 0x9f: /* setcc r/m8 */
4904 ctxt->dst.val = test_cc(ctxt->b, ctxt->eflags); 4934 ctxt->dst.val = test_cc(ctxt->b, ctxt->eflags);