xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Boris Ostrovsky <boris.ostrovsky@oracle.com>
To: David Vrabel <david.vrabel@citrix.com>
Cc: Keir Fraser <keir@xen.org>, Jan Beulich <jan.beulich@suse.com>,
	xen-devel@lists.xen.org
Subject: Re: [PATCH 3/3] evtchn/fifo: don't spin indefinitely when setting LINK
Date: Thu, 31 Oct 2013 14:13:34 -0400	[thread overview]
Message-ID: <52729DCE.6010504@oracle.com> (raw)
In-Reply-To: <1383231791-4604-4-git-send-email-david.vrabel@citrix.com>

On 10/31/2013 11:03 AM, David Vrabel wrote:
> From: David Vrabel <david.vrabel@citrix.com>
>
> A malicious or buggy guest can cause another domain to spin
> indefinitely by repeatedly writing to an event word when the other
> domain is trying to link a new event.  The cmpxchg() in
> evtchn_fifo_set_link() will repeatedly fail and the loop may never
> terminate.
>
> Fixing this requires a minor change to the ABI, which is documented in
> draft G of the design.
>
> http://xenbits.xen.org/people/dvrabel/event-channels-G.pdf
>
> Since a well-behaved guest only makes a limited set of state changes,
> the loop can terminate early if the guest makes an invalid state
> transition.
>
> The guest may:
>
> - clear LINKED and link
> - clear PENDING
> - set MASKED
> - clear MASKED
>
> It is valid for the guest to mask and unmask an event at any time so
> we specify that it is not valid for a guest to clear MASKED if the
> event is the tail of a queue (i.e., LINKED is set and LINK is clear).
> Instead, the guest must make an EVCHNOP_unmask hypercall to unmask the
> event.
>
> The hypercall ensures that UNMASKED isn't cleared on a tail event
> whose LINK field is being set by holding the appropriate queue lock.
>
> The remaining valid writes (clear LINKED, clear PENDING, set MASKED)
> will limit the number of failures of the cmpxchg() to at most 3.  A
> clear of LINKED will also terminate the loop early (as before).
> Therefore, the loop can then be limited to at most 3 iterations.
>
> If the buggy or malicious guest does cause the loop to exit early, the
> newly pending event will be unreachable by the guest and it and
> subsequent events may be lost.
>
> Signed-off-by: David Vrabel <david.vrabel@citrix.com>
> ---
>   xen/common/event_fifo.c |   19 +++++++++++++++++--
>   xen/include/xen/sched.h |    3 +++
>   2 files changed, 20 insertions(+), 2 deletions(-)
>
> diff --git a/xen/common/event_fifo.c b/xen/common/event_fifo.c
> index 64dbfff..6cf30ec 100644
> --- a/xen/common/event_fifo.c
> +++ b/xen/common/event_fifo.c
> @@ -37,6 +37,7 @@ static inline event_word_t *evtchn_fifo_word_from_port(struct domain *d,
>   static bool_t evtchn_fifo_set_link(event_word_t *word, uint32_t link)
>   {
>       event_word_t n, o, w;
> +    unsigned int try = 3;
>   
>       w = *word;
>   
> @@ -45,7 +46,8 @@ static bool_t evtchn_fifo_set_link(event_word_t *word, uint32_t link)
>               return 0;
>           o = w;
>           n = (w & ~EVTCHN_FIFO_LINK_MASK) | link;
> -    } while ( (w = cmpxchg(word, o, n)) != o );
> +        w = cmpxchg(word, o, n);
> +    } while ( w != o && try-- );
>   
>       return 1;

Failure to set link here is an unexpected outcome, possibly indicating a 
malicious guest. Should you emit a (rate-limited) warning for this case?

-boris

