summaryrefslogtreecommitdiffstats
path: root/pc-bios
diff options
context:
space:
mode:
authorDavid Gibson <david@gibson.dropbear.id.au>2015-03-23 12:51:48 +1100
committerPaolo Bonzini <pbonzini@redhat.com>2015-03-25 13:38:05 +0100
commit4bc7b4d56657ebf75b986ad46e959cf7232ff26a (patch)
tree36502da0c03cbc85d66a798cda119fe0ca6c0847 /pc-bios
parent06b82e2d8ead4d1f9441dbf2b03c31369a8f27bd (diff)
downloadhqemu-4bc7b4d56657ebf75b986ad46e959cf7232ff26a.zip
hqemu-4bc7b4d56657ebf75b986ad46e959cf7232ff26a.tar.gz
i6300esb: Fix signed integer overflow
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>
Diffstat (limited to 'pc-bios')
0 files changed, 0 insertions, 0 deletions
OpenPOWER on IntegriCloud