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
next prev parent 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).