Now I attach the code to my question
hi all,I want to intercept and capture fast system call of linux.
(1)I set GUEST_SYSENTER_EIP to 0xDDDDD0AE in vmx_vmexit_handler, and save the real value.
in vmx_vmexit_handler()
{
....
//yandong
if( is_hvm_domain(current->domain) )
{
//printk("MITCTL:is_hvm_domain\n");
switch (current->domain->arch.hvm_domain.mitctl_op.xen_vmexit_handler_mitctl_method)
{
case -1: break;
case XEN_VMEXIT_HANDLER_MITCTL_libvmi :
{
//printk("MITCTL:vmexit set_trap\n");
vmx_properly_set_trap_flag(current->domain);
break;
}
default: break;
}
}
return ...
}
inline void vmx_properly_set_trap_flag(struct domain *d)
{
//set sysenter_eip
if(d->arch.hvm_domain.mitctl_op.xen_vmexit_handler_mitctl_method != -1)
{
vmx_set_sysenter_msrs(d);
//current->arch.hvm_vmx.exec_control |= CPU_BASED_MONITOR_TRAP_FLAG;
//vmx_update_cpu_exec_control(current);
//current->arch.hvm_vcpu.single_step = 1;
}
return;
}
/* force user supplied msr values on this guest */
inline void vmx_set_sysenter_msrs(struct domain *d)
{
u64 new_cs;
u64 new_eip;
u64 old_MSR_EIP = __vmread(GUEST_SYSENTER_EIP);
u64 old_MSR_CS = __vmread(GUEST_SYSENTER_CS);
if( 0xDDDDD0AE != old_MSR_EIP)
{
printk("MITCTL:old_MSR_EIP %lx\n",old_MSR_EIP);
ether_set_imaginary_sysenter_eip(d, old_MSR_EIP);
ether_set_imaginary_sysenter_cs(d, old_MSR_CS);
}
printk("MITCTL:vmx_set_sysenter_msrs GUEST_SYSENTER_EIP %lx %lx\n",old_MSR_EIP, old_MSR_CS);
/* write MSR registers */
/* default to writing old(imaginary) values to guest */
new_cs = ether_get_imaginary_sysenter_cs(d);
new_eip = ether_get_imaginary_sysenter_eip(d);
if(d->arch.hvm_domain.mitctl_op.xen_vmexit_handler_mitctl_method != -1)
{
/* it seems that we should write user supplied
* values instead
*/
u64 forced_cs;
u64 forced_eip;
/* writing user supplied forced values to guest */
forced_cs = ether_get_sysenter_cs(d);
forced_eip = ether_get_sysenter_eip(d);
if(forced_cs)
new_cs = forced_cs;
if(forced_eip)
new_eip = forced_eip;
}
vmx_write_sysenter_msr(GUEST_SYSENTER_CS, new_cs);
vmx_write_sysenter_msr(GUEST_SYSENTER_EIP, new_eip);
}
(2)When a fast syscall come, I will caputue it in sh_page_fault.
(3) Then I set the real GUEST_SYSENTER_EIP(c0103ef0, ia32_sysenter_target) to GUEST_RIP.
static int sh_page_fault(struct vcpu *v,
unsigned long va,
struct cpu_user_regs *regs)
{
...
/*yandong*/
/* Check if this page fault occurs on our magic address */
if(unlikely(ether_get_sysenter_eip(d) != 0 && ether_get_sysenter_eip(d) == va))
{
/* only go through
* with the fault notification if it occurred during
* an instruction fetch.
*/
if ( regs->error_code & PFEC_insn_fetch )
{
unsigned long real_rip = ether_get_imaginary_sysenter_eip(d);
/* process system call notification */
shadow_lock(d);
ether_handle_syscall(v, regs);
shadow_unlock(d);
/* lets update rip to put us in a much happier
* place in memory, notably the actual
* sysenter handling address
*/
printk("MITCTL: sh_page_fault syscall real_rip %lx %lx\n", va, ether_get_sysenter_eip(d));
printk("MITCTL: sh_page_fault syscall real_rip %lx\n", __vmread(GUEST_RIP));
//printk("MITCTL: sh_page_fault syscall %lx %lx %lx %lx\n");
__vmwrite(GUEST_RIP, real_rip);
printk("MITCTL: sh_page_fault syscall real_rip %lx\n", __vmread(GUEST_RIP));
return 1;
}
}
...
}
But, I encounter Infinite loops as below. I always capture the same syscall.
In sh_page_fault, I have successfully set c0103ef0 to GUEST_RIP.But I still capure a page fault , the GUEST_RIP is ddddd0ae.
why? Thank you very much.
(XEN) MIT SYSCALL 7
(XEN) MITCTL: sh_page_fault syscall real_rip ddddd0ae ddddd0ae
(XEN) MITCTL: sh_page_fault syscall real_rip ddddd0ae
(XEN) MITCTL: sh_page_fault syscall real_rip c0103ef0
(XEN) MITCTL:vmx_set_sysenter_msrs GUEST_SYSENTER_EIP ddddd0ae 60
(XEN) vmx_vmenter_helper MITCTL: sh_page_fault syscall real_rip c0103ef0
(XEN) TRAP_page_fault
(XEN) MIT SYSCALL 7
(XEN) MITCTL: sh_page_fault syscall real_rip ddddd0ae ddddd0ae
(XEN) MITCTL: sh_page_fault syscall real_rip ddddd0ae
(XEN) MITCTL: sh_page_fault syscall real_rip c0103ef0
(XEN) MITCTL:vmx_set_sysenter_msrs GUEST_SYSENTER_EIP ddddd0ae 60
(XEN) vmx_vmenter_helper MITCTL: sh_page_fault syscall real_rip c0103ef0
(XEN) TRAP_page_fault
(XEN) MIT SYSCALL 7
Best Regards
Yes, I take the chance that 0xddddd0ae is unmapped within the p2m. Fast system call does not trap into xen. It use an
instruction called sysenter.
> -----ååéä-----
> åää: "Ian Campbell" <
ian.campbell@xxxxxxxxxx>
> åéæé: 2014å2æ28æ ææä
> æää: "éèä" <
hanyandong@xxxxxxxxx>
> æé:
xen-users@xxxxxxxxxxxxxxxxxxx> äé: Re: [Xen-users] intercept and capture fast system call of linux
>
> On Fri, 2014-02-28 at 12:50 +0800, éèä wrote:
> > hi,
> > I want to intercept and capture fast system call of linux.
> > (1)I set GUEST_SYSENTER_EIP to 0xDDDDD0AE in vmx_vmexit_handler, and
> > save the real value.
>
> Are you taking the chance that 0xddddd0ae is unmapped within the p2m? Is
> there not an explicit trap for syscalls in the VMCS?
>
> > (2)When a fast syscall come, I will caputue it in sh_page_fault.
> > (3) Then I set the real GUEST_SYSENTER_EIP(c0103ef0,
> > ia32_sysenter_target) to GUEST_RIP.
>
> Are you sure that setting GUEST_RIP is sufficient to cause the guest to
> switch to that when you reenter? Is there nothing else you need to
> change/update in order to simulate the affect of a syscall from the
> guest PoV?
>
> You might find it helpful to publish your actual code so people can see
> what you've actually done..
>
> You might also want to post to the -devel list instead.
>
> Ian.
>
>
>
> _______________________________________________
> Xen-users mailing list
>
Xen-users@xxxxxxxxxxxxx> http://lists.xen.org/xen-users