Commit c25e8bba authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/otubo/tags/pull-seccomp-20180601' into staging



pull-seccomp-20180601

# gpg: Signature made Fri 01 Jun 2018 13:01:18 BST
# gpg:                using RSA key DF32E7C0F0FFF9A2
# gpg: Good signature from "Eduardo Otubo (Senior Software Engineer) <otubo@redhat.com>"
# Primary key fingerprint: D67E 1B50 9374 86B4 0723  DBAB DF32 E7C0 F0FF F9A2

* remotes/otubo/tags/pull-seccomp-20180601:
  sandbox: disable -sandbox if CONFIG_SECCOMP undefined

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 14fc6184 9d0fdecb
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -21,5 +21,6 @@
#define QEMU_SECCOMP_SET_SPAWN       (1 << 3)
#define QEMU_SECCOMP_SET_RESOURCECTL (1 << 4)

int seccomp_start(uint32_t seccomp_opts);
int parse_sandbox(void *opaque, QemuOpts *opts, Error **errp);

#endif
+120 −1
Original line number Diff line number Diff line
@@ -13,6 +13,11 @@
 * GNU GPL, version 2 or (at your option) any later version.
 */
#include "qemu/osdep.h"
#include "qemu/config-file.h"
#include "qemu/option.h"
#include "qemu/module.h"
#include "qemu/error-report.h"
#include <sys/prctl.h>
#include <seccomp.h>
#include "sysemu/seccomp.h"

@@ -96,7 +101,7 @@ static const struct QemuSeccompSyscall blacklist[] = {
};


int seccomp_start(uint32_t seccomp_opts)
static int seccomp_start(uint32_t seccomp_opts)
{
    int rc = 0;
    unsigned int i = 0;
@@ -125,3 +130,117 @@ int seccomp_start(uint32_t seccomp_opts)
    seccomp_release(ctx);
    return rc;
}

#ifdef CONFIG_SECCOMP
int parse_sandbox(void *opaque, QemuOpts *opts, Error **errp)
{
    if (qemu_opt_get_bool(opts, "enable", false)) {
        uint32_t seccomp_opts = QEMU_SECCOMP_SET_DEFAULT
                | QEMU_SECCOMP_SET_OBSOLETE;
        const char *value = NULL;

        value = qemu_opt_get(opts, "obsolete");
        if (value) {
            if (g_str_equal(value, "allow")) {
                seccomp_opts &= ~QEMU_SECCOMP_SET_OBSOLETE;
            } else if (g_str_equal(value, "deny")) {
                /* this is the default option, this if is here
                 * to provide a little bit of consistency for
                 * the command line */
            } else {
                error_report("invalid argument for obsolete");
                return -1;
            }
        }

        value = qemu_opt_get(opts, "elevateprivileges");
        if (value) {
            if (g_str_equal(value, "deny")) {
                seccomp_opts |= QEMU_SECCOMP_SET_PRIVILEGED;
            } else if (g_str_equal(value, "children")) {
                seccomp_opts |= QEMU_SECCOMP_SET_PRIVILEGED;

                /* calling prctl directly because we're
                 * not sure if host has CAP_SYS_ADMIN set*/
                if (prctl(PR_SET_NO_NEW_PRIVS, 1)) {
                    error_report("failed to set no_new_privs "
                                 "aborting");
                    return -1;
                }
            } else if (g_str_equal(value, "allow")) {
                /* default value */
            } else {
                error_report("invalid argument for elevateprivileges");
                return -1;
            }
        }

        value = qemu_opt_get(opts, "spawn");
        if (value) {
            if (g_str_equal(value, "deny")) {
                seccomp_opts |= QEMU_SECCOMP_SET_SPAWN;
            } else if (g_str_equal(value, "allow")) {
                /* default value */
            } else {
                error_report("invalid argument for spawn");
                return -1;
            }
        }

        value = qemu_opt_get(opts, "resourcecontrol");
        if (value) {
            if (g_str_equal(value, "deny")) {
                seccomp_opts |= QEMU_SECCOMP_SET_RESOURCECTL;
            } else if (g_str_equal(value, "allow")) {
                /* default value */
            } else {
                error_report("invalid argument for resourcecontrol");
                return -1;
            }
        }

        if (seccomp_start(seccomp_opts) < 0) {
            error_report("failed to install seccomp syscall filter "
                         "in the kernel");
            return -1;
        }
    }

    return 0;
}

static QemuOptsList qemu_sandbox_opts = {
    .name = "sandbox",
    .implied_opt_name = "enable",
    .head = QTAILQ_HEAD_INITIALIZER(qemu_sandbox_opts.head),
    .desc = {
        {
            .name = "enable",
            .type = QEMU_OPT_BOOL,
        },
        {
            .name = "obsolete",
            .type = QEMU_OPT_STRING,
        },
        {
            .name = "elevateprivileges",
            .type = QEMU_OPT_STRING,
        },
        {
            .name = "spawn",
            .type = QEMU_OPT_STRING,
        },
        {
            .name = "resourcecontrol",
            .type = QEMU_OPT_STRING,
        },
        { /* end of list */ }
    },
};

static void seccomp_register(void)
{
    qemu_add_opts(&qemu_sandbox_opts);
}
opts_init(seccomp_register);
#endif
+8 −116
Original line number Diff line number Diff line
@@ -28,11 +28,7 @@
#include "qemu/cutils.h"
#include "qemu/help_option.h"
#include "qemu/uuid.h"

