Esempio n. 1
0
status_t linux_init (vmi_instance_t vmi)
{
    status_t ret = VMI_FAILURE;

    if (vmi->cr3){
        vmi->kpgd = vmi->cr3;
    }
    else if (VMI_SUCCESS == linux_system_map_symbol_to_address(vmi, "swapper_pg_dir", &vmi->kpgd)){
        dbprint("--got vaddr for swapper_pg_dir (0x%.16llx).\n", vmi->kpgd);
        if (driver_is_pv(vmi)){
            vmi->kpgd = vmi_translate_kv2p(vmi, vmi->kpgd);
            if (vmi_read_addr_pa(vmi, vmi->kpgd, &(vmi->kpgd)) == VMI_FAILURE){
                errprint("Failed to get physical addr for kpgd.\n");
                goto _exit;
            }
        }
        else{
            vmi->kpgd = vmi_translate_kv2p(vmi, vmi->kpgd);
        }
    }
    else{
        errprint("swapper_pg_dir not found and CR3 not set, exiting\n");
        goto _exit;
    }

    vmi->kpgd = vmi->cr3;
    dbprint("**set vmi->kpgd (0x%.16llx).\n", vmi->kpgd);

    addr_t address = vmi_translate_ksym2v(vmi, "init_task");
    address += vmi->os.linux_instance.tasks_offset;
    if (VMI_FAILURE == vmi_read_addr_va(vmi, address, 0, &(vmi->init_task))){
        errprint("Failed to get task list head 'init_task'.\n");
        goto _exit;
    }

    ret = VMI_SUCCESS;
_exit:
    return ret;
}
Esempio n. 2
0
/*
 * check that this vm uses a paging method that we support
 * and set pm/cr3/pae/pse/lme flags optionally on the given pointers
 */
