KVM-VMI / kvm-vmi

KVM-based Virtual Machine Introspection
https://kvm-vmi.github.io/kvm-vmi/master/
301 stars 61 forks source link

can 't use kvm_vm_ioctl #109

Open wangbaba523 opened 3 years ago

wangbaba523 commented 3 years ago

hi,I don't want to use PathToSocket, so I didn't add

<........> to the XML file. But,In order to use "KVM_INTROSPECTION_HOOK", I am in kvm_dev_ioctl add nitro of "KVM_NITRO_ATTACH_VM" to get the fd communicating with VM, But when we use this fd to communicate with VM, we can 't in kvm_vm_ioctl, could you tell me what's wrong, or how can I add it. Thanks!
Wenzel commented 3 years ago

hi @wangbaba523 ,

If I'm not mistaken, KVM_INTROSPECTION_HOOK refers to the bitdefender KVMI subsystem, the new API that is currently maintained by this project

KVM_NITRO_ATTACH_VM is refering to the Nitro project for syscall interception, which is now deprecated. You can't use both at the same time

wangbaba523 commented 3 years ago

hi @wangbaba523 ,

If I'm not mistaken, KVM_INTROSPECTION_HOOK refers to the bitdefender KVMI subsystem, the new API that is currently maintained by this project

KVM_NITRO_ATTACH_VM is refering to the Nitro project for syscall interception, which is now deprecated. You can't use both at the same time

yes,I know,I add the nitro code in KVMI subsystem to support it ,in kvm_dev_ioctl add case KVM_VMI_ATTACH_VM:

    r = -EFAULT;
    if(copy_from_user(&creator, argp, sizeof(pid_t)))
        goto out;
    r = -ESRCH;

    kvm = kvmi_get_vm_by_creator(creator);
    if(kvm == NULL)
        goto out;
    kvm_get_kvm(kvm);
    r = anon_inode_getfd("kvm-vm", &kvm_vm_fops, kvm, O_RDWR | O_CLOEXEC);

    if(r<0)
        kvm_put_kvm(kvm);

    break;
adlazar commented 3 years ago

@wangbaba523, can you show kvmi_get_vm_by_creator() ?

wangbaba523 commented 3 years ago

/ This function uses “/var/run/libvirt/qemu/vm.pid” to find the kvm structure of the corresponding virtual machine /

struct kvm kvmi_get_vm_by_creator(pid_t creator) { struct kvm rv; struct kvm *kvm;

rv = NULL;

spin_lock(&kvm_lock); list_for_each_entry(kvm,&vm_list,vm_list) if(kvm->mm->owner->pid == creator){ rv = kvm; break; } spin_unlock(&kvm_lock);

return rv; }

adlazar commented 3 years ago

The KVMi subsystem uses a socket. On one side of this socket is the QEMU process of the introspected guest + the kernel (KVM) and on the other side is the introspection tool.

QEMU initiates the connection by writing and reading during a simple handshake (see handshake header). After this, the socket is handed over to KVM, where the KVMi subsystem will use a couple of socket specific functions (see kvmi_msg.c for sock_fd_lookup(), sock_fd_put(), kernel_sock_shutdown(), kernel_recvmsg(), kernel_sendmsg()).

You'll have to replace the code using the socket functions (from QEMU and KVMi) if you still want to use the KVMi API without a socket.

wangbaba523 commented 3 years ago

Thank you for your reply,but how to call the case of "KVM_INTROSPECTION_HOOK"

in kvmi-v7 /virt/kvm/kvm_main.c case KVM_INTROSPECTION_HOOK: if (enable_introspection) r = kvmi_ioctl_hook(kvm, argp); else r = -EPERM; break;

adlazar commented 3 years ago

I don't know how would you combine Nitro and KVMi.

You said that you don't want to use a socket. I assumed you will replace it with another "channel".

wangbaba523 commented 3 years ago

In short, i want to use the function of ..... struct kvm_introspection_hook i; ioctl(vmfd, KVM_INTROSPECTION_HOOK, &i); ...... in my vmi process.but there can' t find vmfd, So I added nitro code to get vmfd.

adlazar commented 3 years ago

Do you want to use QEMU to run your introspected VMs or something else? Because the kvm-vmi/qemu project (kvmi-v7 branch) has all that you might need. In your code, vmfd is the file descriptor returned by ioctl/KVM_CREATE_VM (kvm_state from QEMU code).

Wenzel commented 3 years ago

@wangbaba523 from what I understand you are trying to use both Nitro and KVMi and these are 2 incompatibles APIs.

What you need to do is to rebuild the Nitro capabilities on top of the KVMi API. Nitro was capable of trapping syscall automatically, by forcing a VM-exit on the syscall/sysret and sysenter/sysexit instructions.

You will need to setup a breakpoint system manually and figure out where the syscall entrypoint and exitpoints are, insert them and reconstruct the semantic context.

I'm not maintaining Nitro anymore.

I hope this helps