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

helper.c (15101B)


      1/*
      2 * FUSE: Filesystem in Userspace
      3 * Copyright (C) 2001-2007  Miklos Szeredi <miklos@szeredi.hu>
      4 *
      5 * Helper functions to create (simple) standalone programs. With the
      6 * aid of these functions it should be possible to create full FUSE
      7 * file system by implementing nothing but the request handlers.
      8
      9 * This program can be distributed under the terms of the GNU LGPLv2.
     10 * See the file COPYING.LIB.
     11 */
     12
     13#include "qemu/osdep.h"
     14#include "fuse_i.h"
     15#include "fuse_lowlevel.h"
     16#include "fuse_misc.h"
     17#include "fuse_opt.h"
     18
     19#include <sys/param.h>
     20#include <sys/resource.h>
     21
     22#define FUSE_HELPER_OPT(t, p)                       \
     23    {                                               \
     24        t, offsetof(struct fuse_cmdline_opts, p), 1 \
     25    }
     26#define FUSE_HELPER_OPT_VALUE(t, p, v)              \
     27    {                                               \
     28        t, offsetof(struct fuse_cmdline_opts, p), v \
     29    }
     30
     31static const struct fuse_opt fuse_helper_opts[] = {
     32    FUSE_HELPER_OPT("-h", show_help),
     33    FUSE_HELPER_OPT("--help", show_help),
     34    FUSE_HELPER_OPT("-V", show_version),
     35    FUSE_HELPER_OPT("--version", show_version),
     36    FUSE_HELPER_OPT("--print-capabilities", print_capabilities),
     37    FUSE_HELPER_OPT("-d", debug),
     38    FUSE_HELPER_OPT("debug", debug),
     39    FUSE_HELPER_OPT("-d", foreground),
     40    FUSE_HELPER_OPT("debug", foreground),
     41    FUSE_OPT_KEY("-d", FUSE_OPT_KEY_KEEP),
     42    FUSE_OPT_KEY("debug", FUSE_OPT_KEY_KEEP),
     43    FUSE_HELPER_OPT("-f", foreground),
     44    FUSE_HELPER_OPT_VALUE("--daemonize", foreground, 0),
     45    FUSE_HELPER_OPT("fsname=", nodefault_subtype),
     46    FUSE_OPT_KEY("fsname=", FUSE_OPT_KEY_KEEP),
     47    FUSE_HELPER_OPT("subtype=", nodefault_subtype),
     48    FUSE_OPT_KEY("subtype=", FUSE_OPT_KEY_KEEP),
     49    FUSE_HELPER_OPT("max_idle_threads=%u", max_idle_threads),
     50    FUSE_HELPER_OPT("--rlimit-nofile=%lu", rlimit_nofile),
     51    FUSE_HELPER_OPT("--syslog", syslog),
     52    FUSE_HELPER_OPT_VALUE("log_level=debug", log_level, FUSE_LOG_DEBUG),
     53    FUSE_HELPER_OPT_VALUE("log_level=info", log_level, FUSE_LOG_INFO),
     54    FUSE_HELPER_OPT_VALUE("log_level=warn", log_level, FUSE_LOG_WARNING),
     55    FUSE_HELPER_OPT_VALUE("log_level=err", log_level, FUSE_LOG_ERR),
     56    FUSE_OPT_END
     57};
     58
     59struct fuse_conn_info_opts {
     60    int atomic_o_trunc;
     61    int no_remote_posix_lock;
     62    int no_remote_flock;
     63    int splice_write;
     64    int splice_move;
     65    int splice_read;
     66    int no_splice_write;
     67    int no_splice_move;
     68    int no_splice_read;
     69    int auto_inval_data;
     70    int no_auto_inval_data;
     71    int no_readdirplus;
     72    int no_readdirplus_auto;
     73    int async_dio;
     74    int no_async_dio;
     75    int writeback_cache;
     76    int no_writeback_cache;
     77    int async_read;
     78    int sync_read;
     79    unsigned max_write;
     80    unsigned max_readahead;
     81    unsigned max_background;
     82    unsigned congestion_threshold;
     83    unsigned time_gran;
     84    int set_max_write;
     85    int set_max_readahead;
     86    int set_max_background;
     87    int set_congestion_threshold;
     88    int set_time_gran;
     89};
     90
     91#define CONN_OPTION(t, p, v)                          \
     92    {                                                 \
     93        t, offsetof(struct fuse_conn_info_opts, p), v \
     94    }
     95static const struct fuse_opt conn_info_opt_spec[] = {
     96    CONN_OPTION("max_write=%u", max_write, 0),
     97    CONN_OPTION("max_write=", set_max_write, 1),
     98    CONN_OPTION("max_readahead=%u", max_readahead, 0),
     99    CONN_OPTION("max_readahead=", set_max_readahead, 1),
    100    CONN_OPTION("max_background=%u", max_background, 0),
    101    CONN_OPTION("max_background=", set_max_background, 1),
    102    CONN_OPTION("congestion_threshold=%u", congestion_threshold, 0),
    103    CONN_OPTION("congestion_threshold=", set_congestion_threshold, 1),
    104    CONN_OPTION("sync_read", sync_read, 1),
    105    CONN_OPTION("async_read", async_read, 1),
    106    CONN_OPTION("atomic_o_trunc", atomic_o_trunc, 1),
    107    CONN_OPTION("no_remote_lock", no_remote_posix_lock, 1),
    108    CONN_OPTION("no_remote_lock", no_remote_flock, 1),
    109    CONN_OPTION("no_remote_flock", no_remote_flock, 1),
    110    CONN_OPTION("no_remote_posix_lock", no_remote_posix_lock, 1),
    111    CONN_OPTION("splice_write", splice_write, 1),
    112    CONN_OPTION("no_splice_write", no_splice_write, 1),
    113    CONN_OPTION("splice_move", splice_move, 1),
    114    CONN_OPTION("no_splice_move", no_splice_move, 1),
    115    CONN_OPTION("splice_read", splice_read, 1),
    116    CONN_OPTION("no_splice_read", no_splice_read, 1),
    117    CONN_OPTION("auto_inval_data", auto_inval_data, 1),
    118    CONN_OPTION("no_auto_inval_data", no_auto_inval_data, 1),
    119    CONN_OPTION("readdirplus=no", no_readdirplus, 1),
    120    CONN_OPTION("readdirplus=yes", no_readdirplus, 0),
    121    CONN_OPTION("readdirplus=yes", no_readdirplus_auto, 1),
    122    CONN_OPTION("readdirplus=auto", no_readdirplus, 0),
    123    CONN_OPTION("readdirplus=auto", no_readdirplus_auto, 0),
    124    CONN_OPTION("async_dio", async_dio, 1),
    125    CONN_OPTION("no_async_dio", no_async_dio, 1),
    126    CONN_OPTION("writeback_cache", writeback_cache, 1),
    127    CONN_OPTION("no_writeback_cache", no_writeback_cache, 1),
    128    CONN_OPTION("time_gran=%u", time_gran, 0),
    129    CONN_OPTION("time_gran=", set_time_gran, 1),
    130    FUSE_OPT_END
    131};
    132
    133
    134void fuse_cmdline_help(void)
    135{
    136    printf("    -h   --help                print help\n"
    137           "    -V   --version             print version\n"
    138           "    --print-capabilities       print vhost-user.json\n"
    139           "    -d   -o debug              enable debug output (implies -f)\n"
    140           "    --syslog                   log to syslog (default stderr)\n"
    141           "    -f                         foreground operation\n"
    142           "    --daemonize                run in background\n"
    143           "    -o cache=<mode>            cache mode. could be one of \"auto, "
    144           "always, none\"\n"
    145           "                               default: auto\n"
    146           "    -o flock|no_flock          enable/disable flock\n"
    147           "                               default: no_flock\n"
    148           "    -o log_level=<level>       log level, default to \"info\"\n"
    149           "                               level could be one of \"debug, "
    150           "info, warn, err\"\n"
    151           "    -o max_idle_threads        the maximum number of idle worker "
    152           "threads\n"
    153           "                               allowed (default: 10)\n"
    154           "    -o posix_lock|no_posix_lock\n"
    155           "                               enable/disable remote posix lock\n"
    156           "                               default: no_posix_lock\n"
    157           "    -o readdirplus|no_readdirplus\n"
    158           "                               enable/disable readirplus\n"
    159           "                               default: readdirplus except with "
    160           "cache=none\n"
    161           "    -o sandbox=namespace|chroot\n"
    162           "                               sandboxing mode:\n"
    163           "                               - namespace: mount, pid, and net\n"
    164           "                                 namespaces with pivot_root(2)\n"
    165           "                                 into shared directory\n"
    166           "                               - chroot: chroot(2) into shared\n"
    167           "                                 directory (use in containers)\n"
    168           "                               default: namespace\n"
    169           "    -o timeout=<number>        I/O timeout (seconds)\n"
    170           "                               default: depends on cache= option.\n"
    171           "    -o writeback|no_writeback  enable/disable writeback cache\n"
    172           "                               default: no_writeback\n"
    173           "    -o xattr|no_xattr          enable/disable xattr\n"
    174           "                               default: no_xattr\n"
    175           "    -o xattrmap=<mapping>      Enable xattr mapping (enables xattr)\n"
    176           "                               <mapping> is a string consists of a series of rules\n"
    177           "                               e.g. -o xattrmap=:map::user.virtiofs.:\n"
    178           "    -o modcaps=CAPLIST         Modify the list of capabilities\n"
    179           "                               e.g. -o modcaps=+sys_admin:-chown\n"
    180           "    --rlimit-nofile=<num>      set maximum number of file descriptors\n"
    181           "                               (0 leaves rlimit unchanged)\n"
    182           "                               default: min(1000000, fs.file-max - 16384)\n"
    183           "                                        if the current rlimit is lower\n"
    184           "    -o allow_direct_io|no_allow_direct_io\n"
    185           "                               retain/discard O_DIRECT flags passed down\n"
    186           "                               to virtiofsd from guest applications.\n"
    187           "                               default: no_allow_direct_io\n"
    188           "    -o announce_submounts      Announce sub-mount points to the guest\n"
    189           "    -o posix_acl/no_posix_acl  Enable/Disable posix_acl. (default: disabled)\n"
    190           );
    191}
    192
    193static int fuse_helper_opt_proc(void *data, const char *arg, int key,
    194                                struct fuse_args *outargs)
    195{
    196    (void)data;
    197    (void)outargs;
    198
    199    switch (key) {
    200    case FUSE_OPT_KEY_NONOPT:
    201        fuse_log(FUSE_LOG_ERR, "fuse: invalid argument `%s'\n", arg);
    202        return -1;
    203
    204    default:
    205        /* Pass through unknown options */
    206        return 1;
    207    }
    208}
    209
    210static unsigned long get_default_rlimit_nofile(void)
    211{
    212    g_autofree gchar *file_max_str = NULL;
    213    const rlim_t reserved_fds = 16384; /* leave at least this many fds free */
    214    rlim_t max_fds = 1000000; /* our default RLIMIT_NOFILE target */
    215    rlim_t file_max;
    216    struct rlimit rlim;
    217
    218    /*
    219     * Reduce max_fds below the system-wide maximum, if necessary.  This
    220     * ensures there are fds available for other processes so we don't
    221     * cause resource exhaustion.
    222     */
    223    if (!g_file_get_contents("/proc/sys/fs/file-max", &file_max_str,
    224                             NULL, NULL)) {
    225        fuse_log(FUSE_LOG_ERR, "can't read /proc/sys/fs/file-max\n");
    226        exit(1);
    227    }
    228    file_max = g_ascii_strtoull(file_max_str, NULL, 10);
    229    if (file_max < 2 * reserved_fds) {
    230        fuse_log(FUSE_LOG_ERR,
    231                 "The fs.file-max sysctl is too low (%lu) to allow a "
    232                 "reasonable number of open files.\n",
    233                 (unsigned long)file_max);
    234        exit(1);
    235    }
    236    max_fds = MIN(file_max - reserved_fds, max_fds);
    237
    238    if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
    239        fuse_log(FUSE_LOG_ERR, "getrlimit(RLIMIT_NOFILE): %m\n");
    240        exit(1);
    241    }
    242
    243    if (rlim.rlim_cur >= max_fds) {
    244        return 0; /* we have more fds available than required! */
    245    }
    246    return max_fds;
    247}
    248
    249int fuse_parse_cmdline(struct fuse_args *args, struct fuse_cmdline_opts *opts)
    250{
    251    memset(opts, 0, sizeof(struct fuse_cmdline_opts));
    252
    253    opts->max_idle_threads = 10;
    254    opts->rlimit_nofile = get_default_rlimit_nofile();
    255    opts->foreground = 1;
    256
    257    if (fuse_opt_parse(args, opts, fuse_helper_opts, fuse_helper_opt_proc) ==
    258        -1) {
    259        return -1;
    260    }
    261
    262    return 0;
    263}
    264
    265
    266int fuse_daemonize(int foreground)
    267{
    268    int ret = 0, rett;
    269    if (!foreground) {
    270        int nullfd;
    271        int waiter[2];
    272        char completed;
    273
    274        if (pipe(waiter)) {
    275            fuse_log(FUSE_LOG_ERR, "fuse_daemonize: pipe: %s\n",
    276                     strerror(errno));
    277            return -1;
    278        }
    279
    280        /*
    281         * demonize current process by forking it and killing the
    282         * parent.  This makes current process as a child of 'init'.
    283         */
    284        switch (fork()) {
    285        case -1:
    286            fuse_log(FUSE_LOG_ERR, "fuse_daemonize: fork: %s\n",
    287                     strerror(errno));
    288            return -1;
    289        case 0:
    290            break;
    291        default:
    292            _exit(read(waiter[0], &completed,
    293                       sizeof(completed) != sizeof(completed)));
    294        }
    295
    296        if (setsid() == -1) {
    297            fuse_log(FUSE_LOG_ERR, "fuse_daemonize: setsid: %s\n",
    298                     strerror(errno));
    299            return -1;
    300        }
    301
    302        ret = chdir("/");
    303
    304        nullfd = open("/dev/null", O_RDWR, 0);
    305        if (nullfd != -1) {
    306            rett = dup2(nullfd, 0);
    307            if (!ret) {
    308                ret = rett;
    309            }
    310            rett = dup2(nullfd, 1);
    311            if (!ret) {
    312                ret = rett;
    313            }
    314            rett = dup2(nullfd, 2);
    315            if (!ret) {
    316                ret = rett;
    317            }
    318            if (nullfd > 2) {
    319                close(nullfd);
    320            }
    321        }
    322
    323        /* Propagate completion of daemon initialization */
    324        completed = 1;
    325        rett = write(waiter[1], &completed, sizeof(completed));
    326        if (!ret) {
    327            ret = rett;
    328        }
    329        close(waiter[0]);
    330        close(waiter[1]);
    331    } else {
    332        ret = chdir("/");
    333    }
    334    return ret;
    335}
    336
    337void fuse_apply_conn_info_opts(struct fuse_conn_info_opts *opts,
    338                               struct fuse_conn_info *conn)
    339{
    340    if (opts->set_max_write) {
    341        conn->max_write = opts->max_write;
    342    }
    343    if (opts->set_max_background) {
    344        conn->max_background = opts->max_background;
    345    }
    346    if (opts->set_congestion_threshold) {
    347        conn->congestion_threshold = opts->congestion_threshold;
    348    }
    349    if (opts->set_time_gran) {
    350        conn->time_gran = opts->time_gran;
    351    }
    352    if (opts->set_max_readahead) {
    353        conn->max_readahead = opts->max_readahead;
    354    }
    355
    356#define LL_ENABLE(cond, cap) \
    357    if (cond)                \
    358        conn->want |= (cap)
    359#define LL_DISABLE(cond, cap) \
    360    if (cond)                 \
    361        conn->want &= ~(cap)
    362
    363    LL_ENABLE(opts->splice_read, FUSE_CAP_SPLICE_READ);
    364    LL_DISABLE(opts->no_splice_read, FUSE_CAP_SPLICE_READ);
    365
    366    LL_ENABLE(opts->splice_write, FUSE_CAP_SPLICE_WRITE);
    367    LL_DISABLE(opts->no_splice_write, FUSE_CAP_SPLICE_WRITE);
    368
    369    LL_ENABLE(opts->splice_move, FUSE_CAP_SPLICE_MOVE);
    370    LL_DISABLE(opts->no_splice_move, FUSE_CAP_SPLICE_MOVE);
    371
    372    LL_ENABLE(opts->auto_inval_data, FUSE_CAP_AUTO_INVAL_DATA);
    373    LL_DISABLE(opts->no_auto_inval_data, FUSE_CAP_AUTO_INVAL_DATA);
    374
    375    LL_DISABLE(opts->no_readdirplus, FUSE_CAP_READDIRPLUS);
    376    LL_DISABLE(opts->no_readdirplus_auto, FUSE_CAP_READDIRPLUS_AUTO);
    377
    378    LL_ENABLE(opts->async_dio, FUSE_CAP_ASYNC_DIO);
    379    LL_DISABLE(opts->no_async_dio, FUSE_CAP_ASYNC_DIO);
    380
    381    LL_ENABLE(opts->writeback_cache, FUSE_CAP_WRITEBACK_CACHE);
    382    LL_DISABLE(opts->no_writeback_cache, FUSE_CAP_WRITEBACK_CACHE);
    383
    384    LL_ENABLE(opts->async_read, FUSE_CAP_ASYNC_READ);
    385    LL_DISABLE(opts->sync_read, FUSE_CAP_ASYNC_READ);
    386
    387    LL_DISABLE(opts->no_remote_posix_lock, FUSE_CAP_POSIX_LOCKS);
    388    LL_DISABLE(opts->no_remote_flock, FUSE_CAP_FLOCK_LOCKS);
    389}
    390
    391struct fuse_conn_info_opts *fuse_parse_conn_info_opts(struct fuse_args *args)
    392{
    393    struct fuse_conn_info_opts *opts;
    394
    395    opts = calloc(1, sizeof(struct fuse_conn_info_opts));
    396    if (opts == NULL) {
    397        fuse_log(FUSE_LOG_ERR, "calloc failed\n");
    398        return NULL;
    399    }
    400    if (fuse_opt_parse(args, opts, conn_info_opt_spec, NULL) == -1) {
    401        free(opts);
    402        return NULL;
    403    }
    404    return opts;
    405}