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

commands.c (16579B)


      1/*
      2 * QEMU Guest Agent common/cross-platform command implementations
      3 *
      4 * Copyright IBM Corp. 2012
      5 *
      6 * Authors:
      7 *  Michael Roth      <mdroth@linux.vnet.ibm.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 "qemu/units.h"
     15#include "guest-agent-core.h"
     16#include "qga-qapi-commands.h"
     17#include "qapi/error.h"
     18#include "qapi/qmp/qerror.h"
     19#include "qemu/base64.h"
     20#include "qemu/cutils.h"
     21#include "qemu/atomic.h"
     22#include "commands-common.h"
     23
     24/* Maximum captured guest-exec out_data/err_data - 16MB */
     25#define GUEST_EXEC_MAX_OUTPUT (16 * 1024 * 1024)
     26/* Allocation and I/O buffer for reading guest-exec out_data/err_data - 4KB */
     27#define GUEST_EXEC_IO_SIZE (4 * 1024)
     28/*
     29 * Maximum file size to read - 48MB
     30 *
     31 * (48MB + Base64 3:4 overhead = JSON parser 64 MB limit)
     32 */
     33#define GUEST_FILE_READ_COUNT_MAX (48 * MiB)
     34
     35/* Note: in some situations, like with the fsfreeze, logging may be
     36 * temporarilly disabled. if it is necessary that a command be able
     37 * to log for accounting purposes, check ga_logging_enabled() beforehand,
     38 * and use the QERR_QGA_LOGGING_DISABLED to generate an error
     39 */
     40void slog(const gchar *fmt, ...)
     41{
     42    va_list ap;
     43
     44    va_start(ap, fmt);
     45    g_logv("syslog", G_LOG_LEVEL_INFO, fmt, ap);
     46    va_end(ap);
     47}
     48
     49int64_t qmp_guest_sync_delimited(int64_t id, Error **errp)
     50{
     51    ga_set_response_delimited(ga_state);
     52    return id;
     53}
     54
     55int64_t qmp_guest_sync(int64_t id, Error **errp)
     56{
     57    return id;
     58}
     59
     60void qmp_guest_ping(Error **errp)
     61{
     62    slog("guest-ping called");
     63}
     64
     65static void qmp_command_info(const QmpCommand *cmd, void *opaque)
     66{
     67    GuestAgentInfo *info = opaque;
     68    GuestAgentCommandInfo *cmd_info;
     69
     70    cmd_info = g_new0(GuestAgentCommandInfo, 1);
     71    cmd_info->name = g_strdup(qmp_command_name(cmd));
     72    cmd_info->enabled = qmp_command_is_enabled(cmd);
     73    cmd_info->success_response = qmp_has_success_response(cmd);
     74
     75    QAPI_LIST_PREPEND(info->supported_commands, cmd_info);
     76}
     77
     78struct GuestAgentInfo *qmp_guest_info(Error **errp)
     79{
     80    GuestAgentInfo *info = g_new0(GuestAgentInfo, 1);
     81
     82    info->version = g_strdup(QEMU_VERSION);
     83    qmp_for_each_command(&ga_commands, qmp_command_info, info);
     84    return info;
     85}
     86
     87struct GuestExecIOData {
     88    guchar *data;
     89    gsize size;
     90    gsize length;
     91    bool closed;
     92    bool truncated;
     93    const char *name;
     94};
     95typedef struct GuestExecIOData GuestExecIOData;
     96
     97struct GuestExecInfo {
     98    GPid pid;
     99    int64_t pid_numeric;
    100    gint status;
    101    bool has_output;
    102    bool finished;
    103    GuestExecIOData in;
    104    GuestExecIOData out;
    105    GuestExecIOData err;
    106    QTAILQ_ENTRY(GuestExecInfo) next;
    107};
    108typedef struct GuestExecInfo GuestExecInfo;
    109
    110static struct {
    111    QTAILQ_HEAD(, GuestExecInfo) processes;
    112} guest_exec_state = {
    113    .processes = QTAILQ_HEAD_INITIALIZER(guest_exec_state.processes),
    114};
    115
    116static int64_t gpid_to_int64(GPid pid)
    117{
    118#ifdef G_OS_WIN32
    119    return GetProcessId(pid);
    120#else
    121    return (int64_t)pid;
    122#endif
    123}
    124
    125static GuestExecInfo *guest_exec_info_add(GPid pid)
    126{
    127    GuestExecInfo *gei;
    128
    129    gei = g_new0(GuestExecInfo, 1);
    130    gei->pid = pid;
    131    gei->pid_numeric = gpid_to_int64(pid);
    132    QTAILQ_INSERT_TAIL(&guest_exec_state.processes, gei, next);
    133
    134    return gei;
    135}
    136
    137static GuestExecInfo *guest_exec_info_find(int64_t pid_numeric)
    138{
    139    GuestExecInfo *gei;
    140
    141    QTAILQ_FOREACH(gei, &guest_exec_state.processes, next) {
    142        if (gei->pid_numeric == pid_numeric) {
    143            return gei;
    144        }
    145    }
    146
    147    return NULL;
    148}
    149
    150GuestExecStatus *qmp_guest_exec_status(int64_t pid, Error **errp)
    151{
    152    GuestExecInfo *gei;
    153    GuestExecStatus *ges;
    154
    155    slog("guest-exec-status called, pid: %u", (uint32_t)pid);
    156
    157    gei = guest_exec_info_find(pid);
    158    if (gei == NULL) {
    159        error_setg(errp, QERR_INVALID_PARAMETER, "pid");
    160        return NULL;
    161    }
    162
    163    ges = g_new0(GuestExecStatus, 1);
    164
    165    bool finished = qatomic_mb_read(&gei->finished);
    166
    167    /* need to wait till output channels are closed
    168     * to be sure we captured all output at this point */
    169    if (gei->has_output) {
    170        finished = finished && qatomic_mb_read(&gei->out.closed);
    171        finished = finished && qatomic_mb_read(&gei->err.closed);
    172    }
    173
    174    ges->exited = finished;
    175    if (finished) {
    176        /* Glib has no portable way to parse exit status.
    177         * On UNIX, we can get either exit code from normal termination
    178         * or signal number.
    179         * On Windows, it is either the same exit code or the exception
    180         * value for an unhandled exception that caused the process
    181         * to terminate.
    182         * See MSDN for GetExitCodeProcess() and ntstatus.h for possible
    183         * well-known codes, e.g. C0000005 ACCESS_DENIED - analog of SIGSEGV
    184         * References:
    185         *   https://msdn.microsoft.com/en-us/library/windows/desktop/ms683189(v=vs.85).aspx
    186         *   https://msdn.microsoft.com/en-us/library/aa260331(v=vs.60).aspx
    187         */
    188#ifdef G_OS_WIN32
    189        /* Additionally WIN32 does not provide any additional information
    190         * on whether the child exited or terminated via signal.
    191         * We use this simple range check to distinguish application exit code
    192         * (usually value less then 256) and unhandled exception code with
    193         * ntstatus (always value greater then 0xC0000005). */
    194        if ((uint32_t)gei->status < 0xC0000000U) {
    195            ges->has_exitcode = true;
    196            ges->exitcode = gei->status;
    197        } else {
    198            ges->has_signal = true;
    199            ges->signal = gei->status;
    200        }
    201#else
    202        if (WIFEXITED(gei->status)) {
    203            ges->has_exitcode = true;
    204            ges->exitcode = WEXITSTATUS(gei->status);
    205        } else if (WIFSIGNALED(gei->status)) {
    206            ges->has_signal = true;
    207            ges->signal = WTERMSIG(gei->status);
    208        }
    209#endif
    210        if (gei->out.length > 0) {
    211            ges->has_out_data = true;
    212            ges->out_data = g_base64_encode(gei->out.data, gei->out.length);
    213            g_free(gei->out.data);
    214            ges->has_out_truncated = gei->out.truncated;
    215        }
    216
    217        if (gei->err.length > 0) {
    218            ges->has_err_data = true;
    219            ges->err_data = g_base64_encode(gei->err.data, gei->err.length);
    220            g_free(gei->err.data);
    221            ges->has_err_truncated = gei->err.truncated;
    222        }
    223
    224        QTAILQ_REMOVE(&guest_exec_state.processes, gei, next);
    225        g_free(gei);
    226    }
    227
    228    return ges;
    229}
    230
    231/* Get environment variables or arguments array for execve(). */
    232static char **guest_exec_get_args(const strList *entry, bool log)
    233{
    234    const strList *it;
    235    int count = 1, i = 0;  /* reserve for NULL terminator */
    236    char **args;
    237    char *str; /* for logging array of arguments */
    238    size_t str_size = 1;
    239
    240    for (it = entry; it != NULL; it = it->next) {
    241        count++;
    242        str_size += 1 + strlen(it->value);
    243    }
    244
    245    str = g_malloc(str_size);
    246    *str = 0;
    247    args = g_malloc(count * sizeof(char *));
    248    for (it = entry; it != NULL; it = it->next) {
    249        args[i++] = it->value;
    250        pstrcat(str, str_size, it->value);
    251        if (it->next) {
    252            pstrcat(str, str_size, " ");
    253        }
    254    }
    255    args[i] = NULL;
    256
    257    if (log) {
    258        slog("guest-exec called: \"%s\"", str);
    259    }
    260    g_free(str);
    261
    262    return args;
    263}
    264
    265static void guest_exec_child_watch(GPid pid, gint status, gpointer data)
    266{
    267    GuestExecInfo *gei = (GuestExecInfo *)data;
    268
    269    g_debug("guest_exec_child_watch called, pid: %d, status: %u",
    270            (int32_t)gpid_to_int64(pid), (uint32_t)status);
    271
    272    gei->status = status;
    273    qatomic_mb_set(&gei->finished, true);
    274
    275    g_spawn_close_pid(pid);
    276}
    277
    278/** Reset ignored signals back to default. */
    279static void guest_exec_task_setup(gpointer data)
    280{
    281#if !defined(G_OS_WIN32)
    282    struct sigaction sigact;
    283
    284    memset(&sigact, 0, sizeof(struct sigaction));
    285    sigact.sa_handler = SIG_DFL;
    286
    287    if (sigaction(SIGPIPE, &sigact, NULL) != 0) {
    288        slog("sigaction() failed to reset child process's SIGPIPE: %s",
    289             strerror(errno));
    290    }
    291#endif
    292}
    293
    294static gboolean guest_exec_input_watch(GIOChannel *ch,
    295        GIOCondition cond, gpointer p_)
    296{
    297    GuestExecIOData *p = (GuestExecIOData *)p_;
    298    gsize bytes_written = 0;
    299    GIOStatus status;
    300    GError *gerr = NULL;
    301
    302    /* nothing left to write */
    303    if (p->size == p->length) {
    304        goto done;
    305    }
    306
    307    status = g_io_channel_write_chars(ch, (gchar *)p->data + p->length,
    308            p->size - p->length, &bytes_written, &gerr);
    309
    310    /* can be not 0 even if not G_IO_STATUS_NORMAL */
    311    if (bytes_written != 0) {
    312        p->length += bytes_written;
    313    }
    314
    315    /* continue write, our callback will be called again */
    316    if (status == G_IO_STATUS_NORMAL || status == G_IO_STATUS_AGAIN) {
    317        return true;
    318    }
    319
    320    if (gerr) {
    321        g_warning("qga: i/o error writing to input_data channel: %s",
    322                gerr->message);
    323        g_error_free(gerr);
    324    }
    325
    326done:
    327    g_io_channel_shutdown(ch, true, NULL);
    328    g_io_channel_unref(ch);
    329    qatomic_mb_set(&p->closed, true);
    330    g_free(p->data);
    331
    332    return false;
    333}
    334
    335static gboolean guest_exec_output_watch(GIOChannel *ch,
    336        GIOCondition cond, gpointer p_)
    337{
    338    GuestExecIOData *p = (GuestExecIOData *)p_;
    339    gsize bytes_read;
    340    GIOStatus gstatus;
    341
    342    if (cond == G_IO_HUP || cond == G_IO_ERR) {
    343        goto close;
    344    }
    345
    346    if (p->size == p->length) {
    347        gpointer t = NULL;
    348        if (!p->truncated && p->size < GUEST_EXEC_MAX_OUTPUT) {
    349            t = g_try_realloc(p->data, p->size + GUEST_EXEC_IO_SIZE);
    350        }
    351        if (t == NULL) {
    352            /* ignore truncated output */
    353            gchar buf[GUEST_EXEC_IO_SIZE];
    354
    355            p->truncated = true;
    356            gstatus = g_io_channel_read_chars(ch, buf, sizeof(buf),
    357                                              &bytes_read, NULL);
    358            if (gstatus == G_IO_STATUS_EOF || gstatus == G_IO_STATUS_ERROR) {
    359                goto close;
    360            }
    361
    362            return true;
    363        }
    364        p->size += GUEST_EXEC_IO_SIZE;
    365        p->data = t;
    366    }
    367
    368    /* Calling read API once.
    369     * On next available data our callback will be called again */
    370    gstatus = g_io_channel_read_chars(ch, (gchar *)p->data + p->length,
    371            p->size - p->length, &bytes_read, NULL);
    372    if (gstatus == G_IO_STATUS_EOF || gstatus == G_IO_STATUS_ERROR) {
    373        goto close;
    374    }
    375
    376    p->length += bytes_read;
    377
    378    return true;
    379
    380close:
    381    g_io_channel_shutdown(ch, true, NULL);
    382    g_io_channel_unref(ch);
    383    qatomic_mb_set(&p->closed, true);
    384    return false;
    385}
    386
    387GuestExec *qmp_guest_exec(const char *path,
    388                       bool has_arg, strList *arg,
    389                       bool has_env, strList *env,
    390                       bool has_input_data, const char *input_data,
    391                       bool has_capture_output, bool capture_output,
    392                       Error **errp)
    393{
    394    GPid pid;
    395    GuestExec *ge = NULL;
    396    GuestExecInfo *gei;
    397    char **argv, **envp;
    398    strList arglist;
    399    gboolean ret;
    400    GError *gerr = NULL;
    401    gint in_fd, out_fd, err_fd;
    402    GIOChannel *in_ch, *out_ch, *err_ch;
    403    GSpawnFlags flags;
    404    bool has_output = (has_capture_output && capture_output);
    405    g_autofree uint8_t *input = NULL;
    406    size_t ninput = 0;
    407
    408    arglist.value = (char *)path;
    409    arglist.next = has_arg ? arg : NULL;
    410
    411    if (has_input_data) {
    412        input = qbase64_decode(input_data, -1, &ninput, errp);
    413        if (!input) {
    414            return NULL;
    415        }
    416    }
    417
    418    argv = guest_exec_get_args(&arglist, true);
    419    envp = has_env ? guest_exec_get_args(env, false) : NULL;
    420
    421    flags = G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD |
    422        G_SPAWN_SEARCH_PATH_FROM_ENVP;
    423    if (!has_output) {
    424        flags |= G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL;
    425    }
    426
    427    ret = g_spawn_async_with_pipes(NULL, argv, envp, flags,
    428            guest_exec_task_setup, NULL, &pid, has_input_data ? &in_fd : NULL,
    429            has_output ? &out_fd : NULL, has_output ? &err_fd : NULL, &gerr);
    430    if (!ret) {
    431        error_setg(errp, QERR_QGA_COMMAND_FAILED, gerr->message);
    432        g_error_free(gerr);
    433        goto done;
    434    }
    435
    436    ge = g_new0(GuestExec, 1);
    437    ge->pid = gpid_to_int64(pid);
    438
    439    gei = guest_exec_info_add(pid);
    440    gei->has_output = has_output;
    441    g_child_watch_add(pid, guest_exec_child_watch, gei);
    442
    443    if (has_input_data) {
    444        gei->in.data = g_steal_pointer(&input);
    445        gei->in.size = ninput;
    446#ifdef G_OS_WIN32
    447        in_ch = g_io_channel_win32_new_fd(in_fd);
    448#else
    449        in_ch = g_io_channel_unix_new(in_fd);
    450#endif
    451        g_io_channel_set_encoding(in_ch, NULL, NULL);
    452        g_io_channel_set_buffered(in_ch, false);
    453        g_io_channel_set_flags(in_ch, G_IO_FLAG_NONBLOCK, NULL);
    454        g_io_channel_set_close_on_unref(in_ch, true);
    455        g_io_add_watch(in_ch, G_IO_OUT, guest_exec_input_watch, &gei->in);
    456    }
    457
    458    if (has_output) {
    459#ifdef G_OS_WIN32
    460        out_ch = g_io_channel_win32_new_fd(out_fd);
    461        err_ch = g_io_channel_win32_new_fd(err_fd);
    462#else
    463        out_ch = g_io_channel_unix_new(out_fd);
    464        err_ch = g_io_channel_unix_new(err_fd);
    465#endif
    466        g_io_channel_set_encoding(out_ch, NULL, NULL);
    467        g_io_channel_set_encoding(err_ch, NULL, NULL);
    468        g_io_channel_set_buffered(out_ch, false);
    469        g_io_channel_set_buffered(err_ch, false);
    470        g_io_channel_set_close_on_unref(out_ch, true);
    471        g_io_channel_set_close_on_unref(err_ch, true);
    472        g_io_add_watch(out_ch, G_IO_IN | G_IO_HUP,
    473                guest_exec_output_watch, &gei->out);
    474        g_io_add_watch(err_ch, G_IO_IN | G_IO_HUP,
    475                guest_exec_output_watch, &gei->err);
    476    }
    477
    478done:
    479    g_free(argv);
    480    g_free(envp);
    481
    482    return ge;
    483}
    484
    485/* Convert GuestFileWhence (either a raw integer or an enum value) into
    486 * the guest's SEEK_ constants.  */
    487int ga_parse_whence(GuestFileWhence *whence, Error **errp)
    488{
    489    /*
    490     * Exploit the fact that we picked values to match QGA_SEEK_*;
    491     * however, we have to use a temporary variable since the union
    492     * members may have different size.
    493     */
    494    if (whence->type == QTYPE_QSTRING) {
    495        int value = whence->u.name;
    496        whence->type = QTYPE_QNUM;
    497        whence->u.value = value;
    498    }
    499    switch (whence->u.value) {
    500    case QGA_SEEK_SET:
    501        return SEEK_SET;
    502    case QGA_SEEK_CUR:
    503        return SEEK_CUR;
    504    case QGA_SEEK_END:
    505        return SEEK_END;
    506    }
    507    error_setg(errp, "invalid whence code %"PRId64, whence->u.value);
    508    return -1;
    509}
    510
    511GuestHostName *qmp_guest_get_host_name(Error **errp)
    512{
    513    GuestHostName *result = NULL;
    514    g_autofree char *hostname = qemu_get_host_name(errp);
    515
    516    /*
    517     * We want to avoid using g_get_host_name() because that
    518     * caches the result and we wouldn't reflect changes in the
    519     * host name.
    520     */
    521
    522    if (!hostname) {
    523        hostname = g_strdup("localhost");
    524    }
    525
    526    result = g_new0(GuestHostName, 1);
    527    result->host_name = g_steal_pointer(&hostname);
    528    return result;
    529}
    530
    531GuestTimezone *qmp_guest_get_timezone(Error **errp)
    532{
    533    GuestTimezone *info = NULL;
    534    GTimeZone *tz = NULL;
    535    gint64 now = 0;
    536    gint32 intv = 0;
    537    gchar const *name = NULL;
    538
    539    info = g_new0(GuestTimezone, 1);
    540    tz = g_time_zone_new_local();
    541    if (tz == NULL) {
    542        error_setg(errp, QERR_QGA_COMMAND_FAILED,
    543                   "Couldn't retrieve local timezone");
    544        goto error;
    545    }
    546
    547    now = g_get_real_time() / G_USEC_PER_SEC;
    548    intv = g_time_zone_find_interval(tz, G_TIME_TYPE_UNIVERSAL, now);
    549    info->offset = g_time_zone_get_offset(tz, intv);
    550    name = g_time_zone_get_abbreviation(tz, intv);
    551    if (name != NULL) {
    552        info->has_zone = true;
    553        info->zone = g_strdup(name);
    554    }
    555    g_time_zone_unref(tz);
    556
    557    return info;
    558
    559error:
    560    g_free(info);
    561    return NULL;
    562}
    563
    564GuestFileRead *qmp_guest_file_read(int64_t handle, bool has_count,
    565                                   int64_t count, Error **errp)
    566{
    567    GuestFileHandle *gfh = guest_file_handle_find(handle, errp);
    568    GuestFileRead *read_data;
    569
    570    if (!gfh) {
    571        return NULL;
    572    }
    573    if (!has_count) {
    574        count = QGA_READ_COUNT_DEFAULT;
    575    } else if (count < 0 || count > GUEST_FILE_READ_COUNT_MAX) {
    576        error_setg(errp, "value '%" PRId64 "' is invalid for argument count",
    577                   count);
    578        return NULL;
    579    }
    580
    581    read_data = guest_file_read_unsafe(gfh, count, errp);
    582    if (!read_data) {
    583        slog("guest-file-write failed, handle: %" PRId64, handle);
    584    }
    585
    586    return read_data;
    587}