All of lore.kernel.org
 help / color / mirror / Atom feed
From: Paolo Bonzini <pbonzini@redhat.com>
To: qemu-devel@nongnu.org
Cc: David Gibson <david@gibson.dropbear.id.au>
Subject: [Qemu-devel] [PULL 04/14] i6300esb: Fix signed integer overflow
Date: Thu, 26 Mar 2015 17:02:24 +0100	[thread overview]
Message-ID: <1427385754-13012-5-git-send-email-pbonzini@redhat.com> (raw)
In-Reply-To: <1427385754-13012-1-git-send-email-pbonzini@redhat.com>

From: David Gibson <david@gibson.dropbear.id.au>

If the guest programs a sufficiently large timeout value an integer
overflow can occur in i6300esb_restart_timer().  e.g. if the maximum
possible timer preload value of 0xfffff is programmed then we end up with
the calculation:

timeout = get_ticks_per_sec() * (0xfffff << 15) / 33000000;

get_ticks_per_sec() returns 1000000000 (10^9) giving:

     10^9 * (0xfffff * 2^15) == 0x1dcd632329b000000 (65 bits)

Obviously the division by 33MHz brings it back under 64-bits, but the
overflow has already occurred.

Since signed integer overflow has undefined behaviour in C, in theory this
could be arbitrarily bad.  In practice, the overflowed value wraps around
to something negative, causing the watchdog to immediately expire, killing
the guest, which is still fairly bad.

The bug can be triggered by running a Linux guest, loading the i6300esb
driver with parameter "heartbeat=2046" and opening /dev/watchdog.  The
watchdog will trigger as soon as the device is opened.

This patch corrects the problem by using muldiv64(), which effectively
allows a 128-bit intermediate value between the multiplication and
division.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Message-Id: <1427075508-12099-3-git-send-email-david@gibson.dropbear.id.au>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/watchdog/wdt_i6300esb.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/hw/watchdog/wdt_i6300esb.c b/hw/watchdog/wdt_i6300esb.c
index e694fa9..4ebdbb8 100644
--- a/hw/watchdog/wdt_i6300esb.c
+++ b/hw/watchdog/wdt_i6300esb.c
@@ -125,8 +125,14 @@ static void i6300esb_restart_timer(I6300State *d, int stage)
     else
         timeout <<= 5;
 
-    /* Get the timeout in units of ticks_per_sec. */
-    timeout = get_ticks_per_sec() * timeout / 33000000;
+    /* Get the timeout in units of ticks_per_sec.
+     *
+     * ticks_per_sec is typically 10^9 == 0x3B9ACA00 (30 bits), with
+     * 20 bits of user supplied preload, and 15 bits of scale, the
+     * multiply here can exceed 64-bits, before we divide by 33MHz, so
+     * we use a higher-precision intermediate result.
+     */
+    timeout = muldiv64(get_ticks_per_sec(), timeout, 33000000);
 
     i6300esb_debug("stage %d, timeout %" PRIi64 "\n", d->stage, timeout);
 
-- 
2.3.3

  parent reply	other threads:[~2015-03-26 16:02 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-03-26 16:02 [Qemu-devel] [PULL 00/14] Misc bugfixes for 2.3.0-rc2 Paolo Bonzini
2015-03-26 16:02 ` [Qemu-devel] [PULL 01/14] rcu tests: fix compilation on 32-bit ppc Paolo Bonzini
2015-03-26 16:02 ` [Qemu-devel] [PULL 02/14] fw_cfg: factor out initialization of FW_CFG_ID (rev. number) Paolo Bonzini
2015-03-26 16:02 ` [Qemu-devel] [PULL 03/14] i6300esb: Correct endiannness Paolo Bonzini
2015-03-26 16:02 ` Paolo Bonzini [this message]
2015-03-26 16:02 ` [Qemu-devel] [PULL 05/14] cpus: Don't kick un-realized cpus Paolo Bonzini
2015-03-26 16:02 ` [Qemu-devel] [PULL 06/14] megasas: use PCI DMA APIs Paolo Bonzini
2015-03-26 16:02 ` [Qemu-devel] [PULL 07/14] vmw_pvscsi: " Paolo Bonzini
2015-03-26 16:02 ` [Qemu-devel] [PULL 08/14] nbd: Fix up comment after commit e140177 Paolo Bonzini
2015-03-26 16:02 ` [Qemu-devel] [PULL 09/14] m68k: memory: Replace memory_region_init_ram with memory_region_allocate_system_memory Paolo Bonzini
2015-03-26 16:02 ` [Qemu-devel] [PULL 10/14] mips: " Paolo Bonzini
2015-03-26 16:02 ` [Qemu-devel] [PULL 11/14] sparc: " Paolo Bonzini
2015-03-26 16:02 ` [Qemu-devel] [PULL 12/14] exec: avoid possible overwriting of mmaped area in qemu_ram_remap Paolo Bonzini
2015-03-26 16:02 ` [Qemu-devel] [PULL 13/14] misc: fix typos in copyright declaration Paolo Bonzini
2015-03-26 16:02 ` [Qemu-devel] [PULL 14/14] virtio-scsi-dataplane: fix memory leak for VirtIOSCSIVring Paolo Bonzini
2015-03-26 18:34 ` [Qemu-devel] [PULL 00/14] Misc bugfixes for 2.3.0-rc2 Peter Maydell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1427385754-13012-5-git-send-email-pbonzini@redhat.com \
    --to=pbonzini@redhat.com \
    --cc=david@gibson.dropbear.id.au \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.