From patchwork Thu Oct 19 16:04:19 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ross Lagerwall X-Patchwork-Id: 10017621 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 960CC600CC for ; Thu, 19 Oct 2017 16:06:22 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 882D528D70 for ; Thu, 19 Oct 2017 16:06:22 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7C44128D7B; Thu, 19 Oct 2017 16:06:22 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 31B3328D70 for ; Thu, 19 Oct 2017 16:06:21 +0000 (UTC) Received: from localhost ([::1]:50014 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1e5DKu-0001J6-Fd for patchwork-qemu-devel@patchwork.kernel.org; Thu, 19 Oct 2017 12:06:20 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52089) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1e5DK6-0001Ft-4Z for qemu-devel@nongnu.org; Thu, 19 Oct 2017 12:05:34 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1e5DJz-0001Y3-Jh for qemu-devel@nongnu.org; Thu, 19 Oct 2017 12:05:30 -0400 Received: from smtp.citrix.com ([66.165.176.89]:33476) by eggs.gnu.org with esmtps (TLS1.0:RSA_ARCFOUR_SHA1:16) (Exim 4.71) (envelope-from ) id 1e5DJz-0001WX-9y for qemu-devel@nongnu.org; Thu, 19 Oct 2017 12:05:23 -0400 X-IronPort-AV: E=Sophos;i="5.43,402,1503360000"; d="scan'208";a="447145202" From: Ross Lagerwall To: Date: Thu, 19 Oct 2017 17:04:19 +0100 Message-ID: <20171019160419.11611-1-ross.lagerwall@citrix.com> X-Mailer: git-send-email 2.9.5 MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 66.165.176.89 Subject: [Qemu-devel] [PATCH v1] os-posix: Add -unshare option X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ross Lagerwall , Markus Armbruster Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP Add an option to allow calling unshare() just before starting guest execution. The option allows unsharing one or more of the mount namespace, the network namespace, and the IPC namespace. This is useful to restrict the ability of QEMU to cause damage to the system should it be compromised. An example of using this would be to have QEMU open a QMP socket at startup and unshare the network namespace. The instance of QEMU could still be controlled by the QMP socket since that belongs in the original namespace, but if QEMU were compromised it wouldn't be able to open any new connections, even to other processes on the same machine. Signed-off-by: Ross Lagerwall --- os-posix.c | 34 ++++++++++++++++++++++++++++++++++ qemu-options.hx | 14 ++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/os-posix.c b/os-posix.c index b9c2343..cfc5c38 100644 --- a/os-posix.c +++ b/os-posix.c @@ -45,6 +45,7 @@ static struct passwd *user_pwd; static const char *chroot_dir; static int daemonize; static int daemon_pipe; +static int unshare_flags; void os_setup_early_signal_handling(void) { @@ -160,6 +161,28 @@ void os_parse_cmd_args(int index, const char *optarg) fips_set_state(true); break; #endif +#ifdef CONFIG_SETNS + case QEMU_OPTION_unshare: + { + char *flag; + char *opts = g_strdup(optarg); + + while ((flag = qemu_strsep(&opts, ",")) != NULL) { + if (!strcmp(flag, "mount")) { + unshare_flags |= CLONE_NEWNS; + } else if (!strcmp(flag, "net")) { + unshare_flags |= CLONE_NEWNET; + } else if (!strcmp(flag, "ipc")) { + unshare_flags |= CLONE_NEWIPC; + } else { + fprintf(stderr, "Unknown unshare option: %s\n", flag); + exit(1); + } + } + g_free(opts); + } + break; +#endif } } @@ -201,6 +224,16 @@ static void change_root(void) } +static void unshare_namespaces(void) +{ + if (unshare_flags) { + if (unshare(unshare_flags) < 0) { + perror("could not unshare"); + exit(1); + } + } +} + void os_daemonize(void) { if (daemonize) { @@ -266,6 +299,7 @@ void os_setup_post(void) } change_root(); + unshare_namespaces(); change_process_uid(); if (daemonize) { diff --git a/qemu-options.hx b/qemu-options.hx index 3728e9b..5cfcc51 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -3972,6 +3972,20 @@ Immediately before starting guest execution, chroot to the specified directory. Especially useful in combination with -runas. ETEXI +#ifdef CONFIG_SETNS +DEF("unshare", HAS_ARG, QEMU_OPTION_unshare, \ + "-unshare [mount][,net][,ipc]\n" \ + " unshare namespaces just before starting the VM\n", + QEMU_ARCH_ALL) +#endif +STEXI +@item -unshare @code{[mount][,net][,ipc]} +@findex -unshare +Immediately before starting guest execution, unshare the specified namespaces. +The namespaces that can be unshared are the mount namespace, the network +namespace and the IPC namespace. +ETEXI + #ifndef _WIN32 DEF("runas", HAS_ARG, QEMU_OPTION_runas, \ "-runas user change to user id user just before starting the VM\n",