Testcases for "eip canonical" kvm fixes?
From: Denys Vlasenko
Date: Tue Mar 10 2015 - 14:37:42 EST
Hi,
I wonder how did you trigger the bug for your following fix?
commit 234f3ce485d54017f15cf5e0699cff4100121601
Author: Nadav Amit <namit@xxxxxxxxxxxxxxxxx>
Date: Thu Sep 18 22:39:38 2014 +0300
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.
Non-canonical addresses result in #GP, but KVM doesn't
intercept guest #GP, according to code below:
static void update_exception_bitmap(struct kvm_vcpu *vcpu)
{
u32 eb;
eb = (1u << PF_VECTOR) | (1u << UD_VECTOR) | (1u << MC_VECTOR) |
(1u << NM_VECTOR) | (1u << DB_VECTOR);
if ((vcpu->guest_debug &
(KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP)) ==
(KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP))
eb |= 1u << BP_VECTOR;
if (to_vmx(vcpu)->rmode.vm86_active)
eb = ~0;
if (enable_ept)
eb &= ~(1u << PF_VECTOR); /* bypass_guest_pf = 0 */
if (vcpu->fpu_active)
eb &= ~(1u << NM_VECTOR);
/* When we are running a nested L2 guest and L1 specified for it a
* certain exception bitmap, we must trap the same exceptions and pass
* them to L1. When running L2, we will only handle the exceptions
* specified above if L1 did not want them.
*/
if (is_guest_mode(vcpu))
eb |= get_vmcs12(vcpu)->exception_bitmap;
vmcs_write32(EXCEPTION_BITMAP, eb);
}
That what seems to be happening to me when I try to reproduce
the bug on unpatched kernel: CPU simply emulates #GP, and
everything works as it should.
In particular:
I'm trying "RET far" with noncanonical address on stack (and valid CS).
I expect that buggy behavior would be that #GP happens
after "RET far". Instead, #GP happens _on_ "RET far" insn.
--
vda
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/