[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-users] intercept and capture fast system call of linux



Thank you so muchã
I replaced "__vmwrite(GUEST_RIP, real_rip);" with "regs->eip=real_eip", and it worked.
tha value of GUEST_RIP and regs->eip are the same, but regs->eip will work when reenter VM.

å2014-02-28 17:35:16ïéèähanyandong@xxxxxxxxxåéï

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_handlerand 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






_______________________________________________
Xen-users mailing list
Xen-users@xxxxxxxxxxxxx
http://lists.xen.org/xen-users

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.