status_t probe_memory_layout_x86(vmi_instance_t vmi) {
    // To get the paging layout, the following bits are needed:
    // 1. CR0.PG
    // 2. CR4.PAE
    // 3. Either (a) IA32_EFER.LME, or (b) the guest's address width (32 or
    //    64). Not all backends allow us to read an MSR; in particular, Xen's PV
    //    backend doessn't.

    status_t ret = VMI_FAILURE;
    page_mode_t pm = VMI_PM_UNKNOWN;
    uint8_t dom_addr_width = 0; // domain address width (bytes)

    /* pull info from registers, if we can */
    reg_t cr0, cr3, cr4, efer;
    int pae = 0, pse = 0, lme = 0;
    uint8_t msr_efer_lme = 0;   // LME bit in MSR_EFER

    /* get the control register values */
    if (driver_get_vcpureg(vmi, &cr0, CR0, 0) == VMI_FAILURE) {
        errprint("**failed to get CR0\n");
        goto _exit;
    }

    /* PG Flag --> CR0, bit 31 == 1 --> paging enabled */
    if (!VMI_GET_BIT(cr0, 31)) {
        dbprint(VMI_DEBUG_CORE, "Paging disabled for this VM, only physical addresses supported.\n");
        vmi->page_mode = VMI_PM_UNKNOWN;
        vmi->pae = 0;
        vmi->pse = 0;
        vmi->lme = 0;

        ret = VMI_SUCCESS;
        goto _exit;
    }

    //
    // Paging enabled (PG==1)
    //
    if (driver_get_vcpureg(vmi, &cr4, CR4, 0) == VMI_FAILURE) {
        errprint("**failed to get CR4\n");
        goto _exit;
    }

    /* PSE Flag --> CR4, bit 5 */
    pae = VMI_GET_BIT(cr4, 5);
    dbprint(VMI_DEBUG_CORE, "**set pae = %d\n", pae);

    /* PSE Flag --> CR4, bit 4 */
    pse = VMI_GET_BIT(cr4, 4);
    dbprint(VMI_DEBUG_CORE, "**set pse = %d\n", pse);

    ret = driver_get_vcpureg(vmi, &efer, MSR_EFER, 0);
    if (VMI_SUCCESS == ret) {
        lme = VMI_GET_BIT(efer, 8);
        dbprint(VMI_DEBUG_CORE, "**set lme = %d\n", lme);
    } else {
        dbprint(VMI_DEBUG_CORE, "**failed to get MSR_EFER, trying method #2\n");

        // does this trick work in all cases?
        ret = driver_get_address_width(vmi, &dom_addr_width);
        if (VMI_FAILURE == ret) {
            errprint
                ("Failed to get domain address width. Giving up.\n");
            goto _exit;
        }
        lme = (8 == dom_addr_width);
        dbprint
            (VMI_DEBUG_CORE, "**found guest address width is %d bytes; assuming IA32_EFER.LME = %d\n",
             dom_addr_width, lme);
    }   // if
    // Get current cr3 for sanity checking
    if (driver_get_vcpureg(vmi, &cr3, CR3, 0) == VMI_FAILURE) {
        errprint("**failed to get CR3\n");
        goto _exit;
    }

    // now determine addressing mode
    if (0 == pae) {
        dbprint(VMI_DEBUG_CORE, "**32-bit paging\n");
        pm = VMI_PM_LEGACY;
        cr3 &= 0xFFFFF000ull;
    }
    // PAE == 1; determine IA-32e or PAE
    else if (lme) {    // PAE == 1, LME == 1
        dbprint(VMI_DEBUG_CORE, "**IA-32e paging\n");
        pm = VMI_PM_IA32E;
        cr3 &= 0xFFFFFFFFFFFFF000ull;
    } else {  // PAE == 1, LME == 0
        dbprint(VMI_DEBUG_CORE, "**PAE paging\n");
        pm = VMI_PM_PAE;
        cr3 &= 0xFFFFFFE0;
    }   // if-else
    dbprint(VMI_DEBUG_CORE, "**sanity checking cr3 = 0x%.16"PRIx64"\n", cr3);

    /* testing to see CR3 value */
    if (!driver_is_pv(vmi) && cr3 >= vmi->max_physical_address) {   // sanity check on CR3
        dbprint(VMI_DEBUG_CORE, "** Note cr3 value [0x%"PRIx64"] exceeds memsize [0x%"PRIx64"]\n",
                cr3, vmi->size);
    }

    vmi->page_mode = pm;
    vmi->pae = pae;
    vmi->pse = pse;
    vmi->lme = lme;

_exit:
    return ret;
}
Esempio n. 3
0
status_t linux_init(vmi_instance_t vmi) {
    status_t ret = VMI_FAILURE;
    os_interface_t os_interface = NULL;

    if (vmi->config == NULL) {
        errprint("VMI_ERROR: No config table found\n");
        return VMI_FAILURE;
    }

    if (vmi->os_data != NULL) {
        errprint("VMI_ERROR: os data already initialized, reinitializing\n");
        free(vmi->os_data);
    }

    vmi->os_data = safe_malloc(sizeof(struct linux_instance));
    bzero(vmi->os_data, sizeof(struct linux_instance));

    g_hash_table_foreach(vmi->config, (GHFunc)linux_read_config_ghashtable_entries, vmi);

    if (VMI_SUCCESS
            == linux_system_map_symbol_to_address(vmi, "swapper_pg_dir", NULL,
                    &vmi->kpgd)) {
        dbprint("--got vaddr for swapper_pg_dir (0x%.16"PRIx64").\n",
                vmi->kpgd);
        if (driver_is_pv(vmi)) {
            vmi->kpgd = vmi_translate_kv2p(vmi, vmi->kpgd);
            if (vmi_read_addr_pa(vmi, vmi->kpgd, &(vmi->kpgd)) == VMI_FAILURE) {
                errprint(
                        "Failed to get physical addr for kpgd using swapper_pg_dir.\n");
            }
        }
    }

    if (!vmi->kpgd) {
        ret = driver_get_vcpureg(vmi, &vmi->kpgd, CR3, 0);
        if (ret != VMI_SUCCESS) {
            errprint(
                    "Driver does not support cr3 read and kpgd could not be set, exiting\n");
            goto _exit;
        }
    }

    dbprint("**set vmi->kpgd (0x%.16"PRIx64").\n", vmi->kpgd);

    ret = linux_system_map_symbol_to_address(vmi, "init_task", NULL,
            &vmi->init_task);
    if (ret != VMI_SUCCESS) {
        errprint("VMI_ERROR: Could not get init_task from System.map\n");
        return ret;
    }

    os_interface = safe_malloc(sizeof(struct os_interface));
    bzero(os_interface, sizeof(struct os_interface));
    os_interface->os_get_offset = linux_get_offset;
    os_interface->os_pid_to_pgd = linux_pid_to_pgd;
    os_interface->os_pgd_to_pid = linux_pgd_to_pid;
    os_interface->os_ksym2v = linux_system_map_symbol_to_address;
    os_interface->os_usym2rva = NULL;
    os_interface->os_rva2sym = NULL;
    os_interface->os_teardown = linux_teardown;

    vmi->os_interface = os_interface;

    _exit: return ret;
}