From nobody Fri Nov 7 18:48:28 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.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 209.51.188.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 (209.51.188.17 [209.51.188.17]) by mx.zohomail.com with SMTPS id 1548340967283156.9339206177666; Thu, 24 Jan 2019 06:42:47 -0800 (PST) Received: from localhost ([127.0.0.1]:55072 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gmgDD-00077n-US for importer@patchew.org; Thu, 24 Jan 2019 09:42:36 -0500 Received: from eggs.gnu.org ([209.51.188.92]:47906) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gmg9W-0004Hp-1c for qemu-devel@nongnu.org; Thu, 24 Jan 2019 09:38:51 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gmg9U-0004mS-7g for qemu-devel@nongnu.org; Thu, 24 Jan 2019 09:38:45 -0500 Received: from mx1.redhat.com ([209.132.183.28]:52498) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gmg9T-0004V7-Us; Thu, 24 Jan 2019 09:38:44 -0500 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4B31DC05A1D8; Thu, 24 Jan 2019 14:38:28 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-116-138.ams2.redhat.com [10.36.116.138]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 10B4D5D772; Thu, 24 Jan 2019 14:38:27 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id CEC6911385D5; Thu, 24 Jan 2019 15:38:25 +0100 (CET) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Thu, 24 Jan 2019 15:38:25 +0100 Message-Id: <20190124143825.25921-5-armbru@redhat.com> In-Reply-To: <20190124143825.25921-1-armbru@redhat.com> References: <20190124143825.25921-1-armbru@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Thu, 24 Jan 2019 14:38:28 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PULL 4/4] json: Fix % handling when not interpolating 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: qemu-stable@nongnu.org, Christophe Fergeau Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Christophe Fergeau Commit 8bca4613 added support for %% in json strings when interpolating, but in doing so broke handling of % when not interpolating. When parse_string() is fed a string token containing '%', it skips the '%' regardless of ctxt->ap, i.e. even it's not interpolating. If the '%' is the string's last character, it fails an assertion. Else, it "merely" swallows the '%'. Fix parse_string() to handle '%' specially only when interpolating. To gauge the bug's impact, let's review non-interpolating users of this parser, i.e. code passing NULL context to json_message_parser_init(): * tests/check-qjson.c, tests/test-qobject-input-visitor.c, tests/test-visitor-serialization.c Plenty of tests, but we still failed to cover the buggy case. * monitor.c: QMP input * qga/main.c: QGA input * qobject_from_json(): - qobject-input-visitor.c: JSON command line option arguments of -display and -blockdev Reproducer: -blockdev '{"%"}' - block.c: JSON pseudo-filenames starting with "json:" Reproducer: https://bugzilla.redhat.com/show_bug.cgi?id=3D1668244#c3 - block/rbd.c: JSON key pairs Pseudo-filenames starting with "rbd:". Command line, QMP and QGA input are trusted. Filenames are trusted when they come from command line, QMP or HMP. They are untrusted when they come from from image file headers. Example: QCOW2 backing file name. Note that this is *not* the security boundary between host and guest. It's the boundary between host and an image file from an untrusted source. Neither failing an assertion nor skipping a character in a filename of your choice looks exploitable. Note that we don't support compiling with NDEBUG. Fixes: 8bca4613e6cddd948895b8db3def05950463495b Cc: qemu-stable@nongnu.org Signed-off-by: Christophe Fergeau Message-Id: <20190102140535.11512-1-cfergeau@redhat.com> Reviewed-by: Eric Blake Tested-by: Richard W.M. Jones [Commit message extended to discuss impact] Signed-off-by: Markus Armbruster --- qobject/json-parser.c | 10 ++++++---- tests/check-qjson.c | 5 +++++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/qobject/json-parser.c b/qobject/json-parser.c index 7a7ae9e8d1..d8eb210c0c 100644 --- a/qobject/json-parser.c +++ b/qobject/json-parser.c @@ -208,11 +208,13 @@ static QString *parse_string(JSONParserContext *ctxt,= JSONToken *token) } break; case '%': - if (ctxt->ap && ptr[1] !=3D '%') { - parse_error(ctxt, token, "can't interpolate into string"); - goto out; + if (ctxt->ap) { + if (ptr[1] !=3D '%') { + parse_error(ctxt, token, "can't interpolate into strin= g"); + goto out; + } + ptr++; } - ptr++; /* fall through */ default: cp =3D mod_utf8_codepoint(ptr, 6, &end); diff --git a/tests/check-qjson.c b/tests/check-qjson.c index d876a7a96e..fa2afccb0a 100644 --- a/tests/check-qjson.c +++ b/tests/check-qjson.c @@ -175,6 +175,11 @@ static void utf8_string(void) "\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5", "\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5", "\\u03BA\\u1F79\\u03C3\\u03BC\\u03B5", + }, + /* '%' character when not interpolating */ + { + "100%", + "100%", }, /* 2 Boundary condition test cases */ /* 2.1 First possible sequence of a certain length */ --=20 2.17.2