evtchn/fifo: don't spin indefinitely when setting LINK
authorDavid Vrabel <david.vrabel@citrix.com>
Tue, 12 Nov 2013 12:19:25 +0000 (13:19 +0100)
committerJan Beulich <jbeulich@suse.com>
Tue, 12 Nov 2013 12:19:25 +0000 (13:19 +0100)
commitdae2a1c5f9372be1b5d1e734ad3e51f67a1221aa
tree76dfeed727553f881b09b0d827691747d489fa70
parent58929248461ecadce13e92eb5a5d9ef718a7c88e
evtchn/fifo: don't spin indefinitely when setting LINK

A malicious or buggy guest can cause another domain to spin
indefinitely by repeatedly writing to an event word when the other
guest 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 change to the ABI which is documented in draft
H of the design.

  http://xenbits.xen.org/people/dvrabel/event-channels-H.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
specify that it is not valid for a guest to clear MASKED if Xen is
trying to update LINK.  Indicate this to the guest with an additional
BUSY bit in the event word.  The guest must not clear MASKED if BUSY
is set and it should spin until BUSY is cleared.

The remaining valid writes (clear LINKED, clear PENDING, set MASKED,
clear MASKED by Xen) will limit the number of failures of the
cmpxchg() to at most 4.  A clear of LINKED will also terminate the
loop early. Therefore, the loop can then be limited to at most 4
iterations.

If the buggy or malicious guest does cause the loop to exit with
LINKED set and LINK unset then that buggy guest will lose events.

Reported-by: Anthony Liguori <aliguori@amazon.com>
Signed-off-by: David Vrabel <david.vrabel@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
xen/common/event_fifo.c
xen/include/public/event_channel.h