|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 2/2] x86/svm: Write the correct %eip into the outgoing task
On 21.11.2019 23:15, Andrew Cooper wrote:
> --- a/xen/arch/x86/hvm/svm/emulate.c
> +++ b/xen/arch/x86/hvm/svm/emulate.c
> @@ -117,6 +117,61 @@ unsigned int svm_get_insn_len(struct vcpu *v, unsigned
> int instr_enc)
> }
>
> /*
> + * TASK_SWITCH vmexits never provide an instruction length. We must always
> + * decode under %rip to find the answer.
> + */
> +unsigned int svm_get_task_switch_insn_len(struct vcpu *v)
> +{
> + struct hvm_emulate_ctxt ctxt;
> + struct x86_emulate_state *state;
> + unsigned int emul_len, modrm_reg;
> +
> + ASSERT(v == current);
You look to be using v here just for this ASSERT() - is this really
worth it? By making the function take "void" it would be quite obvious
that it would act on the current vCPU only.
> + hvm_emulate_init_once(&ctxt, NULL, guest_cpu_user_regs());
> + hvm_emulate_init_per_insn(&ctxt, NULL, 0);
> + state = x86_decode_insn(&ctxt.ctxt, hvmemul_insn_fetch);
> + if ( IS_ERR_OR_NULL(state) )
> + return 0;
> +
> + emul_len = x86_insn_length(state, &ctxt.ctxt);
> +
> + /*
> + * Check for an instruction which can cause a task switch. Any far
> + * jmp/call/ret, any software interrupt/exception, and iret.
> + */
> + switch ( ctxt.ctxt.opcode )
> + {
> + case 0xff: /* Grp 5 */
> + /* call / jmp (far, absolute indirect) */
> + if ( x86_insn_modrm(state, NULL, &modrm_reg) != 3 ||
DYM "== 3", to bail upon non-memory operands?
> + (modrm_reg != 3 && modrm_reg != 5) )
> + {
> + /* Wrong instruction. Throw #GP back for now. */
> + default:
> + hvm_inject_hw_exception(TRAP_gp_fault, 0);
> + emul_len = 0;
> + break;
> + }
> + /* Fallthrough */
> + case 0x62: /* bound */
Does "bound" really belong on this list? It raising #BR is like
insns raising random other exceptions, not like INTO / INT3,
where the IDT descriptor also has to have suitable DPL for the
exception to actually get delivered (rather than #GP). I.e. it
shouldn't make it here in the first place, due to the
X86_EVENTTYPE_HW_EXCEPTION check in the caller.
IOW if "bound" needs to be here, then all others need to be as
well, unless they can't cause any exception at all.
> + case 0x9a: /* call (far, absolute) */
> + case 0xca: /* ret imm16 (far) */
> + case 0xcb: /* ret (far) */
> + case 0xcc: /* int3 */
> + case 0xcd: /* int imm8 */
> + case 0xce: /* into */
> + case 0xcf: /* iret */
> + case 0xea: /* jmp (far, absolute) */
> + case 0xf1: /* icebp */
Same perhaps for ICEBP, albeit I'm less certain here, as its
behavior is too poorly documented (if at all).
> --- a/xen/arch/x86/hvm/svm/svm.c
> +++ b/xen/arch/x86/hvm/svm/svm.c
> @@ -2776,7 +2776,41 @@ void svm_vmexit_handler(struct cpu_user_regs *regs)
>
> case VMEXIT_TASK_SWITCH: {
> enum hvm_task_switch_reason reason;
> - int32_t errcode = -1;
> + int32_t errcode = -1, insn_len = -1;
> +
> + /*
> + * All TASK_SWITCH intercepts have fault-like semantics. NRIP is
> + * never provided, even for instruction-induced task switches, but we
> + * need to know the instruction length in order to set %eip suitably
> + * in the outgoing TSS.
> + *
> + * For a task switch which vectored through the IDT, look at the type
> + * to distinguish interrupts/exceptions from instruction based
> + * switches.
> + */
> + if ( vmcb->eventinj.fields.v )
> + {
> + /*
> + * HW_EXCEPTION, NMI and EXT_INTR are not instruction based. All
> + * others are.
> + */
> + if ( vmcb->eventinj.fields.type <= X86_EVENTTYPE_HW_EXCEPTION )
> + insn_len = 0;
> +
> + /*
> + * Clobber the vectoring information, as we are going to emulate
> + * the task switch in full.
> + */
> + vmcb->eventinj.bytes = 0;
> + }
> +
> + /*
> + * insn_len being -1 indicates that we have an instruction-induced
> + * task switch. Decode under %rip to find its length.
> + */
> + if ( insn_len < 0 && (insn_len = svm_get_task_switch_insn_len(v)) ==
> 0 )
> + break;
Won't this live-lock the guest? I.e. isn't it better to e.g. crash it
if svm_get_task_switch_insn_len() didn't raise #GP(0)?
Jan
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |