Skip to content

Can't use KVMi functionality from QEMU monitor commands #171

@Zhuzhzhalka

Description

@Zhuzhzhalka

I'm trying to implement some KVMi based introspection functionality from the QEMU monitor itself: under qmp and hmp commands. That is - booting a KVMi-patched QEMU instance, connecting to its monitor, typing a monitor command and get some implemented introspection results.

QEMU extra args:

-cpu host,kvm=off,migratable=off -chardev socket,path=/tmp/introspector,id=chardev0,reconnect=10 -object introspection,id=kvmi,chardev=chardev0 \

However, when executing the custom qmp command, something hangs in KVMi initialization process - seems to be related to Unix socket.

--found KVM
LibVMI Version 0.13.0
LibVMI Driver Mode 1
--libkvmi path: /usr/local/lib/libkvmi.so
--completed driver init.
--got name from id (1 --> kvmi)
**set image_type = kvmi
--KVMi socket path: /tmp/introspector
--Connecting to KVMI...
--KVMI failed
--Destroying KVM driver

Wait condition timeouts in this fragment of libvmi code:

    kvm->kvmi = kvm->libkvmi.kvmi_init_unix_socket(sock_path, new_guest_cb, handshake_cb, kvm);
    if (kvm->kvmi) {
        struct timeval now;
        if (gettimeofday(&now, NULL) == 0) {
            struct timespec t = {};
            t.tv_sec = now.tv_sec + 10;
            err = pthread_cond_timedwait(&kvm->kvm_start_cond, &kvm->kvm_connect_mutex, &t);
        }
    }

Checked that and turns out poll() doesn't succeed inside accept_worker() in libkvmi.

Custom qmp command implementation uses standard libvmi initialization mechanism:

VmiStatus *qmp_init_vmi(Error **errp)
{
    uint8_t init = VMI_INIT_DOMAINID;
    uint8_t config_type = VMI_CONFIG_JSON_PATH;
    char socket_path[] = "/tmp/introspector";
    struct VmiStatus *status = g_malloc0(sizeof(*status));
    vmi_instance_t *vmi = g_malloc0(sizeof(*vmi));
    uint64_t domid = 1;
    void *input = &domid;
    void *config = g_strndup("/tmp/profile.json", 17);
    vmi_init_data_t *init_data = g_malloc0(sizeof(vmi_init_data_t) + sizeof(vmi_init_data_entry_t));

    init_data->count = 1;
    init_data->entry[0].type = VMI_INIT_DATA_KVMI_SOCKET;
    init_data->entry[0].data = g_strndup(socket_path, sizeof(socket_path));

    status->status = vmi_init_complete(vmi, input, init, init_data, config_type, config, NULL);

    return status;
}

I've followed the instructions from https://kvm-vmi.github.io/kvm-vmi/master/setup.html for bare-metal setup. Everything is fine - all the examples work. Moreover, when executing the exact same libvmi-interacting code (which I wrote for qmp function) as a separate program, everything initializes and works correctly.

--found KVM
LibVMI Version 0.13.0
LibVMI Driver Mode 1
--libkvmi path: /usr/local/lib/libkvmi.so
--completed driver init.
--got name from id (1 --> kvmi)
**set image_type = kvmi
--KVMi socket path: /tmp/introspector
--Connecting to KVMI...
--KVMi handshake:
--    VM name: 
--    VM start time: 23:21:04 - Fri Jan 02 1970
--KVMi new guest:
--    UUID: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
--    FD: 6
--    Protocol version: 1
--KVMi features:
--    VMFUNC: Yes
--    EPTP: Yes
--    VE: Yes
--    SPP: No
--KVMI connected
--VCPU count: 4

I wonder if it is actually possible to use KVMi from inside QEMU monitor commands or it is impossible by design (maybe KVMi relies on the same QEMU functionality and it somehow deadlocks while handshaking)?

Please let me know if there is extra information I can provide you.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions