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