]> xenbits.xensource.com Git - people/pauldu/xen.git/commitdiff
evtchn/sched: reject poll requests for unusable ports
authorJan Beulich <jbeulich@suse.com>
Wed, 30 Sep 2020 07:10:46 +0000 (09:10 +0200)
committerJan Beulich <jbeulich@suse.com>
Wed, 30 Sep 2020 07:10:46 +0000 (09:10 +0200)
Before and after XSA-342 there has been an asymmetry in how not really
usable ports get treated in do_poll(): Ones beyond a certain boundary
(max_evtchns originally, valid_evtchns subsequently) did get refused
with -EINVAL, while lower ones were accepted despite there potentially
being no way to wake the vCPU again from its polling state. Arrange to
also honor evtchn_usable() output in the decision.

Requested-by: Andrew Cooper <andrew.cooper3@citrix.com>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Julien Grall <jgrall@amazon.com>
Reviewed-by: Dario Faggioli <dfaggioli@suse.com>
Reviewed-by: Paul Durrant <paul@xen.org>
xen/common/sched/core.c
xen/include/xen/event.h

index ab94d2ec3aeec5f3dffe7ee5526a8b35ec2ce6fd..ed973e90ecf37baa592e82f9ae29e166d1d3057d 100644 (file)
@@ -1427,13 +1427,13 @@ static long do_poll(struct sched_poll *sched_poll)
         if ( __copy_from_guest_offset(&port, sched_poll->ports, i, 1) )
             goto out;
 
-        rc = -EINVAL;
-        if ( !port_is_valid(d, port) )
-            goto out;
-
-        rc = 0;
-        if ( evtchn_port_is_pending(d, port) )
+        rc = evtchn_port_poll(d, port);
+        if ( rc )
+        {
+            if ( rc > 0 )
+                rc = 0;
             goto out;
+        }
     }
 
     if ( sched_poll->nr_ports == 1 )
index fa93a3684a3d3172af27c061531eb6c91fd3a0b7..509d3ae861c2464e67f4813f37d3c699833f952e 100644 (file)
@@ -240,19 +240,6 @@ static inline bool evtchn_is_pending(const struct domain *d,
     return evtchn_usable(evtchn) && d->evtchn_port_ops->is_pending(d, evtchn);
 }
 
-static inline bool evtchn_port_is_pending(struct domain *d, evtchn_port_t port)
-{
-    struct evtchn *evtchn = evtchn_from_port(d, port);
-    bool rc;
-    unsigned long flags;
-
-    spin_lock_irqsave(&evtchn->lock, flags);
-    rc = evtchn_is_pending(d, evtchn);
-    spin_unlock_irqrestore(&evtchn->lock, flags);
-
-    return rc;
-}
-
 static inline bool evtchn_is_masked(const struct domain *d,
                                     const struct evtchn *evtchn)
 {
@@ -279,6 +266,25 @@ static inline bool evtchn_is_busy(const struct domain *d,
            d->evtchn_port_ops->is_busy(d, evtchn);
 }
 
+/* Returns negative errno, zero for not pending, or positive for pending. */
+static inline int evtchn_port_poll(struct domain *d, evtchn_port_t port)
+{
+    int rc = -EINVAL;
+
+    if ( port_is_valid(d, port) )
+    {
+        struct evtchn *evtchn = evtchn_from_port(d, port);
+        unsigned long flags;
+
+        spin_lock_irqsave(&evtchn->lock, flags);
+        if ( evtchn_usable(evtchn) )
+            rc = evtchn_is_pending(d, evtchn);
+        spin_unlock_irqrestore(&evtchn->lock, flags);
+    }
+
+    return rc;
+}
+
 static inline int evtchn_port_set_priority(struct domain *d,
                                            struct evtchn *evtchn,
                                            unsigned int priority)