qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH for-2.2] qemu-timer: Avoid overflows when conver


From: Fam Zheng
Subject: Re: [Qemu-devel] [PATCH for-2.2] qemu-timer: Avoid overflows when converting timeout to struct timespec
Date: Wed, 26 Nov 2014 11:09:25 +0800
User-agent: Mutt/1.5.23 (2014-03-12)

On Tue, 11/25 18:21, Peter Maydell wrote:
> In qemu_poll_ns(), when we convert an int64_t nanosecond timeout into
> a struct timespec, we may accidentally run into overflow problems if
> the timeout is very long. This happens because the tv_sec field is a
> time_t, which is signed, so we might end up setting it to a negative
> value by mistake. This will result in what was intended to be a
> near-infinite timeout turning into an instantaneous timeout, and we'll
> busy loop. Cap the maximum timeout at INT32_MAX seconds (about 68 years)
> to avoid this problem.
> 
> This specifically manifested on ARM hosts as an extreme slowdown on
> guest shutdown (when the guest reprogrammed the PL031 RTC to not
> generate alarms using a very long timeout) but could happen on other
> hosts and guests too.
> 
> Reported-by: Christoffer Dall <address@hidden>
> Signed-off-by: Peter Maydell <address@hidden>
> ---
> It's not quite clear why this only causes problems in some KVM
> configurations -- presumably in the others we complete the guest
> shutdown reasonably quickly without the busy-waiting QEMU thread
> interfering, but in some setups, notably on TC2 host, we go into
> an extreme slowdown printing out the final bits of the guest shutdown
> to its serial port. Given that (and given that I think this is fairly
> safe) I'd like to get this into 2.2 if possible...
> 
>  qemu-timer.c | 9 ++++++++-
>  1 file changed, 8 insertions(+), 1 deletion(-)
> 
> diff --git a/qemu-timer.c b/qemu-timer.c
> index 00a5d35..c77de64 100644
> --- a/qemu-timer.c
> +++ b/qemu-timer.c
> @@ -314,7 +314,14 @@ int qemu_poll_ns(GPollFD *fds, guint nfds, int64_t 
> timeout)
>          return ppoll((struct pollfd *)fds, nfds, NULL, NULL);
>      } else {
>          struct timespec ts;
> -        ts.tv_sec = timeout / 1000000000LL;
> +        int64_t tvsec = timeout / 1000000000LL;
> +        /* Avoid possibly overflowing and specifying a negative number of
> +         * seconds, which would turn a very long timeout into a busy-wait.
> +         */
> +        if (tvsec > (int64_t)INT32_MAX) {
> +            tvsec = INT32_MAX;
> +        }
> +        ts.tv_sec = tvsec;
>          ts.tv_nsec = timeout % 1000000000LL;
>          return ppoll((struct pollfd *)fds, nfds, &ts, NULL);
>      }
> -- 
> 1.9.1
> 
> 

Reviewed-by: Fam Zheng <address@hidden>



reply via email to

[Prev in Thread] Current Thread [Next in Thread]