Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

KVM: x86: Handle errors when RIP is set during far jumps

Far jmp/call/ret may fault while loading a new RIP. Currently KVM does not
handle this case, and may result in failed vm-entry once the assignment is
done. The tricky part of doing so is that loading the new CS affects the
VMCS/VMCB state, so if we fail during loading the new RIP, we are left in
unconsistent state. Therefore, this patch saves on 64-bit the old CS
descriptor and restores it if loading RIP failed.

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>

authored by

Nadav Amit and committed by
Paolo Bonzini
d1442d85 234f3ce4

+88 -30
+88 -30
arch/x86/kvm/emulate.c
··· 1443 1443 1444 1444 /* Does not support long mode */ 1445 1445 static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt, 1446 - u16 selector, int seg, u8 cpl, bool in_task_switch) 1446 + u16 selector, int seg, u8 cpl, 1447 + bool in_task_switch, 1448 + struct desc_struct *desc) 1447 1449 { 1448 1450 struct desc_struct seg_desc, old_desc; 1449 1451 u8 dpl, rpl; ··· 1586 1584 } 1587 1585 load: 1588 1586 ctxt->ops->set_segment(ctxt, selector, &seg_desc, base3, seg); 1587 + if (desc) 1588 + *desc = seg_desc; 1589 1589 return X86EMUL_CONTINUE; 1590 1590 exception: 1591 1591 return emulate_exception(ctxt, err_vec, err_code, true); ··· 1597 1593 u16 selector, int seg) 1598 1594 { 1599 1595 u8 cpl = ctxt->ops->cpl(ctxt); 1600 - return __load_segment_descriptor(ctxt, selector, seg, cpl, false); 1596 + return __load_segment_descriptor(ctxt, selector, seg, cpl, false, NULL); 1601 1597 } 1602 1598 1603 1599 static void write_register_operand(struct operand *op) ··· 1991 1987 static int em_jmp_far(struct x86_emulate_ctxt *ctxt) 1992 1988 { 1993 1989 int rc; 1994 - unsigned short sel; 1990 + unsigned short sel, old_sel; 1991 + struct desc_struct old_desc, new_desc; 1992 + const struct x86_emulate_ops *ops = ctxt->ops; 1993 + u8 cpl = ctxt->ops->cpl(ctxt); 1994 + 1995 + /* Assignment of RIP may only fail in 64-bit mode */ 1996 + if (ctxt->mode == X86EMUL_MODE_PROT64) 1997 + ops->get_segment(ctxt, &old_sel, &old_desc, NULL, 1998 + VCPU_SREG_CS); 1995 1999 1996 2000 memcpy(&sel, ctxt->src.valptr + ctxt->op_bytes, 2); 1997 2001 1998 - rc = load_segment_descriptor(ctxt, sel, VCPU_SREG_CS); 2002 + rc = __load_segment_descriptor(ctxt, sel, VCPU_SREG_CS, cpl, false, 2003 + &new_desc); 1999 2004 if (rc != X86EMUL_CONTINUE) 2000 2005 return rc; 2001 2006 2002 - ctxt->_eip = 0; 2003 - memcpy(&ctxt->_eip, ctxt->src.valptr, ctxt->op_bytes); 2004 - return X86EMUL_CONTINUE; 2007 + rc = assign_eip_far(ctxt, ctxt->src.val, new_desc.l); 2008 + if (rc != X86EMUL_CONTINUE) { 2009 + WARN_ON(!ctxt->mode != X86EMUL_MODE_PROT64); 2010 + /* assigning eip failed; restore the old cs */ 2011 + ops->set_segment(ctxt, old_sel, &old_desc, 0, VCPU_SREG_CS); 2012 + return rc; 2013 + } 2014 + return rc; 2005 2015 } 2006 2016 2007 2017 static int em_grp45(struct x86_emulate_ctxt *ctxt) ··· 2082 2064 static int em_ret_far(struct x86_emulate_ctxt *ctxt) 2083 2065 { 2084 2066 int rc; 2085 - unsigned long cs; 2067 + unsigned long eip, cs; 2068 + u16 old_cs; 2086 2069 int cpl = ctxt->ops->cpl(ctxt); 2070 + struct desc_struct old_desc, new_desc; 2071 + const struct x86_emulate_ops *ops = ctxt->ops; 2087 2072 2088 - rc = emulate_pop(ctxt, &ctxt->_eip, ctxt->op_bytes); 2073 + if (ctxt->mode == X86EMUL_MODE_PROT64) 2074 + ops->get_segment(ctxt, &old_cs, &old_desc, NULL, 2075 + VCPU_SREG_CS); 2076 + 2077 + rc = emulate_pop(ctxt, &eip, ctxt->op_bytes); 2089 2078 if (rc != X86EMUL_CONTINUE) 2090 2079 return rc; 2091 - if (ctxt->op_bytes == 4) 2092 - ctxt->_eip = (u32)ctxt->_eip; 2093 2080 rc = emulate_pop(ctxt, &cs, ctxt->op_bytes); 2094 2081 if (rc != X86EMUL_CONTINUE) 2095 2082 return rc; 2096 2083 /* Outer-privilege level return is not implemented */ 2097 2084 if (ctxt->mode >= X86EMUL_MODE_PROT16 && (cs & 3) > cpl) 2098 2085 return X86EMUL_UNHANDLEABLE; 2099 - rc = load_segment_descriptor(ctxt, (u16)cs, VCPU_SREG_CS); 2086 + rc = __load_segment_descriptor(ctxt, (u16)cs, VCPU_SREG_CS, 0, false, 2087 + &new_desc); 2088 + if (rc != X86EMUL_CONTINUE) 2089 + return rc; 2090 + rc = assign_eip_far(ctxt, eip, new_desc.l); 2091 + if (rc != X86EMUL_CONTINUE) { 2092 + WARN_ON(!ctxt->mode != X86EMUL_MODE_PROT64); 2093 + ops->set_segment(ctxt, old_cs, &old_desc, 0, VCPU_SREG_CS); 2094 + } 2100 2095 return rc; 2101 2096 } 2102 2097 ··· 2536 2505 * Now load segment descriptors. If fault happens at this stage 2537 2506 * it is handled in a context of new task 2538 2507 */ 2539 - ret = __load_segment_descriptor(ctxt, tss->ldt, VCPU_SREG_LDTR, cpl, true); 2508 + ret = __load_segment_descriptor(ctxt, tss->ldt, VCPU_SREG_LDTR, cpl, 2509 + true, NULL); 2540 2510 if (ret != X86EMUL_CONTINUE) 2541 2511 return ret; 2542 - ret = __load_segment_descriptor(ctxt, tss->es, VCPU_SREG_ES, cpl, true); 2512 + ret = __load_segment_descriptor(ctxt, tss->es, VCPU_SREG_ES, cpl, 2513 + true, NULL); 2543 2514 if (ret != X86EMUL_CONTINUE) 2544 2515 return ret; 2545 - ret = __load_segment_descriptor(ctxt, tss->cs, VCPU_SREG_CS, cpl, true); 2516 + ret = __load_segment_descriptor(ctxt, tss->cs, VCPU_SREG_CS, cpl, 2517 + true, NULL); 2546 2518 if (ret != X86EMUL_CONTINUE) 2547 2519 return ret; 2548 - ret = __load_segment_descriptor(ctxt, tss->ss, VCPU_SREG_SS, cpl, true); 2520 + ret = __load_segment_descriptor(ctxt, tss->ss, VCPU_SREG_SS, cpl, 2521 + true, NULL); 2549 2522 if (ret != X86EMUL_CONTINUE) 2550 2523 return ret; 2551 - ret = __load_segment_descriptor(ctxt, tss->ds, VCPU_SREG_DS, cpl, true); 2524 + ret = __load_segment_descriptor(ctxt, tss->ds, VCPU_SREG_DS, cpl, 2525 + true, NULL); 2552 2526 if (ret != X86EMUL_CONTINUE) 2553 2527 return ret; 2554 2528 ··· 2678 2642 * Now load segment descriptors. If fault happenes at this stage 2679 2643 * it is handled in a context of new task 2680 2644 */ 2681 - ret = __load_segment_descriptor(ctxt, tss->ldt_selector, VCPU_SREG_LDTR, cpl, true); 2645 + ret = __load_segment_descriptor(ctxt, tss->ldt_selector, VCPU_SREG_LDTR, 2646 + cpl, true, NULL); 2682 2647 if (ret != X86EMUL_CONTINUE) 2683 2648 return ret; 2684 - ret = __load_segment_descriptor(ctxt, tss->es, VCPU_SREG_ES, cpl, true); 2649 + ret = __load_segment_descriptor(ctxt, tss->es, VCPU_SREG_ES, cpl, 2650 + true, NULL); 2685 2651 if (ret != X86EMUL_CONTINUE) 2686 2652 return ret; 2687 - ret = __load_segment_descriptor(ctxt, tss->cs, VCPU_SREG_CS, cpl, true); 2653 + ret = __load_segment_descriptor(ctxt, tss->cs, VCPU_SREG_CS, cpl, 2654 + true, NULL); 2688 2655 if (ret != X86EMUL_CONTINUE) 2689 2656 return ret; 2690 - ret = __load_segment_descriptor(ctxt, tss->ss, VCPU_SREG_SS, cpl, true); 2657 + ret = __load_segment_descriptor(ctxt, tss->ss, VCPU_SREG_SS, cpl, 2658 + true, NULL); 2691 2659 if (ret != X86EMUL_CONTINUE) 2692 2660 return ret; 2693 - ret = __load_segment_descriptor(ctxt, tss->ds, VCPU_SREG_DS, cpl, true); 2661 + ret = __load_segment_descriptor(ctxt, tss->ds, VCPU_SREG_DS, cpl, 2662 + true, NULL); 2694 2663 if (ret != X86EMUL_CONTINUE) 2695 2664 return ret; 2696 - ret = __load_segment_descriptor(ctxt, tss->fs, VCPU_SREG_FS, cpl, true); 2665 + ret = __load_segment_descriptor(ctxt, tss->fs, VCPU_SREG_FS, cpl, 2666 + true, NULL); 2697 2667 if (ret != X86EMUL_CONTINUE) 2698 2668 return ret; 2699 - ret = __load_segment_descriptor(ctxt, tss->gs, VCPU_SREG_GS, cpl, true); 2669 + ret = __load_segment_descriptor(ctxt, tss->gs, VCPU_SREG_GS, cpl, 2670 + true, NULL); 2700 2671 if (ret != X86EMUL_CONTINUE) 2701 2672 return ret; 2702 2673 ··· 2985 2942 u16 sel, old_cs; 2986 2943 ulong old_eip; 2987 2944 int rc; 2945 + struct desc_struct old_desc, new_desc; 2946 + const struct x86_emulate_ops *ops = ctxt->ops; 2947 + int cpl = ctxt->ops->cpl(ctxt); 2988 2948 2989 - old_cs = get_segment_selector(ctxt, VCPU_SREG_CS); 2990 2949 old_eip = ctxt->_eip; 2950 + ops->get_segment(ctxt, &old_cs, &old_desc, NULL, VCPU_SREG_CS); 2991 2951 2992 2952 memcpy(&sel, ctxt->src.valptr + ctxt->op_bytes, 2); 2993 - if (load_segment_descriptor(ctxt, sel, VCPU_SREG_CS)) 2953 + rc = __load_segment_descriptor(ctxt, sel, VCPU_SREG_CS, cpl, false, 2954 + &new_desc); 2955 + if (rc != X86EMUL_CONTINUE) 2994 2956 return X86EMUL_CONTINUE; 2995 2957 2996 - ctxt->_eip = 0; 2997 - memcpy(&ctxt->_eip, ctxt->src.valptr, ctxt->op_bytes); 2958 + rc = assign_eip_far(ctxt, ctxt->src.val, new_desc.l); 2959 + if (rc != X86EMUL_CONTINUE) 2960 + goto fail; 2998 2961 2999 2962 ctxt->src.val = old_cs; 3000 2963 rc = em_push(ctxt); 3001 2964 if (rc != X86EMUL_CONTINUE) 3002 - return rc; 2965 + goto fail; 3003 2966 3004 2967 ctxt->src.val = old_eip; 3005 - return em_push(ctxt); 2968 + rc = em_push(ctxt); 2969 + /* If we failed, we tainted the memory, but the very least we should 2970 + restore cs */ 2971 + if (rc != X86EMUL_CONTINUE) 2972 + goto fail; 2973 + return rc; 2974 + fail: 2975 + ops->set_segment(ctxt, old_cs, &old_desc, 0, VCPU_SREG_CS); 2976 + return rc; 2977 + 3006 2978 } 3007 2979 3008 2980 static int em_ret_near_imm(struct x86_emulate_ctxt *ctxt)