From nobody Tue Feb 10 02:55:06 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1597725529; cv=none; d=zohomail.com; s=zohoarc; b=nldVNjetrGTy3Frr6oWCja+OUh41iabi/q/NP0CQAITjh7re8Lhcr7fpeQ3l4K2PSpnsFHfTqGTX1vbktClKnAYWdY710euEF6dGZriUhf0RmuEnTP9CixkQsPl2YiSD7ciS8Rj9JVAKXr/LiPLJ+5Qc9hJ5ZpWUBco7T21ezZ4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1597725529; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=A/mw3ojB7UbOGsAq/ZdFVCZWIAit/Rjo0gp3IIPeup0=; b=E+7yl33khRG+n2DT6Om3qpL1dAkfvzpnMmFk+V2SRg2bXn4dFoWw5BrHBseHQp5DkvkUl2dGuxdOXfgDyUEBdvGlExcx2TeHpayo7zOHGGtOqKG/g7tLTMlXjnULvGJWp4Ucp49Wkra1VY2gIMTLG/9tL1e3IHcjWU512hZ6TZY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1597725529094513.8654799952238; Mon, 17 Aug 2020 21:38:49 -0700 (PDT) Received: from localhost ([::1]:53898 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1k7tOa-0000cg-0z for importer@patchew.org; Tue, 18 Aug 2020 00:38:48 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:50434) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k7t7P-0000kR-Am; Tue, 18 Aug 2020 00:21:03 -0400 Received: from ozlabs.org ([203.11.71.1]:60799) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k7t7M-0006dM-RX; Tue, 18 Aug 2020 00:21:02 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 4BVyNk1Clfz9sW9; Tue, 18 Aug 2020 14:19:34 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gibson.dropbear.id.au; s=201602; t=1597724374; bh=tbf7e1/8oTfJM2oleGmsFgOKdsRYrI6dXLzRHANsedE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=mv89DSD38TtEn6mNGtTM+MtZq84NbMqrFRCpc6ERO1qyZ8Dc2xI/K6IUCfOoLz/ml Pur4HANIv++shCji25JGPygoRQLPX4t/4fYLS4SFMaB9/nYfoeqZ+SY6D6De1aa25W CKa9k2zfAyJZ/5DnA9VD+qEihAfVUpgv8w8dFrSY= From: David Gibson To: peter.maydell@linaro.org, groug@kaod.org Subject: [PULL 39/40] nvram: Exit QEMU if NVRAM cannot contain all -prom-env data Date: Tue, 18 Aug 2020 14:19:21 +1000 Message-Id: <20200818041922.251708-40-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200818041922.251708-1-david@gibson.dropbear.id.au> References: <20200818041922.251708-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.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; Received-SPF: pass client-ip=203.11.71.1; envelope-from=dgibson@ozlabs.org; helo=ozlabs.org X-detected-operating-system: by eggs.gnu.org: First seen = 2020/08/18 00:19:26 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] X-Spam_score_int: -9 X-Spam_score: -1.0 X-Spam_bar: - X-Spam_report: (-1.0 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=1, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, URIBL_BLOCKED=0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: John Snow , David Gibson , qemu-ppc@nongnu.org, qemu-devel@nongnu.org, Laurent Vivier Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" From: Greg Kurz Since commit 61f20b9dc5b7 ("spapr_nvram: Pre-initialize the NVRAM to support the -prom-env parameter"), pseries machines can pre-initialize the "system" partition in the NVRAM with the data passed to all -prom-env parameters on the QEMU command line. In this case it is assumed that all the data fits in 64 KiB, but the user can easily pass more and crash QEMU: $ qemu-system-ppc64 -M pseries $(for ((x=3D0;x<128;x++)); do \ echo -n " -prom-env " ; printf "%0.sx" {1..1024}; \ done) # this requires ~128 Kib malloc(): corrupted top size Aborted (core dumped) This happens because we don't check if all the prom-env data fits in the NVRAM and chrp_nvram_set_var() happily memcpy() it passed the buffer. This crash affects basically all ppc/ppc64 machine types that use -prom-env: - pseries (all versions) - g3beige - mac99 and also sparc/sparc64 machine types: - LX - SPARCClassic - SPARCbook - SS-10 - SS-20 - SS-4 - SS-5 - SS-600MP - Voyager - sun4u - sun4v Add a max_len argument to chrp_nvram_create_system_partition() so that it can check the available size before writing to memory. Since NVRAM is populated at machine init, it seems reasonable to consider this error as fatal. So, instead of reporting an error when we detect that the NVRAM is too small and adapt all machine types to handle it, we simply exit QEMU in all cases. This is still better than crashing. If someone wants another behavior, I guess this can be reworked later. Tested with: $ yes q | \ (for arch in ppc ppc64 sparc sparc64; do \ echo =3D=3D $arch =3D=3D; \ qemu=3D${arch}-softmmu/qemu-system-$arch; \ for mach in $($qemu -M help | awk '! /^Supported/ { print $1 }'); do= \ echo $mach; \ $qemu -M $mach -monitor stdio -nodefaults -nographic \ $(for ((x=3D0;x<128;x++)); do \ echo -n " -prom-env " ; printf "%0.sx" {1..1024}; \ done) >/dev/null; \ done; echo; \ done) Without the patch, affected machine types cause QEMU to report some memory corruption and crash: malloc(): corrupted top size free(): invalid size *** stack smashing detected ***: terminated With the patch, QEMU prints the following message and exits: NVRAM is too small. Try to pass less data to -prom-env It seems that the conditions for the crash have always existed, but it affects pseries, the machine type I care for, since commit 61f20b9dc5b7 only. Fixes: 61f20b9dc5b7 ("spapr_nvram: Pre-initialize the NVRAM to support the = -prom-env parameter") RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=3D1867739 Reported-by: John Snow Reviewed-by: Laurent Vivier Signed-off-by: Greg Kurz Message-Id: <159736033937.350502.12402444542194031035.stgit@bahia.lan> Signed-off-by: David Gibson --- hw/nvram/chrp_nvram.c | 24 +++++++++++++++++++++--- hw/nvram/mac_nvram.c | 2 +- hw/nvram/spapr_nvram.c | 3 ++- hw/sparc/sun4m.c | 2 +- hw/sparc64/sun4u.c | 2 +- include/hw/nvram/chrp_nvram.h | 3 ++- 6 files changed, 28 insertions(+), 8 deletions(-) diff --git a/hw/nvram/chrp_nvram.c b/hw/nvram/chrp_nvram.c index d969f26704..d4d10a7c03 100644 --- a/hw/nvram/chrp_nvram.c +++ b/hw/nvram/chrp_nvram.c @@ -21,14 +21,21 @@ =20 #include "qemu/osdep.h" #include "qemu/cutils.h" +#include "qemu/error-report.h" #include "hw/nvram/chrp_nvram.h" #include "sysemu/sysemu.h" =20 -static int chrp_nvram_set_var(uint8_t *nvram, int addr, const char *str) +static int chrp_nvram_set_var(uint8_t *nvram, int addr, const char *str, + int max_len) { int len; =20 len =3D strlen(str) + 1; + + if (max_len < len) { + return -1; + } + memcpy(&nvram[addr], str, len); =20 return addr + len; @@ -38,19 +45,26 @@ static int chrp_nvram_set_var(uint8_t *nvram, int addr,= const char *str) * Create a "system partition", used for the Open Firmware * environment variables. */ -int chrp_nvram_create_system_partition(uint8_t *data, int min_len) +int chrp_nvram_create_system_partition(uint8_t *data, int min_len, int max= _len) { ChrpNvramPartHdr *part_header; unsigned int i; int end; =20 + if (max_len < sizeof(*part_header)) { + goto fail; + } + part_header =3D (ChrpNvramPartHdr *)data; part_header->signature =3D CHRP_NVPART_SYSTEM; pstrcpy(part_header->name, sizeof(part_header->name), "system"); =20 end =3D sizeof(ChrpNvramPartHdr); for (i =3D 0; i < nb_prom_envs; i++) { - end =3D chrp_nvram_set_var(data, end, prom_envs[i]); + end =3D chrp_nvram_set_var(data, end, prom_envs[i], max_len - end); + if (end =3D=3D -1) { + goto fail; + } } =20 /* End marker */ @@ -65,6 +79,10 @@ int chrp_nvram_create_system_partition(uint8_t *data, in= t min_len) chrp_nvram_finish_partition(part_header, end); =20 return end; + +fail: + error_report("NVRAM is too small. Try to pass less data to -prom-env"); + exit(EXIT_FAILURE); } =20 /** diff --git a/hw/nvram/mac_nvram.c b/hw/nvram/mac_nvram.c index beec1c4e4d..11f2d31cdb 100644 --- a/hw/nvram/mac_nvram.c +++ b/hw/nvram/mac_nvram.c @@ -141,7 +141,7 @@ static void pmac_format_nvram_partition_of(MacIONVRAMSt= ate *nvr, int off, =20 /* OpenBIOS nvram variables partition */ sysp_end =3D chrp_nvram_create_system_partition(&nvr->data[off], - DEF_SYSTEM_SIZE) + off; + DEF_SYSTEM_SIZE, len) + = off; =20 /* Free space partition */ chrp_nvram_create_free_partition(&nvr->data[sysp_end], len - sysp_end); diff --git a/hw/nvram/spapr_nvram.c b/hw/nvram/spapr_nvram.c index 15d08281d4..386513499f 100644 --- a/hw/nvram/spapr_nvram.c +++ b/hw/nvram/spapr_nvram.c @@ -188,7 +188,8 @@ static void spapr_nvram_realize(SpaprVioDevice *dev, Er= ror **errp) } } else if (nb_prom_envs > 0) { /* Create a system partition to pass the -prom-env variables */ - chrp_nvram_create_system_partition(nvram->buf, MIN_NVRAM_SIZE / 4); + chrp_nvram_create_system_partition(nvram->buf, MIN_NVRAM_SIZE / 4, + nvram->size); chrp_nvram_create_free_partition(&nvram->buf[MIN_NVRAM_SIZE / 4], nvram->size - MIN_NVRAM_SIZE / 4); } diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c index 9be930415f..cf7dfa4af5 100644 --- a/hw/sparc/sun4m.c +++ b/hw/sparc/sun4m.c @@ -143,7 +143,7 @@ static void nvram_init(Nvram *nvram, uint8_t *macaddr, memset(image, '\0', sizeof(image)); =20 /* OpenBIOS nvram variables partition */ - sysp_end =3D chrp_nvram_create_system_partition(image, 0); + sysp_end =3D chrp_nvram_create_system_partition(image, 0, 0x1fd0); =20 /* Free space partition */ chrp_nvram_create_free_partition(&image[sysp_end], 0x1fd0 - sysp_end); diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c index 9e30203dcc..37310b73e6 100644 --- a/hw/sparc64/sun4u.c +++ b/hw/sparc64/sun4u.c @@ -136,7 +136,7 @@ static int sun4u_NVRAM_set_params(Nvram *nvram, uint16_= t NVRAM_size, memset(image, '\0', sizeof(image)); =20 /* OpenBIOS nvram variables partition */ - sysp_end =3D chrp_nvram_create_system_partition(image, 0); + sysp_end =3D chrp_nvram_create_system_partition(image, 0, 0x1fd0); =20 /* Free space partition */ chrp_nvram_create_free_partition(&image[sysp_end], 0x1fd0 - sysp_end); diff --git a/include/hw/nvram/chrp_nvram.h b/include/hw/nvram/chrp_nvram.h index 09941a9be4..4a0f5c21b8 100644 --- a/include/hw/nvram/chrp_nvram.h +++ b/include/hw/nvram/chrp_nvram.h @@ -50,7 +50,8 @@ chrp_nvram_finish_partition(ChrpNvramPartHdr *header, uin= t32_t size) header->checksum =3D sum & 0xff; } =20 -int chrp_nvram_create_system_partition(uint8_t *data, int min_len); +/* chrp_nvram_create_system_partition() failure is fatal */ +int chrp_nvram_create_system_partition(uint8_t *data, int min_len, int max= _len); int chrp_nvram_create_free_partition(uint8_t *data, int len); =20 #endif --=20 2.26.2