diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2010-05-26 08:25:51 +0100 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2010-05-26 08:25:51 +0100 |
commit | e8bd7b2d8a0b3becdea25e36c8f96de540906371 (patch) | |
tree | 868df6397f1d8e0b0447cabbe120812d0090f064 | |
parent | 337d8434a40376e9de06d8bec139f048ae522080 (diff) | |
download | xen-e8bd7b2d8a0b3becdea25e36c8f96de540906371.tar.gz xen-e8bd7b2d8a0b3becdea25e36c8f96de540906371.tar.bz2 xen-e8bd7b2d8a0b3becdea25e36c8f96de540906371.zip |
hvm: Handle extreme wallclock offsets safely.
When a VM's wallclock offset is negative enough, gmtime() can be
called
with an underflowed uint64, which it then tries to divide into years
by subtraction. Handle the input as a 40-bit signed integer instead.
Signed-off-by: Tim Deegan <Tim.Deegan@citrix.com>
xen-unstable changeset: 21452:459f35d8cac4
xen-unstable date: Wed May 26 07:59:52 2010 +0100
-rw-r--r-- | xen/common/time.c | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/xen/common/time.c b/xen/common/time.c index 9072fc8386..d326f334cf 100644 --- a/xen/common/time.c +++ b/xen/common/time.c @@ -42,6 +42,18 @@ struct tm gmtime(unsigned long t) int y; const unsigned short int *ip; + y = 1970; +#ifdef __x86_64__ + /* Allow the concept of time before 1970. 64-bit only; for 32-bit + * time after 2038 seems more important than time before 1970. */ + while ( t & (1UL<<39) ) + { + y -= 400; + t += ((unsigned long)(365 * 303 + 366 * 97)) * SECS_PER_DAY; + } + t &= (1UL << 40) - 1; +#endif + days = t / SECS_PER_DAY; rem = t % SECS_PER_DAY; @@ -53,7 +65,6 @@ struct tm gmtime(unsigned long t) tbuf.tm_wday = (4 + days) % 7; if ( tbuf.tm_wday < 0 ) tbuf.tm_wday += 7; - y = 1970; while ( days >= (rem = __isleap(y) ? 366 : 365) ) { ++y; |