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