From patchwork Thu Dec 1 18:37:17 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 5423 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id BE51423E03 for ; Thu, 1 Dec 2011 18:37:21 +0000 (UTC) Received: from mail-lpp01m010-f52.google.com (mail-lpp01m010-f52.google.com [209.85.215.52]) by fiordland.canonical.com (Postfix) with ESMTP id A3008A18670 for ; Thu, 1 Dec 2011 18:37:21 +0000 (UTC) Received: by mail-lpp01m010-f52.google.com with SMTP id h2so1227474laa.11 for ; Thu, 01 Dec 2011 10:37:21 -0800 (PST) Received: by 10.152.111.170 with SMTP id ij10mr5589121lab.5.1322764641544; Thu, 01 Dec 2011 10:37:21 -0800 (PST) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.152.41.198 with SMTP id h6cs80012lal; Thu, 1 Dec 2011 10:37:21 -0800 (PST) Received: by 10.181.13.84 with SMTP id ew20mr5508238wid.58.1322764639788; Thu, 01 Dec 2011 10:37:19 -0800 (PST) Received: from mnementh.archaic.org.uk (mnementh.archaic.org.uk. [81.2.115.146]) by mx.google.com with ESMTPS id m20si2482854wbh.146.2011.12.01.10.37.19 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 01 Dec 2011 10:37:19 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 81.2.115.146 as permitted sender) client-ip=81.2.115.146; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 81.2.115.146 as permitted sender) smtp.mail=pm215@archaic.org.uk Received: from pm215 by mnementh.archaic.org.uk with local (Exim 4.72) (envelope-from ) id 1RWBVV-00047Z-0x; Thu, 01 Dec 2011 18:37:17 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Cc: patches@linaro.org Subject: [PATCH] hw/arm_gic.c: Ignore attempts to complete nonexistent IRQs Date: Thu, 1 Dec 2011 18:37:17 +0000 Message-Id: <1322764637-15818-1-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 1.7.2.5 Ignore attempts to complete non-existent IRQs; this fixes a buffer overrun if the guest writes a bad value to the GICC_EOIR register. (This case is UNPREDICTABLE so ignoring it is a valid choice.) Note that doing nothing if the guest writes 1023 to this register is not in fact a change in behaviour: the old code would also always do nothing in this case but in a non-obvious way. (The buffer overrun was noted by Coverity, see bug 887883.) Signed-off-by: Peter Maydell --- It looks to me as if Coverity is being alarmist about the other alleged static overruns in this file... hw/arm_gic.c | 27 ++++++++++++++++++--------- 1 files changed, 18 insertions(+), 9 deletions(-) diff --git a/hw/arm_gic.c b/hw/arm_gic.c index f3f3516..527c9ce 100644 --- a/hw/arm_gic.c +++ b/hw/arm_gic.c @@ -215,17 +215,26 @@ static void gic_complete_irq(gic_state * s, int cpu, int irq) int update = 0; int cm = 1 << cpu; DPRINTF("EOI %d\n", irq); + if (irq >= GIC_NIRQ) { + /* This handles two cases: + * 1. If software writes the ID of a spurious interrupt [ie 1023] + * to the GICC_EOIR, the GIC ignores that write. + * 2. If software writes the number of a non-existent interrupt + * this must be a subcase of "value written does not match the last + * valid interrupt value read from the Interrupt Acknowledge + * register" and so this is UNPREDICTABLE. We choose to ignore it. + */ + return; + } if (s->running_irq[cpu] == 1023) return; /* No active IRQ. */ - if (irq != 1023) { - /* Mark level triggered interrupts as pending if they are still - raised. */ - if (!GIC_TEST_TRIGGER(irq) && GIC_TEST_ENABLED(irq, cm) - && GIC_TEST_LEVEL(irq, cm) && (GIC_TARGET(irq) & cm) != 0) { - DPRINTF("Set %d pending mask %x\n", irq, cm); - GIC_SET_PENDING(irq, cm); - update = 1; - } + /* Mark level triggered interrupts as pending if they are still + raised. */ + if (!GIC_TEST_TRIGGER(irq) && GIC_TEST_ENABLED(irq, cm) + && GIC_TEST_LEVEL(irq, cm) && (GIC_TARGET(irq) & cm) != 0) { + DPRINTF("Set %d pending mask %x\n", irq, cm); + GIC_SET_PENDING(irq, cm); + update = 1; } if (irq != s->running_irq[cpu]) { /* Complete an IRQ that is not currently running. */