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

char-stdio.c (4589B)


      1/*
      2 * QEMU System Emulator
      3 *
      4 * Copyright (c) 2003-2008 Fabrice Bellard
      5 *
      6 * Permission is hereby granted, free of charge, to any person obtaining a copy
      7 * of this software and associated documentation files (the "Software"), to deal
      8 * in the Software without restriction, including without limitation the rights
      9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     10 * copies of the Software, and to permit persons to whom the Software is
     11 * furnished to do so, subject to the following conditions:
     12 *
     13 * The above copyright notice and this permission notice shall be included in
     14 * all copies or substantial portions of the Software.
     15 *
     16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     22 * THE SOFTWARE.
     23 */
     24
     25#include "qemu/osdep.h"
     26#include "qemu/module.h"
     27#include "qemu/option.h"
     28#include "qemu/sockets.h"
     29#include "qapi/error.h"
     30#include "chardev/char.h"
     31
     32#ifdef _WIN32
     33#include "chardev/char-win.h"
     34#include "chardev/char-win-stdio.h"
     35#else
     36#include <termios.h>
     37#include "chardev/char-fd.h"
     38#endif
     39
     40#ifndef _WIN32
     41/* init terminal so that we can grab keys */
     42static struct termios oldtty;
     43static int old_fd0_flags;
     44static bool stdio_in_use;
     45static bool stdio_allow_signal;
     46static bool stdio_echo_state;
     47
     48static void term_exit(void)
     49{
     50    if (stdio_in_use) {
     51        tcsetattr(0, TCSANOW, &oldtty);
     52        fcntl(0, F_SETFL, old_fd0_flags);
     53    }
     54}
     55
     56static void qemu_chr_set_echo_stdio(Chardev *chr, bool echo)
     57{
     58    struct termios tty;
     59
     60    stdio_echo_state = echo;
     61    tty = oldtty;
     62    if (!echo) {
     63        tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
     64                         | INLCR | IGNCR | ICRNL | IXON);
     65        tty.c_oflag |= OPOST;
     66        tty.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN);
     67        tty.c_cflag &= ~(CSIZE | PARENB);
     68        tty.c_cflag |= CS8;
     69        tty.c_cc[VMIN] = 1;
     70        tty.c_cc[VTIME] = 0;
     71    }
     72    if (!stdio_allow_signal) {
     73        tty.c_lflag &= ~ISIG;
     74    }
     75
     76    tcsetattr(0, TCSANOW, &tty);
     77}
     78
     79static void term_stdio_handler(int sig)
     80{
     81    /* restore echo after resume from suspend. */
     82    qemu_chr_set_echo_stdio(NULL, stdio_echo_state);
     83}
     84
     85static void qemu_chr_open_stdio(Chardev *chr,
     86                                ChardevBackend *backend,
     87                                bool *be_opened,
     88                                Error **errp)
     89{
     90    ChardevStdio *opts = backend->u.stdio.data;
     91    struct sigaction act;
     92
     93    if (is_daemonized()) {
     94        error_setg(errp, "cannot use stdio with -daemonize");
     95        return;
     96    }
     97
     98    if (stdio_in_use) {
     99        error_setg(errp, "cannot use stdio by multiple character devices");
    100        return;
    101    }
    102
    103    stdio_in_use = true;
    104    old_fd0_flags = fcntl(0, F_GETFL);
    105    tcgetattr(0, &oldtty);
    106    qemu_set_nonblock(0);
    107    atexit(term_exit);
    108
    109    memset(&act, 0, sizeof(act));
    110    act.sa_handler = term_stdio_handler;
    111    sigaction(SIGCONT, &act, NULL);
    112
    113    qemu_chr_open_fd(chr, 0, 1);
    114
    115    stdio_allow_signal = !opts->has_signal || opts->signal;
    116    qemu_chr_set_echo_stdio(chr, false);
    117}
    118#endif
    119
    120static void qemu_chr_parse_stdio(QemuOpts *opts, ChardevBackend *backend,
    121                                 Error **errp)
    122{
    123    ChardevStdio *stdio;
    124
    125    backend->type = CHARDEV_BACKEND_KIND_STDIO;
    126    stdio = backend->u.stdio.data = g_new0(ChardevStdio, 1);
    127    qemu_chr_parse_common(opts, qapi_ChardevStdio_base(stdio));
    128    stdio->has_signal = true;
    129    stdio->signal = qemu_opt_get_bool(opts, "signal", true);
    130}
    131
    132static void char_stdio_class_init(ObjectClass *oc, void *data)
    133{
    134    ChardevClass *cc = CHARDEV_CLASS(oc);
    135
    136    cc->parse = qemu_chr_parse_stdio;
    137#ifndef _WIN32
    138    cc->open = qemu_chr_open_stdio;
    139    cc->chr_set_echo = qemu_chr_set_echo_stdio;
    140#endif
    141}
    142
    143static void char_stdio_finalize(Object *obj)
    144{
    145#ifndef _WIN32
    146    term_exit();
    147#endif
    148}
    149
    150static const TypeInfo char_stdio_type_info = {
    151    .name = TYPE_CHARDEV_STDIO,
    152#ifdef _WIN32
    153    .parent = TYPE_CHARDEV_WIN_STDIO,
    154#else
    155    .parent = TYPE_CHARDEV_FD,
    156#endif
    157    .instance_finalize = char_stdio_finalize,
    158    .class_init = char_stdio_class_init,
    159};
    160
    161static void register_types(void)
    162{
    163    type_register_static(&char_stdio_type_info);
    164}
    165
    166type_init(register_types);