cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

vss-win32.c (4648B)


      1/*
      2 * QEMU Guest Agent VSS utility functions
      3 *
      4 * Copyright Hitachi Data Systems Corp. 2013
      5 *
      6 * Authors:
      7 *  Tomoki Sekiyama   <tomoki.sekiyama@hds.com>
      8 *
      9 * This work is licensed under the terms of the GNU GPL, version 2 or later.
     10 * See the COPYING file in the top-level directory.
     11 */
     12
     13#include "qemu/osdep.h"
     14#include <windows.h>
     15#include "qapi/error.h"
     16#include "qemu/error-report.h"
     17#include "guest-agent-core.h"
     18#include "vss-win32.h"
     19#include "vss-win32/requester.h"
     20
     21#define QGA_VSS_DLL "qga-vss.dll"
     22
     23static HMODULE provider_lib;
     24
     25/* Call a function in qga-vss.dll with the specified name */
     26static HRESULT call_vss_provider_func(const char *func_name)
     27{
     28    FARPROC WINAPI func;
     29
     30    g_assert(provider_lib);
     31
     32    func = GetProcAddress(provider_lib, func_name);
     33    if (!func) {
     34        char *msg;
     35        FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
     36                      FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
     37                      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
     38                      (char *)&msg, 0, NULL);
     39        fprintf(stderr, "failed to load %s from %s: %s",
     40                func_name, QGA_VSS_DLL, msg);
     41        LocalFree(msg);
     42        return E_FAIL;
     43    }
     44
     45    return func();
     46}
     47
     48/* Check whether this OS version supports VSS providers */
     49static bool vss_check_os_version(void)
     50{
     51    OSVERSIONINFO OSver;
     52
     53    OSver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
     54    GetVersionEx(&OSver);
     55    if ((OSver.dwMajorVersion == 5 && OSver.dwMinorVersion >= 2) ||
     56       OSver.dwMajorVersion > 5) {
     57        BOOL wow64 = false;
     58#ifndef _WIN64
     59        /* Provider doesn't work under WOW64 (32bit agent on 64bit OS) */
     60        if (!IsWow64Process(GetCurrentProcess(), &wow64)) {
     61            fprintf(stderr, "failed to IsWow64Process (Error: %lx\n)\n",
     62                    GetLastError());
     63            return false;
     64        }
     65        if (wow64) {
     66            warn_report("Running under WOW64");
     67        }
     68#endif
     69        return !wow64;
     70    }
     71    return false;
     72}
     73
     74/* Load qga-vss.dll */
     75bool vss_init(bool init_requester)
     76{
     77    if (!vss_check_os_version()) {
     78        /* Do nothing if OS doesn't support providers. */
     79        fprintf(stderr, "VSS provider is not supported in this OS version: "
     80                "fsfreeze is disabled.\n");
     81        return false;
     82    }
     83
     84    provider_lib = LoadLibraryA(QGA_VSS_DLL);
     85    if (!provider_lib) {
     86        char *msg;
     87        FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
     88                      FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
     89                      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
     90                      (char *)&msg, 0, NULL);
     91        fprintf(stderr, "failed to load %s: %sfsfreeze is disabled\n",
     92                QGA_VSS_DLL, msg);
     93        LocalFree(msg);
     94        return false;
     95    }
     96
     97    if (init_requester) {
     98        HRESULT hr = call_vss_provider_func("requester_init");
     99        if (FAILED(hr)) {
    100            fprintf(stderr, "fsfreeze is disabled.\n");
    101            vss_deinit(false);
    102            return false;
    103        }
    104    }
    105
    106    return true;
    107}
    108
    109/* Unload qga-provider.dll */
    110void vss_deinit(bool deinit_requester)
    111{
    112    if (deinit_requester) {
    113        call_vss_provider_func("requester_deinit");
    114    }
    115    FreeLibrary(provider_lib);
    116    provider_lib = NULL;
    117}
    118
    119bool vss_initialized(void)
    120{
    121    return !!provider_lib;
    122}
    123
    124int ga_install_vss_provider(void)
    125{
    126    HRESULT hr;
    127
    128    if (!vss_init(false)) {
    129        fprintf(stderr, "Installation of VSS provider is skipped. "
    130                "fsfreeze will be disabled.\n");
    131        return 0;
    132    }
    133    hr = call_vss_provider_func("COMRegister");
    134    vss_deinit(false);
    135
    136    return SUCCEEDED(hr) ? 0 : EXIT_FAILURE;
    137}
    138
    139void ga_uninstall_vss_provider(void)
    140{
    141    if (!vss_init(false)) {
    142        fprintf(stderr, "Removal of VSS provider is skipped.\n");
    143        return;
    144    }
    145    call_vss_provider_func("COMUnregister");
    146    vss_deinit(false);
    147}
    148
    149/* Call VSS requester and freeze/thaw filesystems and applications */
    150void qga_vss_fsfreeze(int *nr_volume, bool freeze,
    151                      strList *mountpoints, Error **errp)
    152{
    153    const char *func_name = freeze ? "requester_freeze" : "requester_thaw";
    154    QGAVSSRequesterFunc func;
    155    ErrorSet errset = {
    156        .error_setg_win32_wrapper = error_setg_win32_internal,
    157        .errp = errp,
    158    };
    159
    160    g_assert(errp);             /* requester.cpp requires it */
    161    func = (QGAVSSRequesterFunc)GetProcAddress(provider_lib, func_name);
    162    if (!func) {
    163        error_setg_win32(errp, GetLastError(), "failed to load %s from %s",
    164                         func_name, QGA_VSS_DLL);
    165        return;
    166    }
    167
    168    func(nr_volume, mountpoints, &errset);
    169}