From nobody Tue Nov 4 18:28:05 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1530634516867545.9588234178889; Tue, 3 Jul 2018 09:15:16 -0700 (PDT) Received: from localhost ([::1]:41392 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1faNxO-0000k6-Sk for importer@patchew.org; Tue, 03 Jul 2018 12:15:10 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34496) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1faNN1-0002PV-V9 for qemu-devel@nongnu.org; Tue, 03 Jul 2018 11:37:42 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1faNMx-0005Jl-BS for qemu-devel@nongnu.org; Tue, 03 Jul 2018 11:37:35 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:52098 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1faNMx-0005IE-5F for qemu-devel@nongnu.org; Tue, 03 Jul 2018 11:37:31 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B65F14075C59 for ; Tue, 3 Jul 2018 15:37:30 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-116-126.ams2.redhat.com [10.36.116.126]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 7343E1117629 for ; Tue, 3 Jul 2018 15:37:30 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 4280B1132D3B; Tue, 3 Jul 2018 17:37:28 +0200 (CEST) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Tue, 3 Jul 2018 17:37:07 +0200 Message-Id: <20180703153728.2175-12-armbru@redhat.com> In-Reply-To: <20180703153728.2175-1-armbru@redhat.com> References: <20180703153728.2175-1-armbru@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.3 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Tue, 03 Jul 2018 15:37:30 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Tue, 03 Jul 2018 15:37:30 +0000 (UTC) for IP:'10.11.54.3' DOMAIN:'int-mx03.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'armbru@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PULL 11/32] qmp qemu-ga: Fix qemu-ga not to accept "control" 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Commit cf869d53172 "qmp: support out-of-band (oob) execution" accidentally made qemu-ga accept and ignore "control". Fix that. Out-of-band execution in a monitor that doesn't support it now fails with {"error": {"class": "GenericError", "desc": "QMP input member 'control'= is unexpected"}} instead of {"error": {"class": "GenericError", "desc": "Please enable out-of-band = first for the session during capabilities negotiation"}} The old description is suboptimal when out-of-band cannot not be enabled, or the command doesn't support out-of-band execution. The new description is a bit unspecific, but it'll do. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Message-Id: <20180703085358.13941-12-armbru@redhat.com> --- include/qapi/qmp/dispatch.h | 6 ++++-- monitor.c | 9 ++------- qapi/qmp-dispatch.c | 14 ++++++++------ qga/main.c | 2 +- tests/test-qga.c | 9 +++++---- tests/test-qmp-cmds.c | 8 ++++---- 6 files changed, 24 insertions(+), 24 deletions(-) diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h index b366bb48bd..303a15ba84 100644 --- a/include/qapi/qmp/dispatch.h +++ b/include/qapi/qmp/dispatch.h @@ -41,7 +41,6 @@ void qmp_register_command(QmpCommandList *cmds, const cha= r *name, QmpCommandFunc *fn, QmpCommandOptions options); void qmp_unregister_command(QmpCommandList *cmds, const char *name); QmpCommand *qmp_find_command(QmpCommandList *cmds, const char *name); -QObject *qmp_dispatch(QmpCommandList *cmds, QObject *request); void qmp_disable_command(QmpCommandList *cmds, const char *name); void qmp_enable_command(QmpCommandList *cmds, const char *name); =20 @@ -49,7 +48,10 @@ bool qmp_command_is_enabled(const QmpCommand *cmd); const char *qmp_command_name(const QmpCommand *cmd); bool qmp_has_success_response(const QmpCommand *cmd); QObject *qmp_build_error_object(Error *err); -QDict *qmp_dispatch_check_obj(const QObject *request, Error **errp); +QDict *qmp_dispatch_check_obj(const QObject *request, bool allow_oob, + Error **errp); +QObject *qmp_dispatch(QmpCommandList *cmds, QObject *request, + bool allow_oob); bool qmp_is_oob(QDict *dict); =20 typedef void (*qmp_cmd_callback_fn)(QmpCommand *cmd, void *opaque); diff --git a/monitor.c b/monitor.c index 7245ee37ce..2e443bba13 100644 --- a/monitor.c +++ b/monitor.c @@ -1319,11 +1319,6 @@ static bool qmp_cmd_oob_check(Monitor *mon, QDict *r= eq, Error **errp) } =20 if (qmp_is_oob(req)) { - if (!qmp_oob_enabled(mon)) { - error_setg(errp, "Please enable out-of-band first " - "for the session during capabilities negotiation"); - return false; - } if (!(cmd->options & QCO_ALLOW_OOB)) { error_setg(errp, "The command %s does not support OOB", command); @@ -4195,7 +4190,7 @@ static void monitor_qmp_dispatch_one(QMPRequest *req_= obj) old_mon =3D cur_mon; cur_mon =3D mon; =20 - rsp =3D qmp_dispatch(mon->qmp.commands, req); + rsp =3D qmp_dispatch(mon->qmp.commands, req, qmp_oob_enabled(mon)); =20 cur_mon =3D old_mon; =20 @@ -4286,7 +4281,7 @@ static void handle_qmp_command(JSONMessageParser *par= ser, GQueue *tokens) } /* else will fail qmp_dispatch() */ =20 /* Check against the request in general layout */ - qdict =3D qmp_dispatch_check_obj(req, &err); + qdict =3D qmp_dispatch_check_obj(req, qmp_oob_enabled(mon), &err); if (!qdict) { goto err; } diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index 3d5d5e110f..0ad0fab8ed 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -20,7 +20,8 @@ #include "qapi/qmp/qbool.h" #include "sysemu/sysemu.h" =20 -QDict *qmp_dispatch_check_obj(const QObject *request, Error **errp) +QDict *qmp_dispatch_check_obj(const QObject *request, bool allow_oob, + Error **errp) { const QDictEntry *ent; const char *arg_name; @@ -52,7 +53,7 @@ QDict *qmp_dispatch_check_obj(const QObject *request, Err= or **errp) "QMP input member 'arguments' must be an object= "); return NULL; } - } else if (!strcmp(arg_name, "control")) { + } else if (!strcmp(arg_name, "control") && allow_oob) { if (qobject_type(arg_obj) !=3D QTYPE_QDICT) { error_setg(errp, "QMP input member 'control' must be a dict"); @@ -74,7 +75,7 @@ QDict *qmp_dispatch_check_obj(const QObject *request, Err= or **errp) } =20 static QObject *do_qmp_dispatch(QmpCommandList *cmds, QObject *request, - Error **errp) + bool allow_oob, Error **errp) { Error *local_err =3D NULL; const char *command; @@ -82,7 +83,7 @@ static QObject *do_qmp_dispatch(QmpCommandList *cmds, QOb= ject *request, QmpCommand *cmd; QObject *ret =3D NULL; =20 - dict =3D qmp_dispatch_check_obj(request, errp); + dict =3D qmp_dispatch_check_obj(request, allow_oob, errp); if (!dict) { return NULL; } @@ -157,13 +158,14 @@ bool qmp_is_oob(QDict *dict) return qbool_get_bool(bool_obj); } =20 -QObject *qmp_dispatch(QmpCommandList *cmds, QObject *request) +QObject *qmp_dispatch(QmpCommandList *cmds, QObject *request, + bool allow_oob) { Error *err =3D NULL; QObject *ret; QDict *rsp; =20 - ret =3D do_qmp_dispatch(cmds, request, &err); + ret =3D do_qmp_dispatch(cmds, request, allow_oob, &err); =20 rsp =3D qdict_new(); if (err) { diff --git a/qga/main.c b/qga/main.c index ea7540edcc..d332bacce5 100644 --- a/qga/main.c +++ b/qga/main.c @@ -586,7 +586,7 @@ static void process_command(GAState *s, QDict *req) =20 g_assert(req); g_debug("processing command"); - rsp =3D qmp_dispatch(&ga_commands, QOBJECT(req)); + rsp =3D qmp_dispatch(&ga_commands, QOBJECT(req), false); if (rsp) { ret =3D send_response(s, rsp); if (ret < 0) { diff --git a/tests/test-qga.c b/tests/test-qga.c index 2e9e0f73bb..febabc7ad5 100644 --- a/tests/test-qga.c +++ b/tests/test-qga.c @@ -245,16 +245,17 @@ static void test_qga_invalid_id(gconstpointer fix) =20 static void test_qga_invalid_oob(gconstpointer fix) { - /* FIXME "control" is ignored; it should be rejected */ const TestFixture *fixture =3D fix; - QDict *ret; + QDict *ret, *error; + const char *class; =20 ret =3D qmp_fd(fixture->fd, "{'execute': 'guest-ping'," " 'control': {'run-oob': true}}"); g_assert_nonnull(ret); - qmp_assert_no_error(ret); =20 - qdict_get_qdict(ret, "return"); + error =3D qdict_get_qdict(ret, "error"); + class =3D qdict_get_try_str(error, "class"); + g_assert_cmpstr(class, =3D=3D, "GenericError"); =20 qobject_unref(ret); } diff --git a/tests/test-qmp-cmds.c b/tests/test-qmp-cmds.c index 491b0c4a44..10c7ba40c1 100644 --- a/tests/test-qmp-cmds.c +++ b/tests/test-qmp-cmds.c @@ -102,7 +102,7 @@ static void test_dispatch_cmd(void) =20 qdict_put_str(req, "execute", "user_def_cmd"); =20 - resp =3D qmp_dispatch(&qmp_commands, QOBJECT(req)); + resp =3D qmp_dispatch(&qmp_commands, QOBJECT(req), false); assert(resp !=3D NULL); assert(!qdict_haskey(qobject_to(QDict, resp), "error")); =20 @@ -119,7 +119,7 @@ static void test_dispatch_cmd_failure(void) =20 qdict_put_str(req, "execute", "user_def_cmd2"); =20 - resp =3D qmp_dispatch(&qmp_commands, QOBJECT(req)); + resp =3D qmp_dispatch(&qmp_commands, QOBJECT(req), false); assert(resp !=3D NULL); assert(qdict_haskey(qobject_to(QDict, resp), "error")); =20 @@ -133,7 +133,7 @@ static void test_dispatch_cmd_failure(void) =20 qdict_put_str(req, "execute", "user_def_cmd"); =20 - resp =3D qmp_dispatch(&qmp_commands, QOBJECT(req)); + resp =3D qmp_dispatch(&qmp_commands, QOBJECT(req), false); assert(resp !=3D NULL); assert(qdict_haskey(qobject_to(QDict, resp), "error")); =20 @@ -147,7 +147,7 @@ static QObject *test_qmp_dispatch(QDict *req) QDict *resp; QObject *ret; =20 - resp_obj =3D qmp_dispatch(&qmp_commands, QOBJECT(req)); + resp_obj =3D qmp_dispatch(&qmp_commands, QOBJECT(req), false); assert(resp_obj); resp =3D qobject_to(QDict, resp_obj); assert(resp && !qdict_haskey(resp, "error")); --=20 2.17.1