#ifdef CONFIG_SECCOMP
#include <sys/prctl.h>
#include "sysemu/seccomp.h"
#endif

#ifdef CONFIG_SDL
#if defined(__APPLE__) || defined(main)
@@ -259,35 +255,6 @@ static QemuOptsList qemu_rtc_opts = {
    },
};

static QemuOptsList qemu_sandbox_opts = {
    .name = "sandbox",
    .implied_opt_name = "enable",
    .head = QTAILQ_HEAD_INITIALIZER(qemu_sandbox_opts.head),
    .desc = {
        {
            .name = "enable",
            .type = QEMU_OPT_BOOL,
        },
        {
            .name = "obsolete",
            .type = QEMU_OPT_STRING,
        },
        {
            .name = "elevateprivileges",
            .type = QEMU_OPT_STRING,
        },
        {
            .name = "spawn",
            .type = QEMU_OPT_STRING,
        },
        {
            .name = "resourcecontrol",
            .type = QEMU_OPT_STRING,
        },
        { /* end of list */ }
    },
};

static QemuOptsList qemu_option_rom_opts = {
    .name = "option-rom",
    .implied_opt_name = "romfile",
@@ -1050,88 +1017,6 @@ static int bt_parse(const char *opt)
    return 1;
}

static int parse_sandbox(void *opaque, QemuOpts *opts, Error **errp)
{
    if (qemu_opt_get_bool(opts, "enable", false)) {
#ifdef CONFIG_SECCOMP
        uint32_t seccomp_opts = QEMU_SECCOMP_SET_DEFAULT
                | QEMU_SECCOMP_SET_OBSOLETE;
        const char *value = NULL;

        value = qemu_opt_get(opts, "obsolete");
        if (value) {
            if (g_str_equal(value, "allow")) {
                seccomp_opts &= ~QEMU_SECCOMP_SET_OBSOLETE;
            } else if (g_str_equal(value, "deny")) {
                /* this is the default option, this if is here
                 * to provide a little bit of consistency for
                 * the command line */
            } else {
                error_report("invalid argument for obsolete");
                return -1;
            }
        }

        value = qemu_opt_get(opts, "elevateprivileges");
        if (value) {
            if (g_str_equal(value, "deny")) {
                seccomp_opts |= QEMU_SECCOMP_SET_PRIVILEGED;
            } else if (g_str_equal(value, "children")) {
                seccomp_opts |= QEMU_SECCOMP_SET_PRIVILEGED;

                /* calling prctl directly because we're
                 * not sure if host has CAP_SYS_ADMIN set*/
                if (prctl(PR_SET_NO_NEW_PRIVS, 1)) {
                    error_report("failed to set no_new_privs "
                                 "aborting");
                    return -1;
                }
            } else if (g_str_equal(value, "allow")) {
                /* default value */
            } else {
                error_report("invalid argument for elevateprivileges");
                return -1;
            }
        }

        value = qemu_opt_get(opts, "spawn");
        if (value) {
            if (g_str_equal(value, "deny")) {
                seccomp_opts |= QEMU_SECCOMP_SET_SPAWN;
            } else if (g_str_equal(value, "allow")) {
                /* default value */
            } else {
                error_report("invalid argument for spawn");
                return -1;
            }
        }

        value = qemu_opt_get(opts, "resourcecontrol");
        if (value) {
            if (g_str_equal(value, "deny")) {
                seccomp_opts |= QEMU_SECCOMP_SET_RESOURCECTL;
            } else if (g_str_equal(value, "allow")) {
                /* default value */
            } else {
                error_report("invalid argument for resourcecontrol");
                return -1;
            }
        }

        if (seccomp_start(seccomp_opts) < 0) {
            error_report("failed to install seccomp syscall filter "
                         "in the kernel");
            return -1;
        }
#else
        error_report("seccomp support is disabled");
        return -1;
#endif
    }

    return 0;
}

static int parse_name(void *opaque, QemuOpts *opts, Error **errp)
{
    const char *proc_name;
@@ -3079,7 +2964,6 @@ int main(int argc, char **argv, char **envp)
    qemu_add_opts(&qemu_mem_opts);
    qemu_add_opts(&qemu_smp_opts);
    qemu_add_opts(&qemu_boot_opts);
    qemu_add_opts(&qemu_sandbox_opts);
    qemu_add_opts(&qemu_add_fd_opts);
    qemu_add_opts(&qemu_object_opts);
    qemu_add_opts(&qemu_tpmdev_opts);
@@ -3980,11 +3864,17 @@ int main(int argc, char **argv, char **envp)
                qtest_log = optarg;
                break;
            case QEMU_OPTION_sandbox:
#ifdef CONFIG_SECCOMP
                opts = qemu_opts_parse_noisily(qemu_find_opts("sandbox"),
                                               optarg, true);
                if (!opts) {
                    exit(1);
                }
#else
                error_report("-sandbox support is not enabled "
                             "in this QEMU binary");
                exit(1);
#endif
                break;
            case QEMU_OPTION_add_fd:
#ifndef _WIN32
@@ -4077,10 +3967,12 @@ int main(int argc, char **argv, char **envp)
        exit(1);
    }

#ifdef CONFIG_SECCOMP
    if (qemu_opts_foreach(qemu_find_opts("sandbox"),
                          parse_sandbox, NULL, NULL)) {
        exit(1);
    }
#endif

    if (qemu_opts_foreach(qemu_find_opts("name"),
                          parse_name, NULL, NULL)) {