From patchwork Wed Jan 15 02:39:51 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= X-Patchwork-Id: 11333215 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1BDB992A for ; Wed, 15 Jan 2020 02:41:49 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id E138B222C3 for ; Wed, 15 Jan 2020 02:41:48 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="RPYeuwRj" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org E138B222C3 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=invisiblethingslab.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1irYbu-000584-Ri; Wed, 15 Jan 2020 02:40:46 +0000 Received: from us1-rack-iad1.inumbo.com ([172.99.69.81]) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1irYbt-000563-FG for xen-devel@lists.xenproject.org; Wed, 15 Jan 2020 02:40:45 +0000 X-Inumbo-ID: 617cb482-3740-11ea-b89f-bc764e2007e4 Received: from out2-smtp.messagingengine.com (unknown [66.111.4.26]) by us1-rack-iad1.inumbo.com (Halon) with ESMTPS id 617cb482-3740-11ea-b89f-bc764e2007e4; Wed, 15 Jan 2020 02:40:24 +0000 (UTC) Received: from compute7.internal (compute7.nyi.internal [10.202.2.47]) by mailout.nyi.internal (Postfix) with ESMTP id 161CF221BD; Tue, 14 Jan 2020 21:40:24 -0500 (EST) Received: from mailfrontend2 ([10.202.2.163]) by compute7.internal (MEProxy); Tue, 14 Jan 2020 21:40:24 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:content-type :date:from:in-reply-to:message-id:mime-version:references :subject:to:x-me-proxy:x-me-proxy:x-me-sender:x-me-sender :x-sasl-enc; s=fm1; bh=ZsOEiGo4bLBb/cJsQQgBXQAcppRT0uPThW/qIrcld oQ=; b=RPYeuwRjuB0Ig8qKMPyUD9iVkfS1lE7iM8daBpDlNRqCh5R9dyL5WfAEs w2zqfLRX5h0q846Ob9irqOpJTJdpi5WppPggK6Ov2Autlerh1BbJn4f++dfZD77E /vyhcopWQtwnxGOcqXMlumjbdyInyFfPoL5wkBGYRA6GODFnL87z9Rq0Ei5jmmYq UWzmoDseyGtC8jvAajUyalA0ark758uAjlSTG//Y3CcPoPEOZxazjDi8b/jTvmU2 A9LbnmdE6fYx/R8OF03yz2GK/liCbNAC+apMSP9g6wh86lF6AHhJUxTuqaimw19y UqdSeDCqjhzirE+93/7zoLn+BppSA== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedugedrtddvgdegkecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenuc fjughrpefhvffufffkofgjfhggtgfgsehtkeertdertdejnecuhfhrohhmpeforghrvghk ucforghrtgiihihkohifshhkihdqifpkrhgvtghkihcuoehmrghrmhgrrhgvkhesihhnvh hishhisghlvghthhhinhhgshhlrggsrdgtohhmqeenucffohhmrghinhepshhprgifnhdr rghonecukfhppeeluddrieehrdefgedrfeefnecurfgrrhgrmhepmhgrihhlfhhrohhmpe hmrghrmhgrrhgvkhesihhnvhhishhisghlvghthhhinhhgshhlrggsrdgtohhmnecuvehl uhhsthgvrhfuihiivgeptd X-ME-Proxy: Received: from localhost.localdomain (ip5b412221.dynamic.kabel-deutschland.de [91.65.34.33]) by mail.messagingengine.com (Postfix) with ESMTPA id 2C2CB30607B4; Tue, 14 Jan 2020 21:40:23 -0500 (EST) From: =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= To: xen-devel@lists.xenproject.org Date: Wed, 15 Jan 2020 03:39:51 +0100 Message-Id: <8d8515cabfdc666bd1afb40f6b7e44ccbe362dbf.1579055705.git-series.marmarek@invisiblethingslab.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: References: MIME-Version: 1.0 Subject: [Xen-devel] [PATCH v4 12/16] libxl: use vchan for QMP access with Linux stubdomain X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Anthony PERARD , Ian Jackson , =?utf-8?q?Marek_Marczykowski-G?= =?utf-8?q?=C3=B3recki?= , Wei Liu Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" Access to QMP of QEMU in Linux stubdomain is possible over vchan connection. Handle the actual vchan connection in a separate process (vchan-socket-proxy). This simplified integration with QMP (already quite complex), but also allows preliminary filtering of (potentially malicious) QMP input. Since only one client can be connected to vchan server at the same time and it is not enforced by the libxenvchan itself, additional client-side locking is needed. It is implicitly implemented by vchan-socket-proxy, as it handle only one connection at a time. Note that qemu supports only one simultaneous client on a control socket anyway (but in UNIX socket case, it enforce it server-side), so it doesn't add any extra limitation. Signed-off-by: Marek Marczykowski-Górecki --- Changes in v4: - new patch, in place of both "libxl: use vchan for QMP access ..." --- tools/configure.ac | 9 ++- tools/libxl/libxl_dm.c | 159 ++++++++++++++++++++++++++++++++++-- tools/libxl/libxl_internal.h | 1 +- 3 files changed, 161 insertions(+), 8 deletions(-) diff --git a/tools/configure.ac b/tools/configure.ac index 8d86c42..20bbdbf 100644 --- a/tools/configure.ac +++ b/tools/configure.ac @@ -192,6 +192,15 @@ AC_SUBST(qemu_xen) AC_SUBST(qemu_xen_path) AC_SUBST(qemu_xen_systemd) +AC_ARG_WITH([stubdom-qmp-proxy], + AC_HELP_STRING([--stubdom-qmp-proxy@<:@=PATH@:>@], + [Use supplied binary PATH as a QMP proxy into stubdomain]),[ + stubdom_qmp_proxy="$withval" +],[ + stubdom_qmp_proxy="$bindir/vchan-socket-proxy" +]) +AC_DEFINE_UNQUOTED([STUBDOM_QMP_PROXY_PATH], ["$stubdom_qmp_proxy"], [QMP proxy path]) + AC_ARG_WITH([system-seabios], AS_HELP_STRING([--with-system-seabios@<:@=PATH@:>@], [Use system supplied seabios PATH instead of building and installing diff --git a/tools/libxl/libxl_dm.c b/tools/libxl/libxl_dm.c index 528ca3e..23ac7e4 100644 --- a/tools/libxl/libxl_dm.c +++ b/tools/libxl/libxl_dm.c @@ -1183,7 +1183,7 @@ static int libxl__build_device_model_args_new(libxl__gc *gc, "-xen-domid", GCSPRINTF("%d", guest_domid), NULL); - /* There is currently no way to access the QMP socket in the stubdom */ + /* QMP access to qemu running in stubdomain is done over vchan, stubdomain setup it itself */ if (!is_stubdom) { flexarray_append(dm_args, "-chardev"); if (state->dm_monitor_fd >= 0) { @@ -2178,6 +2178,23 @@ static void stubdom_pvqemu_unpaused(libxl__egc *egc, static void stubdom_xswait_cb(libxl__egc *egc, libxl__xswait_state *xswait, int rc, const char *p); +static void spawn_qmp_proxy(libxl__egc *egc, + libxl__stub_dm_spawn_state *sdss); + +static void qmp_proxy_confirm(libxl__egc *egc, libxl__spawn_state *spawn, + const char *xsdata); + +static void qmp_proxy_startup_failed(libxl__egc *egc, + libxl__spawn_state *spawn, + int rc); + +static void qmp_proxy_detached(libxl__egc *egc, + libxl__spawn_state *spawn); + +static void qmp_proxy_spawn_outcome(libxl__egc *egc, + libxl__stub_dm_spawn_state *sdss, + int rc); + char *libxl__stub_dm_name(libxl__gc *gc, const char *guest_name) { return GCSPRINTF("%s-dm", guest_name); @@ -2460,24 +2477,150 @@ static void spawn_stub_launch_dm(libxl__egc *egc, goto out; } + sdss->qmp_proxy_spawn.ao = ao; + if (libxl__stubdomain_is_linux(&guest_config->b_info)) { + spawn_qmp_proxy(egc, sdss); + } else { + qmp_proxy_spawn_outcome(egc, sdss, 0); + } + + return; + +out: + assert(ret); + qmp_proxy_spawn_outcome(egc, sdss, ret); +} + +static void spawn_qmp_proxy(libxl__egc *egc, + libxl__stub_dm_spawn_state *sdss) +{ + STATE_AO_GC(sdss->qmp_proxy_spawn.ao); + const uint32_t guest_domid = sdss->dm.guest_domid; + const uint32_t dm_domid = sdss->pvqemu.guest_domid; + const char *dom_path = libxl__xs_get_dompath(gc, dm_domid); + char **args; + int nr = 0; + int rc, logfile_w, null; + + if (access(STUBDOM_QMP_PROXY_PATH, X_OK) < 0) { + LOGED(ERROR, guest_domid, "qmp proxy %s is not executable", STUBDOM_QMP_PROXY_PATH); + rc = ERROR_FAIL; + goto out; + } + + sdss->qmp_proxy_spawn.what = GCSPRINTF("domain %d device model qmp proxy", guest_domid); + sdss->qmp_proxy_spawn.pidpath = GCSPRINTF("%s/image/qmp-proxy-pid", dom_path); + sdss->qmp_proxy_spawn.xspath = GCSPRINTF("%s/image/qmp-proxy-state", dom_path); + + sdss->qmp_proxy_spawn.timeout_ms = LIBXL_DEVICE_MODEL_START_TIMEOUT * 1000; + sdss->qmp_proxy_spawn.midproc_cb = libxl__spawn_record_pid; + sdss->qmp_proxy_spawn.confirm_cb = qmp_proxy_confirm; + sdss->qmp_proxy_spawn.failure_cb = qmp_proxy_startup_failed; + sdss->qmp_proxy_spawn.detached_cb = qmp_proxy_detached; + + const int arraysize = 6; + GCNEW_ARRAY(args, arraysize); + args[nr++] = STUBDOM_QMP_PROXY_PATH; + args[nr++] = GCSPRINTF("--state-path=%s", sdss->qmp_proxy_spawn.xspath); + args[nr++] = GCSPRINTF("%u", dm_domid); + args[nr++] = GCSPRINTF("%s/device-model/%u/qmp-vchan", dom_path, guest_domid); + args[nr++] = (char*)libxl__qemu_qmp_path(gc, guest_domid); + args[nr++] = NULL; + assert(nr == arraysize); + + logfile_w = libxl__create_qemu_logfile(gc, GCSPRINTF("qmp-proxy-%s", + sdss->dm_config.c_info.name)); + if (logfile_w < 0) { + rc = logfile_w; + goto out; + } + null = open("/dev/null", O_RDWR); + if (null < 0) { + LOGED(ERROR, guest_domid, "unable to open /dev/null"); + rc = ERROR_FAIL; + goto out_close; + } + + rc = libxl__spawn_spawn(egc, &sdss->qmp_proxy_spawn); + if (rc < 0) + goto out_close; + if (!rc) { /* inner child */ + setsid(); + libxl__exec(gc, null, null, logfile_w, STUBDOM_QMP_PROXY_PATH, args, NULL); + /* unreachable */ + } + + rc = 0; + +out_close: + if (logfile_w >= 0) + close(logfile_w); + if (null >= 0) + close(null); +out: + if (rc) + qmp_proxy_spawn_outcome(egc, sdss, rc); +} + +static void qmp_proxy_confirm(libxl__egc *egc, libxl__spawn_state *spawn, + const char *xsdata) +{ + STATE_AO_GC(spawn->ao); + + if (!xsdata) + return; + + if (strcmp(xsdata, "running")) + return; + + libxl__spawn_initiate_detach(gc, spawn); +} + +static void qmp_proxy_startup_failed(libxl__egc *egc, + libxl__spawn_state *spawn, + int rc) +{ + libxl__stub_dm_spawn_state *sdss = CONTAINER_OF(spawn, *sdss, qmp_proxy_spawn); + qmp_proxy_spawn_outcome(egc, sdss, rc); +} + +static void qmp_proxy_detached(libxl__egc *egc, + libxl__spawn_state *spawn) +{ + libxl__stub_dm_spawn_state *sdss = CONTAINER_OF(spawn, *sdss, qmp_proxy_spawn); + qmp_proxy_spawn_outcome(egc, sdss, 0); +} + +static void qmp_proxy_spawn_outcome(libxl__egc *egc, + libxl__stub_dm_spawn_state *sdss, + int rc) +{ + STATE_AO_GC(sdss->qmp_proxy_spawn.ao); + int need_pvqemu = libxl__need_xenpv_qemu(gc, &sdss->dm_config); + + if (rc) goto out; + + if (need_pvqemu < 0) { + rc = need_pvqemu; + goto out; + } + sdss->pvqemu.spawn.ao = ao; - sdss->pvqemu.guest_domid = dm_domid; sdss->pvqemu.guest_config = &sdss->dm_config; sdss->pvqemu.build_state = &sdss->dm_state; sdss->pvqemu.callback = spawn_stubdom_pvqemu_cb; - - if (!need_qemu) { + if (need_pvqemu) { + libxl__spawn_local_dm(egc, &sdss->pvqemu); + } else { /* If dom0 qemu not needed, do not launch it */ spawn_stubdom_pvqemu_cb(egc, &sdss->pvqemu, 0); - } else { - libxl__spawn_local_dm(egc, &sdss->pvqemu); } return; out: - assert(ret); - spawn_stubdom_pvqemu_cb(egc, &sdss->pvqemu, ret); + assert(rc); + spawn_stubdom_pvqemu_cb(egc, &sdss->pvqemu, rc); } static void spawn_stubdom_pvqemu_cb(libxl__egc *egc, diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index 2b4a1cc..895bb65 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -4129,6 +4129,7 @@ typedef struct { libxl__destroy_domid_state dis; libxl__multidev multidev; libxl__xswait_state xswait; + libxl__spawn_state qmp_proxy_spawn; } libxl__stub_dm_spawn_state; _hidden void libxl__spawn_stub_dm(libxl__egc *egc, libxl__stub_dm_spawn_state*);