>   }
> @@ -90,6 +92,8 @@ static void evtchn_fifo_set_pending(struct vcpu *v, struct evtchn *evtchn)
>           event_word_t *tail_word;
>           bool_t linked = 0;
>   
> +        evtchn->q = q;
> +
>           spin_lock_irqsave(&q->lock, flags);
>   
>           /*
> @@ -148,7 +152,18 @@ static void evtchn_fifo_unmask(struct domain *d, struct evtchn *evtchn)
>       if ( unlikely(!word) )
>           return;
>   
> -    clear_bit(EVTCHN_FIFO_MASKED, word);
> +    /*
> +     * If this event is on the tail of a queue, the queue lock must be
> +     * held to avoid clearing MASKED while setting LINK.
> +     */
> +    if ( evtchn->q && evtchn->q->tail == evtchn->port )
> +    {
> +        spin_lock_irq(&evtchn->q->lock);
> +        clear_bit(EVTCHN_FIFO_MASKED, word);
> +        spin_unlock_irq(&evtchn->q->lock);
> +    }
> +    else
> +        clear_bit(EVTCHN_FIFO_MASKED, word);
>   
>       /* Relink if pending. */
>       if ( test_bit(EVTCHN_FIFO_PENDING, word) )
> diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
> index 624ea15..7b0273a 100644
> --- a/xen/include/xen/sched.h
> +++ b/xen/include/xen/sched.h
> @@ -68,6 +68,8 @@ extern struct domain *dom0;
>   #define EVTCHNS_PER_GROUP  (BUCKETS_PER_GROUP * EVTCHNS_PER_BUCKET)
>   #define NR_EVTCHN_GROUPS   DIV_ROUND_UP(MAX_NR_EVTCHNS, EVTCHNS_PER_GROUP)
>   
> +struct evtchn_fifo_queue;
> +
>   struct evtchn
>   {
>   #define ECS_FREE         0 /* Channel is available for use.                  */
> @@ -98,6 +100,7 @@ struct evtchn
>       } u;
>       u8 priority;
>       u8 pending:1;
> +    struct evtchn_fifo_queue *q; /* Latest queue this event was on. */
>   #ifdef FLASK_ENABLE
>       void *ssid;
>   #endif

  reply	other threads:[~2013-10-31 18:13 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-10-31 15:03 [PATCHv2 0/3] Xen: FIFO-based event channel ABI fixes David Vrabel
2013-10-31 15:03 ` [PATCH 1/3] MAINTAINERS: Add FIFO-based event channel ABI maintainer David Vrabel
2013-11-04 14:29   ` Jan Beulich
2013-11-05 21:06     ` Keir Fraser
2013-11-06 11:49       ` David Vrabel
2013-11-06 12:40         ` Jan Beulich
2013-10-31 15:03 ` [PATCH 2/3] evtchn: don't lose pending state if FIFO event array page is missing David Vrabel
2013-11-04 14:29   ` Jan Beulich
2013-11-05 21:07     ` Keir Fraser
2013-10-31 15:03 ` [PATCH 3/3] evtchn/fifo: don't spin indefinitely when setting LINK David Vrabel
2013-10-31 18:13   ` Boris Ostrovsky [this message]
2013-11-04 14:39   ` Jan Beulich
2013-11-04 14:52     ` David Vrabel
2013-11-04 14:57       ` Jan Beulich
2013-11-04 16:30         ` David Vrabel
2013-11-05 14:18           ` Jan Beulich
2013-11-04 15:07       ` Ian Campbell
2013-11-04 15:11         ` David Vrabel
2013-11-05 14:19   ` Jan Beulich
2013-11-05 14:25   ` Jan Beulich
2013-11-06 13:38   ` David Vrabel
2013-11-06 15:01     ` Boris Ostrovsky
2013-11-06 15:07       ` David Vrabel
2013-11-10 21:21   ` Matt Wilson
2013-10-31 15:13 ` [PATCHv2 0/3] Xen: FIFO-based event channel ABI fixes David Vrabel

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=52729DCE.6010504@oracle.com \
    --to=boris.ostrovsky@oracle.com \
    --cc=david.vrabel@citrix.com \
    --cc=jan.beulich@suse.com \
    --cc=keir@xen.org \
    --cc=xen-devel@lists.xen.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).