I want to intercept syscall on Xen, by modifing SYSENTER_MSR_CS as 0x0 to trap sysenter/sysexit into Xen because of #GP.
I am going to crazying, anyone can help me?
The following is details:
Step 1) first, I set Xen to trap the #GP.
In vmx_vmexit_handler()
__vmwrite(EXCEPTION_BITMAP, __vmread(EXCEPTION_BITMAP) | (1U<<TRAP_gp_fault));
current->arch.hvm_vmx.exception_bitmap = current->arch.hvm_vmx.exception_bitmap | (1U<<TRAP_gp_fault);
Step 2) set Xen to handle the GP.
In vmx_vmexit_handler()
switch ( exit_reason )
{
case EXIT_REASON_EXCEPTION_NMI:
{
...
switch ( vector )
{
//dprintk(XENLOG_G_ERR, "vmexit hander exit_reason %u, vector %d \n", exit_reason, vector);
case TRAP_debug:...
case TRAP_gp_fault:
{
unsigned char inst[4] = {0,0,0,0};
printk("[%d]GET #GP MSR_CS=[%lx %x] %lx [%lx %x] !!!\n",v->domain->domain_id,__vmread(GUEST_SYSENTER_CS), regs->cs,regs->eip, regs->esp, regs->ss);
hvm_copy_from_guest_virt(inst, regs->eip,sizeof(inst),0);
switch(inst[0])
{
case 0x34: printk("sysenter 1 \n");
{
__vmwrite(GUEST_CS_SELECTOR, ether_get_imaginary_sysenter_cs(v->domain));
__vmwrite(GUEST_CS_BASE, 0U);
__vmwrite(GUEST_CS_LIMIT, ~0U);
__vmwrite(GUEST_CS_AR_BYTES, 0xc09b);
__vmwrite(GUEST_SS_SELECTOR, ether_get_imaginary_sysenter_cs(v->domain)+8U);
__vmwrite(GUEST_SS_BASE, 0U);
__vmwrite(GUEST_SS_LIMIT, ~0U);
__vmwrite(GUEST_SS_AR_BYTES, 0xc093);
regs->eip = __vmread(GUEST_SYSENTER_EIP);
regs->esp = __vmread(GUEST_SYSENTER_ESP);
regs->eflags &= ~(EFLG_VM | EFLG_IF | EFLG_RF);
printk("Handle MSR_CS=[%lx %x] %lx [%lx %x]!!!\n",__vmread(GUEST_SYSENTER_CS), regs->cs,regs->eip, regs->esp, regs->ss);
}break;
case 0x35:
{
printk("sysexit n\n");
__vmwrite(GUEST_CS_SELECTOR, ether_get_imaginary_sysenter_cs(v->domain)+16U+0x3);
__vmwrite(GUEST_CS_BASE, 0U);
__vmwrite(GUEST_CS_LIMIT, ~0U);
__vmwrite(GUEST_CS_AR_BYTES, 0xc0fb);
__vmwrite(GUEST_SS_SELECTOR, ether_get_imaginary_sysenter_cs(v->domain)+24U+0x3);
__vmwrite(GUEST_SS_BASE, 0U);
__vmwrite(GUEST_SS_LIMIT, ~0U);
__vmwrite(GUEST_SS_AR_BYTES, 0xc0f3);
regs->eip=regs->edx;
regs->esp=regs->ecx;
break;
}
default:
{
break;
}
}
break;
}
Step 3) set MSR_SYSENTER_CS with Null segment selector(0) to raise a #GP by an hypercall
new_cs=0x0;
vmx_write_sysenter_msr(GUEST_SYSENTER_CS, new_cs);
--
Best Regards,
yandong