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

[xen staging] evtchn/FIFO: re-order and synchronize (with) map_control_block()



commit c5e63651fdc706954d920a2d98f74f4a21b46a7e
Author:     Jan Beulich <jbeulich@xxxxxxxx>
AuthorDate: Tue Dec 15 13:46:37 2020 +0100
Commit:     Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Tue Dec 15 13:46:37 2020 +0100

    evtchn/FIFO: re-order and synchronize (with) map_control_block()
    
    For evtchn_fifo_set_pending()'s check of the control block having been
    set to be effective, ordering of respective reads and writes needs to be
    ensured: The control block pointer needs to be recorded strictly after
    the setting of all the queue heads, and it needs checking strictly
    before any uses of them (this latter aspect was already guaranteed).
    
    This is XSA-358 / CVE-2020-29570.
    
    Reported-by: Julien Grall <jgrall@xxxxxxxxxx>
    Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
    Acked-by: Julien Grall <jgrall@xxxxxxxxxx>
---
 xen/common/event_fifo.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/xen/common/event_fifo.c b/xen/common/event_fifo.c
index 3310dc00d7..2fb01b82db 100644
--- a/xen/common/event_fifo.c
+++ b/xen/common/event_fifo.c
@@ -252,6 +252,10 @@ static void evtchn_fifo_set_pending(struct vcpu *v, struct 
evtchn *evtchn)
      * Link the event if it unmasked and not already linked.
      */
     if ( !guest_test_bit(d, EVTCHN_FIFO_MASKED, word) &&
+         /*
+          * This also acts as the read counterpart of the smp_wmb() in
+          * map_control_block().
+          */
          !guest_test_and_set_bit(d, EVTCHN_FIFO_LINKED, word) )
     {
         /*
@@ -478,6 +482,7 @@ static int setup_control_block(struct vcpu *v)
 static int map_control_block(struct vcpu *v, uint64_t gfn, uint32_t offset)
 {
     void *virt;
+    struct evtchn_fifo_control_block *control_block;
     unsigned int i;
     int rc;
 
@@ -488,10 +493,15 @@ static int map_control_block(struct vcpu *v, uint64_t 
gfn, uint32_t offset)
     if ( rc < 0 )
         return rc;
 
-    v->evtchn_fifo->control_block = virt + offset;
+    control_block = virt + offset;
 
     for ( i = 0; i <= EVTCHN_FIFO_PRIORITY_MIN; i++ )
-        v->evtchn_fifo->queue[i].head = 
&v->evtchn_fifo->control_block->head[i];
+        v->evtchn_fifo->queue[i].head = &control_block->head[i];
+
+    /* All queue heads must have been set before setting the control block. */
+    smp_wmb();
+
+    v->evtchn_fifo->control_block = control_block;
 
     return 0;
 }
--
generated by git-patchbot for /home/xen/git/xen.git#staging



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.