[libvirt] [PATCH] event: fix two event-handling bugs

Daniel Veillard veillard at redhat.com
Fri Jan 21 06:09:07 UTC 2011


On Thu, Jan 20, 2011 at 05:01:13PM -0700, Eric Blake wrote:
> Regression introduced in commit e6b68d7.
> 
> Prior to that point, handlesAlloc was always a multiple of
> EVENT_ALLOC_EXTENT, and was an integer (so even if the
> subtraction wrapped, a negative value was less than the
> count and did not try to free the handles array).  But after
> that point, VIR_RESIZE_N made handlesAlloc grow geometrically,
> so handlesAlloc could be 49 when handlesCount was 47, while
> still freeing off only 10 at a time, and eventually reach
> handlesAlloc 7 and handlesCount 1.  Since (size_t)(7 - 10) is
> indeed greater than 1, this then tried to free 10 elements,
> which had the awful effect of nuking the handles array while
> there were still live handles.
> 
> Which leads to crashes like this:
> https://bugzilla.redhat.com/show_bug.cgi?id=670848
> 
> * daemon/event.c (virEventDispatchHandles): Cache watch while the
> lock is still held, as eventLoop.handles might be relocated
> outside the lock.
> (virEventCleanupHandles): Avoid integer wrap-around causing us to
> delete the entire handles array while handles are still active.
> ---
> 
> Thanks to Dave Allan for letting me use his faqemu setup for testing
> this.  Basically, starting 60 faqemu followed by stopping them all
> was a reliable way to trigger the handle cleanup integer wraparound.
> 
>  daemon/event.c |   12 +++++++-----
>  1 files changed, 7 insertions(+), 5 deletions(-)
> 
> diff --git a/daemon/event.c b/daemon/event.c
> index 89ca9f0..9cad466 100644
> --- a/daemon/event.c
> +++ b/daemon/event.c
> @@ -1,7 +1,7 @@
>  /*
>   * event.c: event loop for monitoring file handles
>   *
> - * Copyright (C) 2007, 2010 Red Hat, Inc.
> + * Copyright (C) 2007, 2010-2011 Red Hat, Inc.
>   * Copyright (C) 2007 Daniel P. Berrange
>   *
>   * This library is free software; you can redistribute it and/or
> @@ -435,6 +435,7 @@ static int virEventDispatchTimeouts(void) {
>   */
>  static int virEventDispatchHandles(int nfds, struct pollfd *fds) {
>      int i, n;
> +    int watch;
>      DEBUG("Dispatch %d", nfds);
> 
>      /* NB, use nfds not eventLoop.handlesCount, because new
> @@ -463,9 +464,9 @@ static int virEventDispatchHandles(int nfds, struct pollfd *fds) {
>              EVENT_DEBUG("Dispatch n=%d f=%d w=%d e=%d %p", i,
>                          fds[n].fd, eventLoop.handles[i].watch,
>                          fds[n].revents, eventLoop.handles[i].opaque);
> +            watch = eventLoop.handles[i].watch;
>              virMutexUnlock(&eventLoop.lock);
> -            (cb)(eventLoop.handles[i].watch,
> -                 fds[n].fd, hEvents, opaque);
> +            (cb)(watch, fds[n].fd, hEvents, opaque);
>              virMutexLock(&eventLoop.lock);
>          }
>      }
> @@ -542,9 +543,10 @@ static int virEventCleanupHandles(void) {
>      }
> 
>      /* Release some memory if we've got a big chunk free */
> -    if ((eventLoop.handlesAlloc - EVENT_ALLOC_EXTENT) > eventLoop.handlesCount) {
> +    if (eventLoop.handlesAlloc - eventLoop.handlesCount > EVENT_ALLOC_EXTENT) {
>          EVENT_DEBUG("Releasing %zu out of %zu handles slots used, releasing %d",
> -                   eventLoop.handlesCount, eventLoop.handlesAlloc, EVENT_ALLOC_EXTENT);
> +                    eventLoop.handlesCount, eventLoop.handlesAlloc,
> +                    EVENT_ALLOC_EXTENT);
>          VIR_SHRINK_N(eventLoop.handles, eventLoop.handlesAlloc,
>                       EVENT_ALLOC_EXTENT);
>      }

  ACK, fairly nasty !

   thanks for chasing this down !

Daniel

-- 
Daniel Veillard      | libxml Gnome XML XSLT toolkit  http://xmlsoft.org/
daniel at veillard.com  | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library  http://libvirt.org/




More information about the libvir-list mailing list